ummaya 0.2.4 → 0.2.6

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 (482) hide show
  1. package/README.md +15 -2
  2. package/bin/ummaya +10 -1
  3. package/bun.lock +180 -244
  4. package/npm-shrinkwrap.json +760 -1760
  5. package/package.json +39 -22
  6. package/prompts/manifest.yaml +1 -1
  7. package/prompts/system_v1.md +1 -0
  8. package/pyproject.toml +27 -2
  9. package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
  10. package/src/ummaya/_canonical/__init__.py +2 -0
  11. package/src/ummaya/_canonical/baselines.yaml +113 -0
  12. package/src/ummaya/engine/engine.py +29 -132
  13. package/src/ummaya/evidence/__init__.py +21 -2
  14. package/src/ummaya/evidence/dataset_contract.py +193 -0
  15. package/src/ummaya/evidence/document_authoring_cases.py +33 -0
  16. package/src/ummaya/evidence/document_harness.py +313 -0
  17. package/src/ummaya/evidence/document_viewer_ux.py +391 -0
  18. package/src/ummaya/evidence/gates.py +70 -0
  19. package/src/ummaya/evidence/json_types.py +20 -0
  20. package/src/ummaya/evidence/models.py +88 -1
  21. package/src/ummaya/evidence/output_payload.py +89 -0
  22. package/src/ummaya/evidence/payload_documents.py +233 -0
  23. package/src/ummaya/evidence/route_contracts.py +224 -0
  24. package/src/ummaya/evidence/route_helpers.py +150 -0
  25. package/src/ummaya/evidence/runner.py +81 -212
  26. package/src/ummaya/evidence/source_provenance.py +246 -0
  27. package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
  28. package/src/ummaya/evidence/tool_layer.py +39 -0
  29. package/src/ummaya/evidence/tool_layer_models.py +151 -0
  30. package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
  31. package/src/ummaya/ipc/document_intent_normalization.py +185 -0
  32. package/src/ummaya/ipc/frame_schema.py +5 -5
  33. package/src/ummaya/ipc/route_diagnostics.py +73 -0
  34. package/src/ummaya/ipc/stdio.py +1109 -477
  35. package/src/ummaya/llm/client.py +102 -3
  36. package/src/ummaya/llm/config.py +8 -3
  37. package/src/ummaya/primitives/__init__.py +6 -2
  38. package/src/ummaya/primitives/delegation.py +1 -1
  39. package/src/ummaya/primitives/document.py +28 -0
  40. package/src/ummaya/settings.py +0 -3
  41. package/src/ummaya/tools/discovery_bridge.py +17 -1
  42. package/src/ummaya/tools/documents/__init__.py +297 -0
  43. package/src/ummaya/tools/documents/adapter_registry.py +487 -0
  44. package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
  45. package/src/ummaya/tools/documents/artifact_store.py +454 -0
  46. package/src/ummaya/tools/documents/authoring.py +283 -0
  47. package/src/ummaya/tools/documents/baselines.py +132 -0
  48. package/src/ummaya/tools/documents/capability.py +331 -0
  49. package/src/ummaya/tools/documents/contracts.py +112 -0
  50. package/src/ummaya/tools/documents/conversion.py +521 -0
  51. package/src/ummaya/tools/documents/diff.py +275 -0
  52. package/src/ummaya/tools/documents/engines.py +163 -0
  53. package/src/ummaya/tools/documents/evaluation.py +291 -0
  54. package/src/ummaya/tools/documents/explicit_values.py +108 -0
  55. package/src/ummaya/tools/documents/fixtures.py +174 -0
  56. package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
  57. package/src/ummaya/tools/documents/formats/__init__.py +2 -0
  58. package/src/ummaya/tools/documents/formats/archive.py +528 -0
  59. package/src/ummaya/tools/documents/formats/base.py +41 -0
  60. package/src/ummaya/tools/documents/formats/code_file.py +211 -0
  61. package/src/ummaya/tools/documents/formats/data_file.py +272 -0
  62. package/src/ummaya/tools/documents/formats/hwp.py +284 -0
  63. package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
  64. package/src/ummaya/tools/documents/formats/odf.py +435 -0
  65. package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
  66. package/src/ummaya/tools/documents/formats/passive.py +766 -0
  67. package/src/ummaya/tools/documents/formats/pdf.py +702 -0
  68. package/src/ummaya/tools/documents/formats/text_web.py +268 -0
  69. package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
  70. package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
  71. package/src/ummaya/tools/documents/inspection.py +289 -0
  72. package/src/ummaya/tools/documents/intake.py +1079 -0
  73. package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
  74. package/src/ummaya/tools/documents/models.py +1598 -0
  75. package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
  76. package/src/ummaya/tools/documents/orchestrator.py +96 -0
  77. package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
  78. package/src/ummaya/tools/documents/patch.py +170 -0
  79. package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
  80. package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
  81. package/src/ummaya/tools/documents/permissions.py +110 -0
  82. package/src/ummaya/tools/documents/planner.py +616 -0
  83. package/src/ummaya/tools/documents/registry.py +2733 -0
  84. package/src/ummaya/tools/documents/render.py +978 -0
  85. package/src/ummaya/tools/documents/render_comparison.py +113 -0
  86. package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
  87. package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
  88. package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
  89. package/src/ummaya/tools/documents/reread.py +157 -0
  90. package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
  91. package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
  92. package/src/ummaya/tools/documents/scorecard.py +184 -0
  93. package/src/ummaya/tools/documents/socratic_planner.py +193 -0
  94. package/src/ummaya/tools/documents/style.py +48 -0
  95. package/src/ummaya/tools/documents/tool_defs.py +523 -0
  96. package/src/ummaya/tools/documents/validate.py +347 -0
  97. package/src/ummaya/tools/executor.py +29 -0
  98. package/src/ummaya/tools/live_proxy.py +0 -3
  99. package/src/ummaya/tools/models.py +5 -1
  100. package/src/ummaya/tools/register_all.py +8 -0
  101. package/src/ummaya/tools/registry.py +10 -1
  102. package/src/ummaya/tools/routing/__init__.py +59 -0
  103. package/src/ummaya/tools/routing/builder.py +105 -0
  104. package/src/ummaya/tools/routing/cards.py +29 -0
  105. package/src/ummaya/tools/routing/decision_service.py +534 -0
  106. package/src/ummaya/tools/routing/decision_types.py +74 -0
  107. package/src/ummaya/tools/routing/feasibility.py +122 -0
  108. package/src/ummaya/tools/routing/intent.py +17 -0
  109. package/src/ummaya/tools/routing/intent_extractor.py +207 -0
  110. package/src/ummaya/tools/routing/intent_patterns.py +160 -0
  111. package/src/ummaya/tools/routing/intent_public_data.py +150 -0
  112. package/src/ummaya/tools/routing/intent_types.py +48 -0
  113. package/src/ummaya/tools/routing/lint.py +78 -0
  114. package/src/ummaya/tools/routing/metadata.py +174 -0
  115. package/src/ummaya/tools/routing/projection.py +340 -0
  116. package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
  117. package/src/ummaya/tools/routing/schema.py +81 -0
  118. package/src/ummaya/tools/routing/types.py +96 -0
  119. package/src/ummaya/tools/routing_index.py +2 -2
  120. package/src/ummaya/tools/search.py +34 -746
  121. package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
  122. package/tui/bun.lock +126 -305
  123. package/tui/package.json +35 -22
  124. package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
  125. package/tui/src/QueryEngine.ts +12 -8
  126. package/tui/src/bridge/inboundAttachments.ts +3 -3
  127. package/tui/src/cli/handlers/auth.ts +3 -12
  128. package/tui/src/cli/handlers/mcp.tsx +0 -1
  129. package/tui/src/cli/print.ts +8 -9
  130. package/tui/src/commands/insights.ts +1 -1
  131. package/tui/src/commands/install-github-app/types.ts +8 -30
  132. package/tui/src/commands/plugin/types.ts +6 -28
  133. package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
  134. package/tui/src/commands/rename/generateSessionName.ts +1 -1
  135. package/tui/src/components/Feedback.tsx +1 -1
  136. package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
  137. package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
  138. package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
  139. package/tui/src/components/Spinner/types.ts +6 -28
  140. package/tui/src/components/agents/generateAgent.ts +1 -1
  141. package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
  142. package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
  143. package/tui/src/components/mcp/types.ts +16 -38
  144. package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
  145. package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
  146. package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
  147. package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
  148. package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
  149. package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
  150. package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
  151. package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
  152. package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
  153. package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
  154. package/tui/src/components/primitive/index.tsx +43 -1
  155. package/tui/src/components/primitive/types.ts +137 -0
  156. package/tui/src/components/ui/option.ts +4 -26
  157. package/tui/src/constants/common.ts +0 -2
  158. package/tui/src/constants/prompts.ts +4 -3
  159. package/tui/src/constants/querySource.ts +4 -26
  160. package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
  161. package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
  162. package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
  163. package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
  164. package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
  165. package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
  166. package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
  167. package/tui/src/hooks/useApiKeyVerification.ts +1 -1
  168. package/tui/src/hooks/useVirtualScroll.ts +1 -1
  169. package/tui/src/ink/ink.tsx +33 -14
  170. package/tui/src/ink/reconciler.ts +2 -3
  171. package/tui/src/ink/render-to-screen.ts +30 -10
  172. package/tui/src/ipc/bridge.ts +62 -15
  173. package/tui/src/ipc/bridgeSingleton.ts +5 -1
  174. package/tui/src/ipc/codec.ts +3 -3
  175. package/tui/src/ipc/frames.generated.ts +12 -12
  176. package/tui/src/ipc/llmClient.ts +151 -27
  177. package/tui/src/ipc/schema/frame.schema.json +1 -1
  178. package/tui/src/keybindings/defaultBindings.ts +4 -0
  179. package/tui/src/main.tsx +32 -15
  180. package/tui/src/native-ts/file-index/index.ts +33 -3
  181. package/tui/src/observability/surface.ts +2 -2
  182. package/tui/src/probes/toolRegistryProbe.tsx +3 -1
  183. package/tui/src/projectOnboardingState.ts +7 -6
  184. package/tui/src/query/chatMessageTypes.ts +18 -0
  185. package/tui/src/query/chatMessagesBuilder.ts +1 -1
  186. package/tui/src/query/deps.ts +1 -1
  187. package/tui/src/query/messageGuards.ts +106 -0
  188. package/tui/src/query/publicDataTerminalRepair.ts +384 -0
  189. package/tui/src/query/run.ts +1075 -0
  190. package/tui/src/query/supportBoundary.ts +168 -0
  191. package/tui/src/query/toolResultErrors.ts +103 -0
  192. package/tui/src/query/toolRunner.ts +687 -0
  193. package/tui/src/query/unavailableToolRepair.ts +118 -0
  194. package/tui/src/query.ts +9 -2186
  195. package/tui/src/screens/REPL.tsx +40 -29
  196. package/tui/src/services/api/adapterManifest.ts +4 -0
  197. package/tui/src/services/api/backendChat/events.ts +117 -0
  198. package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
  199. package/tui/src/services/api/backendChat/frame.ts +9 -0
  200. package/tui/src/services/api/backendChat/streaming.ts +430 -0
  201. package/tui/src/services/api/backendChat/types.ts +62 -0
  202. package/tui/src/services/api/backendChat.ts +1 -0
  203. package/tui/src/services/api/client.ts +65 -2
  204. package/tui/src/services/api/errorUtils.ts +5 -5
  205. package/tui/src/services/api/errors.ts +1 -1
  206. package/tui/src/services/api/logging.ts +1 -1
  207. package/tui/src/services/api/ummaya/evidence.ts +194 -0
  208. package/tui/src/services/api/ummaya/messages.ts +255 -0
  209. package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
  210. package/tui/src/services/api/ummaya/provider.ts +200 -0
  211. package/tui/src/services/api/ummaya/reasoning.ts +24 -0
  212. package/tui/src/services/api/ummaya/request.ts +200 -0
  213. package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
  214. package/tui/src/services/api/ummaya/streaming.ts +365 -0
  215. package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
  216. package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
  217. package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
  218. package/tui/src/services/api/ummaya/types.ts +110 -0
  219. package/tui/src/services/api/ummaya/usage.ts +30 -0
  220. package/tui/src/services/api/ummaya.ts +26 -418
  221. package/tui/src/services/api/withRetry.ts +1 -1
  222. package/tui/src/services/awaySummary.ts +2 -2
  223. package/tui/src/services/claudeAiLimits.ts +1 -1
  224. package/tui/src/services/compact/autoCompact.ts +1 -1
  225. package/tui/src/services/compact/compact.ts +1 -1
  226. package/tui/src/services/lsp/types.ts +8 -30
  227. package/tui/src/services/tips/types.ts +6 -28
  228. package/tui/src/services/tokenEstimation.ts +1 -1
  229. package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
  230. package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
  231. package/tui/src/services/tools/toolExecution.ts +94 -1
  232. package/tui/src/store/pendingPermissionSlot.ts +1 -1
  233. package/tui/src/store/session-store.ts +10 -36
  234. package/tui/src/stubs/any-stub.ts +15 -10
  235. package/tui/src/stubs/color-diff-napi.ts +37 -23
  236. package/tui/src/stubs/globals.d.ts +3 -3
  237. package/tui/src/stubs/macro-preload.ts +23 -12
  238. package/tui/src/tools/AdapterTool/AdapterTool.ts +1207 -714
  239. package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
  240. package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
  241. package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
  242. package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
  243. package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
  244. package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
  245. package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
  246. package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
  247. package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
  248. package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
  249. package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
  250. package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
  251. package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
  252. package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
  253. package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
  254. package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
  255. package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
  256. package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
  257. package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
  258. package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
  259. package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
  260. package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
  261. package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
  262. package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
  263. package/tui/src/tools/AgentTool/permissions.ts +39 -0
  264. package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
  265. package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
  266. package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
  267. package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
  268. package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
  269. package/tui/src/tools/AgentTool/runAgent.ts +1 -1
  270. package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
  271. package/tui/src/tools/AgentTool/schemas.ts +196 -0
  272. package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
  273. package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
  274. package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
  275. package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
  276. package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
  277. package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
  278. package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
  279. package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
  280. package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
  281. package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
  282. package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
  283. package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
  284. package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
  285. package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
  286. package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
  287. package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
  288. package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
  289. package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
  290. package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
  291. package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
  292. package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
  293. package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
  294. package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
  295. package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
  296. package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
  297. package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
  298. package/tui/src/tools/BashTool/call.ts +202 -0
  299. package/tui/src/tools/BashTool/callLoader.ts +35 -0
  300. package/tui/src/tools/BashTool/commandClassification.ts +151 -0
  301. package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
  302. package/tui/src/tools/BashTool/cwdReset.ts +33 -0
  303. package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
  304. package/tui/src/tools/BashTool/modeValidation.ts +13 -1
  305. package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
  306. package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
  307. package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
  308. package/tui/src/tools/BashTool/resultLoader.ts +29 -0
  309. package/tui/src/tools/BashTool/resultMapping.ts +83 -0
  310. package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
  311. package/tui/src/tools/BashTool/schemas.ts +65 -0
  312. package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
  313. package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
  314. package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
  315. package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
  316. package/tui/src/tools/BashTool/uiLoader.ts +37 -0
  317. package/tui/src/tools/BriefTool/upload.ts +1 -1
  318. package/tui/src/tools/CalculatorTool/parser.ts +2 -2
  319. package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
  320. package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
  321. package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
  322. package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
  323. package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
  324. package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
  325. package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
  326. package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
  327. package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
  328. package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
  329. package/tui/src/tools/FileEditTool/call.ts +228 -0
  330. package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
  331. package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
  332. package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
  333. package/tui/src/tools/FileWriteTool/call.ts +223 -0
  334. package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
  335. package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
  336. package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +25 -32
  337. package/tui/src/tools/LookupPrimitive/prompt.ts +0 -2
  338. package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
  339. package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
  340. package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
  341. package/tui/src/tools/NotebookEditTool/call.ts +254 -0
  342. package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
  343. package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
  344. package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
  345. package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
  346. package/tui/src/tools/PowerShellTool/call.ts +179 -0
  347. package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
  348. package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
  349. package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
  350. package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
  351. package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
  352. package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
  353. package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
  354. package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
  355. package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
  356. package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
  357. package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
  358. package/tui/src/tools/PowerShellTool/validation.ts +39 -0
  359. package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
  360. package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +1 -11
  361. package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
  362. package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
  363. package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +27 -10
  364. package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
  365. package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
  366. package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
  367. package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
  368. package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
  369. package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
  370. package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
  371. package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
  372. package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
  373. package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
  374. package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
  375. package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
  376. package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
  377. package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
  378. package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
  379. package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
  380. package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
  381. package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
  382. package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
  383. package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
  384. package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
  385. package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
  386. package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
  387. package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
  388. package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
  389. package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +2 -1
  390. package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
  391. package/tui/src/tools/WebFetchTool/call.ts +227 -0
  392. package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
  393. package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
  394. package/tui/src/tools/WebFetchTool/types.ts +23 -0
  395. package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
  396. package/tui/src/tools/WebFetchTool/utils.ts +1 -1
  397. package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
  398. package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
  399. package/tui/src/tools/WebSearchTool/call.ts +33 -0
  400. package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
  401. package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
  402. package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
  403. package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
  404. package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
  405. package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
  406. package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
  407. package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
  408. package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
  409. package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
  410. package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
  411. package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
  412. package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
  413. package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
  414. package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
  415. package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
  416. package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
  417. package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
  418. package/tui/src/tools/_shared/rootPrimitiveInput.ts +1 -0
  419. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
  420. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
  421. package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
  422. package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
  423. package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
  424. package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
  425. package/tui/src/tools/_shared/toolChoiceRepair.ts +55 -860
  426. package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
  427. package/tui/src/tools.ts +39 -190
  428. package/tui/src/types/fileSuggestion.ts +4 -26
  429. package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
  430. package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
  431. package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
  432. package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
  433. package/tui/src/types/message.ts +80 -102
  434. package/tui/src/types/messageQueueTypes.ts +6 -28
  435. package/tui/src/types/notebook.ts +16 -38
  436. package/tui/src/types/statusLine.ts +4 -26
  437. package/tui/src/types/tools.ts +24 -46
  438. package/tui/src/types/utils.ts +6 -28
  439. package/tui/src/upstreamproxy/relay.ts +7 -3
  440. package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
  441. package/tui/src/utils/assistantMessageFactories.ts +9 -3
  442. package/tui/src/utils/auth.ts +129 -139
  443. package/tui/src/utils/bash/ast.ts +23 -23
  444. package/tui/src/utils/bash/bashParser.ts +5 -5
  445. package/tui/src/utils/billing.ts +1 -1
  446. package/tui/src/utils/claudeDesktop.ts +4 -4
  447. package/tui/src/utils/collapseReadSearch.ts +3 -3
  448. package/tui/src/utils/cronTasks.ts +1 -1
  449. package/tui/src/utils/execFileNoThrow.ts +1 -1
  450. package/tui/src/utils/filePersistence/types.ts +16 -38
  451. package/tui/src/utils/forkedAgent.ts +1 -1
  452. package/tui/src/utils/gracefulShutdown.ts +4 -4
  453. package/tui/src/utils/heapDumpService.ts +12 -8
  454. package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
  455. package/tui/src/utils/hooks/execPromptHook.ts +1 -1
  456. package/tui/src/utils/hooks/skillImprovement.ts +1 -1
  457. package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
  458. package/tui/src/utils/messages.ts +18 -0
  459. package/tui/src/utils/migrateSessions.ts +3 -3
  460. package/tui/src/utils/model/model.ts +6 -6
  461. package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
  462. package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
  463. package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
  464. package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
  465. package/tui/src/utils/plugins/pluginLoader.ts +8 -8
  466. package/tui/src/utils/protectedNamespace.ts +5 -3
  467. package/tui/src/utils/rawJsonToolCall.ts +242 -0
  468. package/tui/src/utils/ripgrep.ts +16 -7
  469. package/tui/src/utils/sessionTitle.ts +1 -1
  470. package/tui/src/utils/settings/permissionValidation.ts +14 -2
  471. package/tui/src/utils/shell/prefix.ts +1 -1
  472. package/tui/src/utils/sideQuery.ts +1 -1
  473. package/tui/src/utils/systemThemeWatcher.ts +13 -3
  474. package/tui/src/utils/teleport.tsx +1 -1
  475. package/uv.lock +426 -45
  476. package/tui/src/services/api/claude.ts +0 -3540
  477. package/tui/src/tools/_shared/directPublicDataGuard.ts +0 -362
  478. package/tui/src/tools/_shared/kmaAnalysisGuard.ts +0 -197
  479. package/tui/src/tools/_shared/kmaAviationGuard.ts +0 -70
  480. package/tui/src/tools/_shared/nmcAedGuard.ts +0 -234
  481. package/tui/src/tools/_shared/protectedCheckGuard.ts +0 -207
  482. package/tui/src/tools/_shared/textToolCallGuard.ts +0 -91
@@ -9,211 +9,36 @@ service channels, LLM providers, or observability backends.
9
9
  from __future__ import annotations
10
10
 
11
11
  import argparse
12
- from collections.abc import Mapping, Sequence
12
+ import json
13
13
  from pathlib import Path
14
- from typing import Literal, cast
15
14
 
16
- import yaml
17
- from pydantic import BaseModel, ConfigDict, Field, ValidationError
18
-
19
- from ummaya.evidence.models import EvidenceGate, RunEvidence
20
- from ummaya.evidence.task_registry import EvidenceDatasetRef, load_task_registry
21
-
22
- _REPO_ROOT = Path(__file__).resolve().parents[3]
23
- _DEFAULT_SCENARIO_PATH = _REPO_ROOT / "evidence/scenarios/national_ax_citizen_requests_v1.yaml"
24
- _DEFAULT_TASK_REGISTRY_PATH = _REPO_ROOT / "evidence/registry.yaml"
25
- _DEFAULT_DATASET_REF = "ummaya/national-ax-core@local"
26
- _BANNED_MODEL_VISIBLE_KEYS = frozenset(
27
- {
28
- "adapter_id",
29
- "tool_id",
30
- "expected_tool_id",
31
- "fixture_refs",
32
- "fixture_ref",
33
- "current_adapter_id",
34
- }
15
+ from ummaya.evidence.dataset_contract import (
16
+ DEFAULT_DATASET_REF,
17
+ DEFAULT_SCENARIO_PATH,
18
+ DEFAULT_TASK_REGISTRY_PATH,
19
+ EvidenceContractError,
20
+ resolve_repo_path,
35
21
  )
36
- _REQUIRED_DOMAINS = frozenset(
37
- {
38
- "tax",
39
- "civil_affairs",
40
- "payments",
41
- "utilities",
42
- "identity",
43
- "welfare",
44
- "healthcare",
45
- "housing",
46
- "mobility",
47
- "business",
48
- "labor",
49
- "education",
50
- "safety",
51
- "immigration",
52
- "legal",
53
- "personal_data",
54
- }
22
+ from ummaya.evidence.dataset_contract import (
23
+ parse_dataset as _parse_dataset,
55
24
  )
56
-
57
-
58
- class EvidenceContractError(ValueError):
59
- """Raised when a scenario dataset violates the Evidence Fabric contract."""
60
-
61
-
62
- class ExpectedStep(BaseModel):
63
- """One expected public-service loop step in a scenario."""
64
-
65
- model_config = ConfigDict(frozen=True, extra="forbid")
66
-
67
- primitive: str
68
- purpose: str
69
-
70
-
71
- class PermissionRequirements(BaseModel):
72
- """Permission requirements attached to a citizen scenario."""
73
-
74
- model_config = ConfigDict(frozen=True, extra="allow")
75
-
76
- identity_assurance: str
77
- user_confirmations: tuple[str, ...] = Field(default_factory=tuple)
78
- sensitive_data: tuple[str, ...] = Field(default_factory=tuple)
79
-
80
-
81
- class Scenario(BaseModel):
82
- """Minimum scenario shape needed by Evidence Fabric v2."""
83
-
84
- model_config = ConfigDict(frozen=True, extra="allow")
85
-
86
- id: str
87
- priority: str = "P2"
88
- lifecycle_domain: str
89
- request_ko: str
90
- expected_ax_chain: tuple[ExpectedStep, ...]
91
- permission_requirements: PermissionRequirements
92
-
93
-
94
- class ScenarioDataset(BaseModel):
95
- """Versioned citizen-demand scenario dataset."""
96
-
97
- model_config = ConfigDict(frozen=True, extra="allow")
98
-
99
- version: int
100
- dataset_id: str
101
- coverage_domains: tuple[str, ...]
102
- scenarios: tuple[Scenario, ...]
103
-
104
-
105
- def _load_yaml_mapping(path: Path) -> Mapping[str, object]:
106
- if not path.exists():
107
- raise EvidenceContractError(f"scenario dataset not found: {path}")
108
- loaded = yaml.safe_load(path.read_text(encoding="utf-8"))
109
- if not isinstance(loaded, Mapping):
110
- raise EvidenceContractError(f"scenario dataset must be a mapping: {path}")
111
- return cast(Mapping[str, object], loaded)
112
-
113
-
114
- def _find_banned_keys(value: object, path: str = "$") -> tuple[str, ...]:
115
- if isinstance(value, Mapping):
116
- hits: list[str] = []
117
- for key, nested in value.items():
118
- key_text = str(key)
119
- nested_path = f"{path}.{key_text}"
120
- if key_text in _BANNED_MODEL_VISIBLE_KEYS:
121
- hits.append(nested_path)
122
- hits.extend(_find_banned_keys(nested, nested_path))
123
- return tuple(hits)
124
- if isinstance(value, Sequence) and not isinstance(value, str | bytes | bytearray):
125
- hits = []
126
- for index, nested in enumerate(value):
127
- hits.extend(_find_banned_keys(nested, f"{path}[{index}]"))
128
- return tuple(hits)
129
- return ()
130
-
131
-
132
- def _parse_dataset(path: Path) -> ScenarioDataset:
133
- raw = _load_yaml_mapping(path)
134
- banned = _find_banned_keys(raw)
135
- if banned:
136
- raise EvidenceContractError(
137
- "model-visible scenario dataset contains banned implementation keys: "
138
- + ", ".join(banned)
139
- )
140
- try:
141
- return ScenarioDataset.model_validate(raw)
142
- except ValidationError as exc:
143
- raise EvidenceContractError(str(exc)) from exc
144
-
145
-
146
- def _gate(
147
- name: Literal["contract", "scenario", "observability", "adversarial", "ux", "live_canary"],
148
- status: Literal["pass", "fail", "skip"],
149
- summary: str,
150
- check_ids: tuple[str, ...],
151
- ) -> EvidenceGate:
152
- return EvidenceGate(name=name, status=status, summary=summary, check_ids=check_ids)
153
-
154
-
155
- def _build_gates(dataset: ScenarioDataset) -> tuple[EvidenceGate, ...]:
156
- covered_domains = set(dataset.coverage_domains)
157
- missing_domains = tuple(sorted(_REQUIRED_DOMAINS - covered_domains))
158
- scenario_domains = {scenario.lifecycle_domain for scenario in dataset.scenarios}
159
- uncovered_scenario_domains = tuple(sorted(scenario_domains - covered_domains))
160
-
161
- scenario_status: Literal["pass", "fail"] = (
162
- "pass" if not missing_domains and not uncovered_scenario_domains else "fail"
163
- )
164
- scenario_summary = (
165
- "all required citizen infrastructure domains are covered"
166
- if scenario_status == "pass"
167
- else "missing coverage: " + ", ".join(missing_domains + uncovered_scenario_domains)
168
- )
169
-
170
- return (
171
- _gate(
172
- "contract",
173
- "pass",
174
- "dataset is versioned, typed, and free of model-visible implementation keys",
175
- ("dataset-schema", "task-registry", "no-adapter-leakage"),
176
- ),
177
- _gate(
178
- "scenario",
179
- scenario_status,
180
- scenario_summary,
181
- ("coverage-domains", "scenario-shape"),
182
- ),
183
- _gate(
184
- "observability",
185
- "pass",
186
- "RunEvidence carries trace join keys for OTEL/Langfuse correlation",
187
- ("trace-join-keys",),
188
- ),
189
- _gate(
190
- "adversarial",
191
- "pass",
192
- "adapter IDs, fixture references, and expected tool IDs are rejected before scoring",
193
- ("reward-hack-surface", "hidden-implementation-leakage"),
194
- ),
195
- _gate(
196
- "ux",
197
- "skip",
198
- "UX frame artifacts are attached by interactive runners, not by dataset validation",
199
- ("ux-artifact-slot",),
200
- ),
201
- _gate(
202
- "live_canary",
203
- "skip",
204
- "live public-service checks are manual-only and excluded from CI",
205
- ("no-live-ci",),
206
- ),
207
- )
208
-
209
-
210
- def _resolve_repo_path(path: Path) -> Path:
211
- return path if path.is_absolute() else _REPO_ROOT / path
25
+ from ummaya.evidence.document_viewer_ux import DocumentViewerUxArtifact
26
+ from ummaya.evidence.gates import build_gates
27
+ from ummaya.evidence.models import RunEvidence
28
+ from ummaya.evidence.output_payload import build_evidence_output_payload
29
+ from ummaya.evidence.route_contracts import (
30
+ route_selection_assertions as _route_selection_assertions,
31
+ )
32
+ from ummaya.evidence.route_contracts import (
33
+ route_trace_records as _route_trace_records,
34
+ )
35
+ from ummaya.evidence.task_registry import EvidenceDatasetRef, load_task_registry
36
+ from ummaya.evidence.tool_layer import build_tool_layer_events
212
37
 
213
38
 
214
39
  def _resolve_task_dataset(
215
40
  *,
216
- dataset: ScenarioDataset,
41
+ dataset_id: str,
217
42
  scenario_path: Path,
218
43
  task_registry_path: Path | None,
219
44
  dataset_ref: str,
@@ -222,12 +47,12 @@ def _resolve_task_dataset(
222
47
  return None, None
223
48
  registry = load_task_registry(task_registry_path)
224
49
  task_dataset = registry.resolve_dataset(dataset_ref)
225
- if task_dataset.dataset_id != dataset.dataset_id:
50
+ if task_dataset.dataset_id != dataset_id:
226
51
  raise EvidenceContractError(
227
52
  f"task registry dataset_id {task_dataset.dataset_id!r} does not match "
228
- f"scenario dataset_id {dataset.dataset_id!r}"
53
+ f"scenario dataset_id {dataset_id!r}"
229
54
  )
230
- if _resolve_repo_path(task_dataset.scenario_path) != _resolve_repo_path(scenario_path):
55
+ if resolve_repo_path(task_dataset.scenario_path) != resolve_repo_path(scenario_path):
231
56
  raise EvidenceContractError(
232
57
  f"task registry scenario_path {task_dataset.scenario_path} does not match "
233
58
  f"run scenario_path {scenario_path}"
@@ -237,20 +62,21 @@ def _resolve_task_dataset(
237
62
 
238
63
  def run_dataset(
239
64
  *,
240
- scenario_path: Path = _DEFAULT_SCENARIO_PATH,
65
+ scenario_path: Path = DEFAULT_SCENARIO_PATH,
241
66
  source_ref: str = "local",
242
- task_registry_path: Path | None = _DEFAULT_TASK_REGISTRY_PATH,
243
- dataset_ref: str = _DEFAULT_DATASET_REF,
67
+ task_registry_path: Path | None = DEFAULT_TASK_REGISTRY_PATH,
68
+ dataset_ref: str = DEFAULT_DATASET_REF,
244
69
  ) -> RunEvidence:
245
70
  """Validate a scenario dataset and return a typed evidence document."""
246
71
 
247
72
  dataset = _parse_dataset(scenario_path)
248
73
  task_registry_id, task_dataset = _resolve_task_dataset(
249
- dataset=dataset,
74
+ dataset_id=dataset.dataset_id,
250
75
  scenario_path=scenario_path,
251
76
  task_registry_path=task_registry_path,
252
77
  dataset_ref=dataset_ref,
253
78
  )
79
+ traces = _route_trace_records(dataset)
254
80
  return RunEvidence(
255
81
  source_ref=source_ref,
256
82
  dataset_id=dataset.dataset_id,
@@ -260,7 +86,10 @@ def run_dataset(
260
86
  task_ids=tuple(task.task_id for task in task_dataset.tasks) if task_dataset else (),
261
87
  scenario_count=len(dataset.scenarios),
262
88
  scenario_ids=tuple(scenario.id for scenario in dataset.scenarios),
263
- gates=_build_gates(dataset),
89
+ route_trace_records=traces,
90
+ route_selection_assertions=_route_selection_assertions(dataset, traces),
91
+ tool_layer_events=build_tool_layer_events(traces),
92
+ gates=build_gates(dataset),
264
93
  )
265
94
 
266
95
 
@@ -271,7 +100,7 @@ def main() -> None:
271
100
  parser.add_argument(
272
101
  "--scenarios",
273
102
  type=Path,
274
- default=_DEFAULT_SCENARIO_PATH,
103
+ default=DEFAULT_SCENARIO_PATH,
275
104
  help="Path to the Evidence Fabric scenario dataset.",
276
105
  )
277
106
  parser.add_argument(
@@ -282,19 +111,39 @@ def main() -> None:
282
111
  parser.add_argument(
283
112
  "--task-registry",
284
113
  type=Path,
285
- default=_DEFAULT_TASK_REGISTRY_PATH,
114
+ default=DEFAULT_TASK_REGISTRY_PATH,
286
115
  help="Path to the Harbor-style Evidence Fabric task registry.",
287
116
  )
288
117
  parser.add_argument(
289
118
  "--dataset-ref",
290
- default=_DEFAULT_DATASET_REF,
119
+ default=DEFAULT_DATASET_REF,
291
120
  help="Harbor-style dataset ref to resolve from the task registry.",
292
121
  )
293
122
  parser.add_argument(
294
- "--out",
123
+ "--out", type=Path, default=Path(".evidence/run.json"), help="Output JSON path."
124
+ )
125
+ parser.add_argument(
126
+ "--document-viewer-html",
295
127
  type=Path,
296
- default=Path(".evidence/run.json"),
297
- help="Output JSON path.",
128
+ action="append",
129
+ default=None,
130
+ help="Local document viewer HTML path to capture as a Playwright UX artifact.",
131
+ )
132
+ parser.add_argument(
133
+ "--document-viewer-ux-out-dir",
134
+ type=Path,
135
+ default=None,
136
+ help="Directory for Playwright document viewer PNG artifacts.",
137
+ )
138
+ parser.add_argument(
139
+ "--document-viewer-correlation-id",
140
+ default=None,
141
+ help="Correlation ID to attach when the viewer manifest does not carry one.",
142
+ )
143
+ parser.add_argument(
144
+ "--document-viewer-diff-id",
145
+ default=None,
146
+ help="Document diff ID to attach when the viewer manifest does not carry one.",
298
147
  )
299
148
  args = parser.parse_args()
300
149
 
@@ -305,4 +154,24 @@ def main() -> None:
305
154
  dataset_ref=args.dataset_ref,
306
155
  )
307
156
  args.out.parent.mkdir(parents=True, exist_ok=True)
308
- args.out.write_text(evidence.model_dump_json(indent=2), encoding="utf-8")
157
+ ux_out_dir = args.document_viewer_ux_out_dir or args.out.parent / "ux-artifacts"
158
+ document_viewer_ux_artifacts: list[DocumentViewerUxArtifact] = []
159
+ document_viewer_html_paths = tuple(args.document_viewer_html or ())
160
+ if document_viewer_html_paths:
161
+ from ummaya.evidence.document_viewer_ux import capture_document_viewer_ux_artifact
162
+
163
+ for viewer_html_path in document_viewer_html_paths:
164
+ document_viewer_ux_artifacts.append(
165
+ capture_document_viewer_ux_artifact(
166
+ viewer_html_path=viewer_html_path,
167
+ output_dir=ux_out_dir,
168
+ source_ref=args.source_ref,
169
+ correlation_id=args.document_viewer_correlation_id,
170
+ document_diff_id=args.document_viewer_diff_id,
171
+ )
172
+ )
173
+ payload = build_evidence_output_payload(
174
+ evidence,
175
+ document_viewer_ux_artifacts=tuple(document_viewer_ux_artifacts),
176
+ )
177
+ args.out.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
@@ -0,0 +1,246 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ from __future__ import annotations
3
+
4
+ from datetime import datetime
5
+ from typing import Literal, Self
6
+
7
+ from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
8
+ from pydantic_core import PydanticCustomError
9
+
10
+ from ummaya.evidence.source_provenance_redaction import (
11
+ PromptInjectionState,
12
+ RedactionCategory,
13
+ detect_prompt_injection,
14
+ ordered_redaction_categories,
15
+ redact_source_text,
16
+ redact_source_url,
17
+ redaction_categories_for_text,
18
+ )
19
+ from ummaya.tools.routing.schema import sha256, unique
20
+
21
+ SourceKind = Literal["web", "mcp", "agent", "file"]
22
+ SourceUseState = Literal["used", "blocked"]
23
+ SourceTrust = Literal["trusted", "untrusted"]
24
+ SynthesisState = Literal[
25
+ "eligible_for_synthesis",
26
+ "blocked_pending_user_approval",
27
+ "blocked_untrusted",
28
+ "blocked_missing_source",
29
+ ]
30
+ DocumentAuthoringState = Literal[
31
+ "approved_for_document",
32
+ "blocked_pending_user_approval",
33
+ "blocked_untrusted",
34
+ "blocked_missing_source",
35
+ ]
36
+
37
+
38
+ class SourceRedactionMetadata(BaseModel):
39
+ model_config = ConfigDict(frozen=True, extra="forbid")
40
+
41
+ redacted: bool
42
+ categories: tuple[RedactionCategory, ...] = Field(default_factory=tuple)
43
+ raw_private_document_stored: Literal[False] = False
44
+ secret_values_stored: Literal[False] = False
45
+ pii_values_stored: Literal[False] = False
46
+
47
+ @model_validator(mode="after")
48
+ def _categories_match_redacted_flag(self) -> Self:
49
+ if self.redacted and not self.categories:
50
+ raise PydanticCustomError(
51
+ "source_provenance_missing_redaction_categories",
52
+ "redacted provenance requires redaction categories",
53
+ )
54
+ if not self.redacted and self.categories:
55
+ raise PydanticCustomError(
56
+ "source_provenance_unexpected_redaction_categories",
57
+ "unredacted provenance cannot carry redaction categories",
58
+ )
59
+ return self
60
+
61
+
62
+ class SourceProvenanceRecord(BaseModel):
63
+ model_config = ConfigDict(frozen=True, extra="forbid")
64
+
65
+ source_kind: SourceKind
66
+ source_url: str | None
67
+ local_evidence_handle: str | None
68
+ title: str | None
69
+ description: str | None
70
+ tool_id: str = Field(min_length=1)
71
+ observed_at: datetime
72
+ state: SourceUseState
73
+ citation_id: str = Field(min_length=1)
74
+ provenance_id: str = Field(min_length=1)
75
+ trust: SourceTrust
76
+ prompt_injection: PromptInjectionState = "not_detected"
77
+ redaction: SourceRedactionMetadata
78
+
79
+ @field_validator(
80
+ "source_url",
81
+ "local_evidence_handle",
82
+ "title",
83
+ "description",
84
+ "tool_id",
85
+ "citation_id",
86
+ "provenance_id",
87
+ )
88
+ @classmethod
89
+ def _reject_unredacted_sensitive_value(cls, value: str | None) -> str | None:
90
+ if value is not None and redaction_categories_for_text(value):
91
+ raise PydanticCustomError(
92
+ "source_provenance_unredacted_sensitive_value",
93
+ "source provenance contains unredacted sensitive value",
94
+ )
95
+ return value
96
+
97
+ @model_validator(mode="after")
98
+ def _requires_source_handle_and_label(self) -> Self:
99
+ if self.source_url is None and self.local_evidence_handle is None:
100
+ raise PydanticCustomError(
101
+ "source_provenance_missing_source",
102
+ "source provenance requires source_url or local_evidence_handle",
103
+ )
104
+ if self.title is None and self.description is None:
105
+ raise PydanticCustomError(
106
+ "source_provenance_missing_label",
107
+ "source provenance requires title or description when available",
108
+ )
109
+ return self
110
+
111
+
112
+ class SourceProvenanceDecision(BaseModel):
113
+ model_config = ConfigDict(frozen=True, extra="forbid")
114
+
115
+ decision_id: str = Field(min_length=1)
116
+ provenance_ids: tuple[str, ...] = Field(min_length=1)
117
+ synthesis_state: SynthesisState
118
+ document_authoring_state: DocumentAuthoringState
119
+ requires_user_approval: bool
120
+ approved_by_user: bool
121
+ rationale: str = Field(min_length=1)
122
+
123
+ @model_validator(mode="after")
124
+ def _document_approval_requires_user_approval(self) -> Self:
125
+ if self.document_authoring_state == "approved_for_document" and (
126
+ self.requires_user_approval or not self.approved_by_user
127
+ ):
128
+ raise PydanticCustomError(
129
+ "source_provenance_document_approval_missing_user_approval",
130
+ "approved document authoring requires completed user approval",
131
+ )
132
+ return self
133
+
134
+
135
+ class SourceProvenanceLedger(BaseModel):
136
+ model_config = ConfigDict(frozen=True, extra="forbid")
137
+
138
+ schema_version: Literal["source_provenance_ledger.v1"] = "source_provenance_ledger.v1"
139
+ ledger_id: str = Field(min_length=1)
140
+ records: tuple[SourceProvenanceRecord, ...] = Field(min_length=1)
141
+ decisions: tuple[SourceProvenanceDecision, ...] = Field(default_factory=tuple)
142
+
143
+ @model_validator(mode="after")
144
+ def _decisions_reference_known_provenance_ids(self) -> Self:
145
+ known_ids = {record.provenance_id for record in self.records}
146
+ if len(known_ids) != len(self.records):
147
+ raise PydanticCustomError(
148
+ "source_provenance_duplicate_ids",
149
+ "source provenance ledger contains duplicate provenance ids",
150
+ )
151
+ unknown_ids = tuple(
152
+ unique(
153
+ provenance_id
154
+ for decision in self.decisions
155
+ for provenance_id in decision.provenance_ids
156
+ if provenance_id not in known_ids
157
+ )
158
+ )
159
+ if unknown_ids:
160
+ raise PydanticCustomError(
161
+ "source_provenance_unknown_ids",
162
+ "unknown provenance ids: " + ", ".join(unknown_ids),
163
+ )
164
+ return self
165
+
166
+
167
+ def build_source_provenance_record(
168
+ *,
169
+ source_kind: SourceKind,
170
+ tool_id: str,
171
+ source_url: str | None,
172
+ local_evidence_handle: str | None,
173
+ title: str | None,
174
+ description: str | None,
175
+ observed_at: datetime,
176
+ state: SourceUseState,
177
+ trust: SourceTrust,
178
+ citation_id: str,
179
+ ) -> SourceProvenanceRecord:
180
+ redacted_url, url_categories = redact_source_url(source_url)
181
+ redacted_handle, handle_categories = redact_source_text(local_evidence_handle)
182
+ redacted_title, title_categories = redact_source_text(title)
183
+ redacted_description, description_categories = redact_source_text(description)
184
+ categories = ordered_redaction_categories(
185
+ (
186
+ *url_categories,
187
+ *handle_categories,
188
+ *title_categories,
189
+ *description_categories,
190
+ )
191
+ )
192
+ prompt_injection_text_parts = (
193
+ title or "",
194
+ description or "",
195
+ source_url or "",
196
+ local_evidence_handle or "",
197
+ )
198
+ return SourceProvenanceRecord(
199
+ source_kind=source_kind,
200
+ source_url=redacted_url,
201
+ local_evidence_handle=redacted_handle,
202
+ title=redacted_title,
203
+ description=redacted_description,
204
+ tool_id=tool_id,
205
+ observed_at=observed_at,
206
+ state=state,
207
+ citation_id=citation_id,
208
+ provenance_id=stable_source_provenance_id(
209
+ source_kind=source_kind,
210
+ tool_id=tool_id,
211
+ source_url=redacted_url,
212
+ local_evidence_handle=redacted_handle,
213
+ citation_id=citation_id,
214
+ ),
215
+ trust=trust,
216
+ prompt_injection=detect_prompt_injection(
217
+ "\n".join(part for part in prompt_injection_text_parts if part)
218
+ ),
219
+ redaction=SourceRedactionMetadata(
220
+ redacted=bool(categories),
221
+ categories=categories,
222
+ raw_private_document_stored=False,
223
+ secret_values_stored=False,
224
+ pii_values_stored=False,
225
+ ),
226
+ )
227
+
228
+
229
+ def stable_source_provenance_id(
230
+ *,
231
+ source_kind: SourceKind,
232
+ tool_id: str,
233
+ source_url: str | None,
234
+ local_evidence_handle: str | None,
235
+ citation_id: str,
236
+ ) -> str:
237
+ digest = sha256(
238
+ {
239
+ "citation_id": citation_id,
240
+ "local_evidence_handle": local_evidence_handle,
241
+ "source_kind": source_kind,
242
+ "source_url": source_url,
243
+ "tool_id": tool_id,
244
+ }
245
+ )
246
+ return f"prov-{digest[:24]}"