precis-cli 0.1.7__tar.gz → 0.1.8__tar.gz

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 (453) hide show
  1. {precis_cli-0.1.7/precis_cli.egg-info → precis_cli-0.1.8}/PKG-INFO +1 -1
  2. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/dependencies.py +42 -0
  3. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/models/full_validation.py +6 -0
  4. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/models/validation.py +6 -0
  5. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/ai/hardware.py +5 -1
  6. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/ai/utils.py +8 -1
  7. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/core/data_sources.py +1 -1
  8. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/core/reporting.py +1 -1
  9. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/preview/header_row.py +1 -1
  10. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/helpers.py +1 -1
  11. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/projects/open.py +1 -1
  12. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/projects/scan.py +1 -1
  13. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/validation/common.py +3 -0
  14. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/services/full_validation_response_builder.py +3 -0
  15. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shared_services/config_ops.py +2 -2
  16. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/io/yaml.py +3 -1
  17. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/registry.py +4 -0
  18. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/reporter/reporters/__init__.py +1 -1
  19. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/allowed_values.py +6 -0
  20. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/charset.py +15 -0
  21. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/composite.py +4 -0
  22. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/conditional.py +31 -0
  23. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/date_logic.py +80 -0
  24. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/foreign_key.py +12 -0
  25. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/not_null.py +6 -0
  26. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/range.py +20 -0
  27. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/regex.py +14 -0
  28. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/scripted.py +12 -0
  29. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/unique.py +8 -0
  30. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/yaml_io.py +1 -1
  31. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/service.py +29 -9
  32. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/validators/adapter.py +32 -11
  33. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/validators/base.py +8 -4
  34. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/validators/composite.py +8 -0
  35. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/validators/date_logic.py +48 -6
  36. {precis_cli-0.1.7 → precis_cli-0.1.8/precis_cli.egg-info}/PKG-INFO +1 -1
  37. {precis_cli-0.1.7 → precis_cli-0.1.8}/precis_cli.egg-info/SOURCES.txt +0 -4
  38. {precis_cli-0.1.7 → precis_cli-0.1.8}/pyproject.toml +1 -1
  39. precis_cli-0.1.7/app/cli_main.py +0 -52
  40. precis_cli-0.1.7/app/shared/core/manifest_schema/types.py +0 -99
  41. precis_cli-0.1.7/app/shared/services/ai/types.py +0 -213
  42. precis_cli-0.1.7/app/shared/services/llm/models.py +0 -104
  43. {precis_cli-0.1.7 → precis_cli-0.1.8}/MANIFEST.in +0 -0
  44. {precis_cli-0.1.7 → precis_cli-0.1.8}/PYPI_README.md +0 -0
  45. {precis_cli-0.1.7 → precis_cli-0.1.8}/README.md +0 -0
  46. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/__init__.py +0 -0
  47. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/__init__.py +0 -0
  48. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/main.py +0 -0
  49. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/middleware/__init__.py +0 -0
  50. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/middleware/exception_handler.py +0 -0
  51. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/middleware/request_logging.py +0 -0
  52. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/middleware/token_auth.py +0 -0
  53. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/models/__init__.py +0 -0
  54. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/models/connection_rules.py +0 -0
  55. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/models/files.py +0 -0
  56. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/models/project.py +0 -0
  57. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/models/projects.py +0 -0
  58. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/models/schema.py +0 -0
  59. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/models/v2_responses.py +0 -0
  60. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/models/workspace.py +0 -0
  61. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/__init__.py +0 -0
  62. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/ai/__init__.py +0 -0
  63. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/ai/chat.py +0 -0
  64. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/ai/generate.py +0 -0
  65. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/ai/jobs.py +0 -0
  66. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/ai/migrate.py +0 -0
  67. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/ai/models.py +0 -0
  68. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/ai/ollama.py +0 -0
  69. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/ai/providers.py +0 -0
  70. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/ai/router.py +0 -0
  71. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/ai/stream.py +0 -0
  72. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/core/__init__.py +0 -0
  73. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/core/connection_rules.py +0 -0
  74. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/core/regex.py +0 -0
  75. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/files/__init__.py +0 -0
  76. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/files/ops.py +0 -0
  77. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/files/transfer.py +0 -0
  78. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/preview/__init__.py +0 -0
  79. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/preview/content_mode.py +0 -0
  80. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/preview/models.py +0 -0
  81. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/preview/path_mode.py +0 -0
  82. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/preview/router.py +0 -0
  83. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/__init__.py +0 -0
  84. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/base.py +0 -0
  85. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/constraint.py +0 -0
  86. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/full_config.py +0 -0
  87. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/full_config_writer.py +0 -0
  88. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/inspection_fix.py +0 -0
  89. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/manifest.py +0 -0
  90. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/models.py +0 -0
  91. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/pattern.py +0 -0
  92. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/regex.py +0 -0
  93. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/scanner.py +0 -0
  94. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/schema.py +0 -0
  95. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/schema_helpers.py +0 -0
  96. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/settings.py +0 -0
  97. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/template.py +0 -0
  98. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/validation.py +0 -0
  99. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/view.py +0 -0
  100. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/project/workspaces.py +0 -0
  101. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/projects/__init__.py +0 -0
  102. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/projects/create.py +0 -0
  103. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/validation/__init__.py +0 -0
  104. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/validation/content_mode.py +0 -0
  105. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/validation/history.py +0 -0
  106. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/validation/inline_mode.py +0 -0
  107. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/validation/path_mode.py +0 -0
  108. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/routers/validation/router.py +0 -0
  109. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/services/io_error_messages.py +0 -0
  110. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/api/services/preview_service.py +0 -0
  111. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/__init__.py +0 -0
  112. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/__main__.py +0 -0
  113. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shared_services/__init__.py +0 -0
  114. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shared_services/generation_ops.py +0 -0
  115. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shared_services/project_ops.py +0 -0
  116. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/__init__.py +0 -0
  117. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/__init__.py +0 -0
  118. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/__init__.py +0 -0
  119. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/agent_interaction.py +0 -0
  120. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/chat.py +0 -0
  121. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/delete.py +0 -0
  122. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/diff.py +0 -0
  123. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/display.py +0 -0
  124. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/executor.py +0 -0
  125. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/executor_utils.py +0 -0
  126. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/generate.py +0 -0
  127. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/interaction.py +0 -0
  128. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/migrate.py +0 -0
  129. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/resolver.py +0 -0
  130. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/status.py +0 -0
  131. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/switch.py +0 -0
  132. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/ai/utils.py +0 -0
  133. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/base.py +0 -0
  134. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/config/__init__.py +0 -0
  135. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/config/base.py +0 -0
  136. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/config/check.py +0 -0
  137. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/config/edit.py +0 -0
  138. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/config/get.py +0 -0
  139. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/config/init.py +0 -0
  140. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/config/inspect.py +0 -0
  141. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/config/list.py +0 -0
  142. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/config/set.py +0 -0
  143. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/config/show.py +0 -0
  144. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/exit.py +0 -0
  145. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/help.py +0 -0
  146. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/infer_schema.py +0 -0
  147. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/open.py +0 -0
  148. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/project.py +0 -0
  149. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/provider.py +0 -0
  150. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/system.py +0 -0
  151. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/commands/validate.py +0 -0
  152. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/completer.py +0 -0
  153. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/config_storage.py +0 -0
  154. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/exceptions.py +0 -0
  155. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/formatter.py +0 -0
  156. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/interactive_menu.py +0 -0
  157. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/main.py +0 -0
  158. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/shell/parser.py +0 -0
  159. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/cli/start.py +0 -0
  160. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/mcp_server.py +0 -0
  161. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/__init__.py +0 -0
  162. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/app_version.py +0 -0
  163. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/config/__init__.py +0 -0
  164. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/config/server.py +0 -0
  165. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/__init__.py +0 -0
  166. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loader.py +0 -0
  167. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loaders/__init__.py +0 -0
  168. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loaders/base.py +0 -0
  169. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loaders/converter.py +0 -0
  170. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loaders/csv_loader.py +0 -0
  171. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loaders/excel_loader.py +0 -0
  172. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loaders/extractor.py +0 -0
  173. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loaders/json_loader.py +0 -0
  174. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loaders/registry.py +0 -0
  175. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loaders/sql_loader.py +0 -0
  176. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loaders/strategies/__init__.py +0 -0
  177. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loaders/strategies/array_parser.py +0 -0
  178. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loaders/strategies/lines_parser.py +0 -0
  179. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/loaders/strategies/object_parser.py +0 -0
  180. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/schema_info.py +0 -0
  181. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/specs/__init__.py +0 -0
  182. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/specs/base.py +0 -0
  183. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/specs/csv_source.py +0 -0
  184. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/specs/excel_source.py +0 -0
  185. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/specs/file_base.py +0 -0
  186. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/specs/json_source.py +0 -0
  187. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/data_source/specs/sql_source.py +0 -0
  188. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/encoding.py +0 -0
  189. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/io/__init__.py +0 -0
  190. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/manifest_schema/__init__.py +0 -0
  191. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/manifest_schema/version.py +0 -0
  192. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/patterns/__init__.py +0 -0
  193. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/patterns/loader.py +0 -0
  194. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/patterns/writer.py +0 -0
  195. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/__init__.py +0 -0
  196. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/builders/__init__.py +0 -0
  197. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/builders/base.py +0 -0
  198. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/builders/composite.py +0 -0
  199. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/builders/conditional.py +0 -0
  200. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/builders/foreign_key.py +0 -0
  201. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/builders/registry.py +0 -0
  202. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/builders/scripted.py +0 -0
  203. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/builders/single_column.py +0 -0
  204. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/builders/unique.py +0 -0
  205. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/factory.py +0 -0
  206. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/reader.py +0 -0
  207. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/types/__init__.py +0 -0
  208. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/types/constraint_file.py +0 -0
  209. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/types/refs.py +0 -0
  210. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/types.py +0 -0
  211. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/constraint/writer.py +0 -0
  212. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/__init__.py +0 -0
  213. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/loader.py +0 -0
  214. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/loader_parts/config_inspector.py +0 -0
  215. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/loader_parts/embedded_constraints.py +0 -0
  216. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/loader_parts/file_loaders.py +0 -0
  217. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/loader_parts/inspection_ids.py +0 -0
  218. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/loader_parts/inspector_helpers.py +0 -0
  219. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/loader_parts/inspector_id_checks.py +0 -0
  220. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/loader_parts/inspector_reference_checks.py +0 -0
  221. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/loader_parts/inspector_uniqueness_checks.py +0 -0
  222. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/loader_parts/loading_error_messages.py +0 -0
  223. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/loader_parts/main.py +0 -0
  224. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/loader_parts/path_validation.py +0 -0
  225. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/loader_parts/runtime.py +0 -0
  226. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/loader/types.py +0 -0
  227. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/coverage.py +0 -0
  228. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/reader.py +0 -0
  229. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/types.py +0 -0
  230. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/types_parts/__init__.py +0 -0
  231. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/types_parts/constants.py +0 -0
  232. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/types_parts/data_source.py +0 -0
  233. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/types_parts/info.py +0 -0
  234. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/types_parts/manifest.py +0 -0
  235. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/types_parts/refs.py +0 -0
  236. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/types_parts/settings.py +0 -0
  237. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/types_parts/settings_file_processing.py +0 -0
  238. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/types_parts/settings_script_security.py +0 -0
  239. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/types_parts/settings_validation.py +0 -0
  240. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/types_parts/template.py +0 -0
  241. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manifest/writer.py +0 -0
  242. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manual_data/__init__.py +0 -0
  243. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/manual_data/types.py +0 -0
  244. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/regex/reader.py +0 -0
  245. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/regex/types.py +0 -0
  246. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/regex/writer.py +0 -0
  247. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/schema/reader.py +0 -0
  248. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/schema/types.py +0 -0
  249. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/schema/types_parts/__init__.py +0 -0
  250. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/schema/types_parts/column.py +0 -0
  251. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/schema/types_parts/column_utils.py +0 -0
  252. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/schema/types_parts/constraint.py +0 -0
  253. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/schema/types_parts/schema_id.py +0 -0
  254. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/schema/types_parts/source.py +0 -0
  255. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/schema/types_parts/source_options.py +0 -0
  256. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/schema/types_parts/table.py +0 -0
  257. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/schema/writer.py +0 -0
  258. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/schema_ref_check.py +0 -0
  259. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/template/__init__.py +0 -0
  260. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/template/expander.py +0 -0
  261. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/template/reader.py +0 -0
  262. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/template/types.py +0 -0
  263. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/transform/reader.py +0 -0
  264. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/transform/types.py +0 -0
  265. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/project/transform/writer.py +0 -0
  266. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/pydantic_messages.py +0 -0
  267. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/reporter/__init__.py +0 -0
  268. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/reporter/reporter.py +0 -0
  269. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/reporter/reporters/base.py +0 -0
  270. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/reporter/reporters/dingtalk_app_reporter.py +0 -0
  271. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/reporter/reporters/email_reporter.py +0 -0
  272. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/reporter/reporters/feishu_app_reporter.py +0 -0
  273. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/reporter/reporters/local_file_reporter.py +0 -0
  274. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/reporter/reporters/wecom_app_reporter.py +0 -0
  275. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/utils/__init__.py +0 -0
  276. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/utils/path_utils.py +0 -0
  277. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/core/utils/regex_extract.py +0 -0
  278. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/__init__.py +0 -0
  279. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/__init__.py +0 -0
  280. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/base.py +0 -0
  281. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/condition_registry.py +0 -0
  282. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/constraints/key_normalization.py +0 -0
  283. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/data_engine.py +0 -0
  284. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/data_types.py +0 -0
  285. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/data_types_parts/__init__.py +0 -0
  286. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/data_types_parts/base.py +0 -0
  287. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/data_types_parts/composite.py +0 -0
  288. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/data_types_parts/expression.py +0 -0
  289. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/data_types_parts/extracted.py +0 -0
  290. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/data_types_parts/json_types.py +0 -0
  291. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/data_types_parts/scalars.py +0 -0
  292. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/data_types_parts/sequence.py +0 -0
  293. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/dataset_schema.py +0 -0
  294. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/eval_sandbox.py +0 -0
  295. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/expression_system.py +0 -0
  296. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/regex_flags.py +0 -0
  297. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/schema/builder.py +0 -0
  298. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/schema/models.py +0 -0
  299. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/__init__.py +0 -0
  300. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/aggregate.py +0 -0
  301. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/base.py +0 -0
  302. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/cast_type.py +0 -0
  303. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/concat.py +0 -0
  304. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/conditional_assign.py +0 -0
  305. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/date_format.py +0 -0
  306. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/digits.py +0 -0
  307. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/drop_duplicates.py +0 -0
  308. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/fill_na.py +0 -0
  309. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/filter_rows.py +0 -0
  310. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/lookup.py +0 -0
  311. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/lower_case.py +0 -0
  312. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/map_value.py +0 -0
  313. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/math_expr.py +0 -0
  314. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/modulo.py +0 -0
  315. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/regex_extract.py +0 -0
  316. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/registry.py +0 -0
  317. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/replace.py +0 -0
  318. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/sort_rows.py +0 -0
  319. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/string_split.py +0 -0
  320. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/strip.py +0 -0
  321. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/substring.py +0 -0
  322. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/upper_case.py +0 -0
  323. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/transforms/weighted_sum.py +0 -0
  324. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/domain/validation_constraints.py +0 -0
  325. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/__init__.py +0 -0
  326. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/__init__.py +0 -0
  327. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/__init__.py +0 -0
  328. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/chat_tools/__init__.py +0 -0
  329. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/chat_tools/apply_actions.py +0 -0
  330. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/chat_tools/ask_user.py +0 -0
  331. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/chat_tools/read_canvas.py +0 -0
  332. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/chat_tools/read_project.py +0 -0
  333. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/chat_tools/read_table.py +0 -0
  334. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/chat_tools/schemas.py +0 -0
  335. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/chat_tools/validate_table.py +0 -0
  336. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/executor.py +0 -0
  337. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/memory.py +0 -0
  338. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/planner.py +0 -0
  339. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/tool_registry.py +0 -0
  340. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/tools/__init__.py +0 -0
  341. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/tools/config_generate.py +0 -0
  342. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/tools/config_refine.py +0 -0
  343. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/tools/config_validate.py +0 -0
  344. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/tools/merge_results.py +0 -0
  345. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/tools/plan_chunks.py +0 -0
  346. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/tools/script_parse.py +0 -0
  347. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/agent/types.py +0 -0
  348. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/chat_agent_runner.py +0 -0
  349. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/chat_orchestrator.py +0 -0
  350. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/failure_messages.py +0 -0
  351. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/job_storage.py +0 -0
  352. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/migrate_service.py +0 -0
  353. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/streaming/__init__.py +0 -0
  354. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/streaming/event_journal.py +0 -0
  355. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/streaming/orchestrator.py +0 -0
  356. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/streaming/pending_interaction_store.py +0 -0
  357. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/streaming/sse_response.py +0 -0
  358. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/streaming/types.py +0 -0
  359. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/ai/utils.py +0 -0
  360. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/diff/config_diff.py +0 -0
  361. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/hardware.py +0 -0
  362. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/__init__.py +0 -0
  363. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/__init__.py +0 -0
  364. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/_canvas_validator.py +0 -0
  365. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/_constraint_validator.py +0 -0
  366. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/_regex_validator.py +0 -0
  367. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/_schema_validator.py +0 -0
  368. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/_settings_validator.py +0 -0
  369. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/_transform_validator.py +0 -0
  370. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/action_handlers.py +0 -0
  371. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/action_parser.py +0 -0
  372. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/action_processor.py +0 -0
  373. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/action_validator.py +0 -0
  374. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/diff_compute.py +0 -0
  375. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/regex_handlers.py +0 -0
  376. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/registry.py +0 -0
  377. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/schema_handlers.py +0 -0
  378. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/settings_handlers.py +0 -0
  379. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/specs.py +0 -0
  380. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/transform_handlers.py +0 -0
  381. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/actions/validation_types.py +0 -0
  382. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/cache/__init__.py +0 -0
  383. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/cache/response_cache.py +0 -0
  384. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/chat/__init__.py +0 -0
  385. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/chat/chat_system_prompt.py +0 -0
  386. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/chat/response_parser.py +0 -0
  387. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/config/__init__.py +0 -0
  388. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/config/crypto.py +0 -0
  389. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/config/loader.py +0 -0
  390. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/config/models.py +0 -0
  391. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/config/presets.py +0 -0
  392. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/config_generator.py +0 -0
  393. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/constraints/__init__.py +0 -0
  394. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/constraints/constraint_builder.py +0 -0
  395. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/constraints/constraint_deletion.py +0 -0
  396. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/constraints/constraint_id.py +0 -0
  397. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/constraints/frontend_instructions.py +0 -0
  398. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/constraints/inline_batch.py +0 -0
  399. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/discovery/__init__.py +0 -0
  400. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/discovery/scanner.py +0 -0
  401. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/generation/__init__.py +0 -0
  402. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/generation/agent_wiring.py +0 -0
  403. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/generation/config_builder.py +0 -0
  404. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/generation/errors.py +0 -0
  405. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/generation/existing_config.py +0 -0
  406. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/generation/profiler.py +0 -0
  407. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/generation/prompt_builder.py +0 -0
  408. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/generation/response_parser.py +0 -0
  409. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/generation/service.py +0 -0
  410. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/providers/__init__.py +0 -0
  411. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/providers/base.py +0 -0
  412. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/providers/cached_provider.py +0 -0
  413. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/providers/fake.py +0 -0
  414. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/providers/ollama.py +0 -0
  415. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/providers/openai.py +0 -0
  416. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/providers/registry.py +0 -0
  417. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/schema_resolver.py +0 -0
  418. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/suggestion_utils.py +0 -0
  419. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/llm/validate_executor.py +0 -0
  420. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/preview/__init__.py +0 -0
  421. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/preview/loader.py +0 -0
  422. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/preview/path_validation.py +0 -0
  423. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/project_loader.py +0 -0
  424. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/schema_inference.py +0 -0
  425. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/schema_runtime_builder.py +0 -0
  426. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/__init__.py +0 -0
  427. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/chunked_loader.py +0 -0
  428. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/dag/__init__.py +0 -0
  429. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/dag/builder.py +0 -0
  430. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/dag/executor.py +0 -0
  431. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/dag/sorter.py +0 -0
  432. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/data_loader.py +0 -0
  433. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/engine.py +0 -0
  434. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/executor.py +0 -0
  435. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/extractors.py +0 -0
  436. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/history.py +0 -0
  437. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/json_payload.py +0 -0
  438. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/loader.py +0 -0
  439. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/memory_monitor.py +0 -0
  440. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/postprocess.py +0 -0
  441. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/progress.py +0 -0
  442. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/report_export.py +0 -0
  443. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/resolver.py +0 -0
  444. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/types.py +0 -0
  445. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/shared/services/validation/validators/__init__.py +0 -0
  446. {precis_cli-0.1.7 → precis_cli-0.1.8}/app/start_server.py +0 -0
  447. {precis_cli-0.1.7 → precis_cli-0.1.8}/precis_cli.egg-info/dependency_links.txt +0 -0
  448. {precis_cli-0.1.7 → precis_cli-0.1.8}/precis_cli.egg-info/entry_points.txt +0 -0
  449. {precis_cli-0.1.7 → precis_cli-0.1.8}/precis_cli.egg-info/requires.txt +0 -0
  450. {precis_cli-0.1.7 → precis_cli-0.1.8}/precis_cli.egg-info/top_level.txt +0 -0
  451. {precis_cli-0.1.7 → precis_cli-0.1.8}/setup.cfg +0 -0
  452. {precis_cli-0.1.7 → precis_cli-0.1.8}/tests/test_local_file_reporter.py +0 -0
  453. {precis_cli-0.1.7 → precis_cli-0.1.8}/tests/test_schema_builder.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: precis-cli
3
- Version: 0.1.7
3
+ Version: 0.1.8
4
4
  Summary: Precis - 可配置数据校验工具 CLI(校验 CSV/Excel/JSON 数据质量)
5
5
  Author: Precis Team
6
6
  License: Apache-2.0
@@ -36,6 +36,7 @@
36
36
 
37
37
  # backend/app/api/dependencies.py
38
38
  import os
39
+ from urllib.parse import quote, unquote
39
40
 
40
41
  from fastapi import Depends, Header, HTTPException
41
42
 
@@ -65,6 +66,44 @@ class ProjectStore:
65
66
  self.project_path = project_path
66
67
 
67
68
 
69
+ def _decode_header_path(value: str) -> str:
70
+ """还原 HTTP header 携带的非 ASCII 路径。
71
+
72
+ 两种线上契约并存,按特征识别、互不干扰:
73
+
74
+ 1. GUI 契约(axios/fetch):前端在出口处对路径做 encodeURIComponent(纯
75
+ ASCII 百分号转义)。浏览器 XHR/fetch 的 header 值只接受 ByteString
76
+ (ISO-8859-1),中文原值会被 XHR 直接拒绝;axios 1.18 的
77
+ toByteStringHeaderValue 还会把 latin1 之外的字符静默删除——不转义的
78
+ 中文路径会以"删字后的错误路径"上线且无从在服务端还原。判定是否为
79
+ 规范转义串用 round-trip 校验(quote(unquote(v)) == v),字面上含 % 的
80
+ 合法路径通常不会被误解码(例外:字面 "%XX" 恰为合法 UTF-8 转义序列
81
+ 的路径会被还原,随后走校验链报错而非指向任意目录)。round-trip 的
82
+ 转义集必须与 encodeURIComponent 的不转义集对齐:JS 保留
83
+ `!'()*` 五字符原样上线,校验端 quote 的 safe 集须包含它们,否则含
84
+ 括号/感叹号的中文路径(如 `D:/项目(备份)`)契约判定必败,被契约 2
85
+ 原样放行后以百分号串走校验链 400/404。
86
+ 2. TUI/脚本契约(reqwest FromBytes、curl 等):UTF-8 原始字节按 obs-text
87
+ 上线。ASGI 服务器把 header 字节按 latin-1 解码成乱码,latin-1 与字节流
88
+ 双射,编码回字节再按 UTF-8 解码即可无损还原;非 UTF-8 字节保持原值,
89
+ 交由后续校验链正常报错。
90
+ """
91
+ # 契约 1:规范百分号转义(GUI)。safe 集对齐 encodeURIComponent 的保留集
92
+ # (`!'()*`),Python quote 恒不转义字母数字与 `_.-~`,两者已一致
93
+ if "%" in value:
94
+ try:
95
+ decoded = unquote(value, errors="strict")
96
+ except UnicodeDecodeError:
97
+ decoded = None
98
+ if decoded is not None and decoded != value and quote(decoded, safe="!'()*") == value:
99
+ return decoded
100
+ # 契约 2:UTF-8 原始字节(TUI/脚本)
101
+ try:
102
+ return value.encode("latin-1").decode("utf-8")
103
+ except (UnicodeEncodeError, UnicodeDecodeError):
104
+ return value
105
+
106
+
68
107
  async def get_project_config_path(
69
108
  x_project_config_path: str = Header(..., description="项目根目录的绝对路径(须含 project.precis.yaml)"),
70
109
  ) -> str:
@@ -121,6 +160,9 @@ def _validate_project_root(raw_path: str | None) -> str:
121
160
  """
122
161
  if not raw_path:
123
162
  raise HTTPException(status_code=400, detail="X-Project-Config-Path header 不能为空。")
163
+ # 还原 header 编码乱码(见 _decode_header_path):中文路径经 UTF-8 上线、
164
+ # latin-1 解码后 isdir 必失败,必须先还原再做后续校验
165
+ raw_path = _decode_header_path(raw_path)
124
166
  # 步骤1:先校验原始输入是否为绝对路径
125
167
  # 在 Windows 下,os.path.abspath 会把相对路径(如 "../project")解析成绝对路径,
126
168
  # 导致后续 isabs 检查无法拒绝相对路径。因此必须在规范化之前先做判断。
@@ -438,6 +438,12 @@ class FullValidationErrorItem(BaseModel):
438
438
  source_sheet: str | None = Field(
439
439
  default=None, description="配置文件内定义的 Excel Sheet 名(可选)"
440
440
  ) # schema 配置中 source.sheet 定义的 Excel 工作表名称,可选
441
+ error_code: str | None = Field(
442
+ default=None, description="稳定错误码(UPPER_SNAKE),供前端映射 i18n key 按当前语言渲染"
443
+ ) # 与 message 同时给出:message 为后端默认语言的兜底文案
444
+ error_params: dict | None = Field(
445
+ default=None, description="错误码对应的插值参数(JSON 标量),如 {column: 'Total'}"
446
+ ) # 供前端 t(key, params) 插值
441
447
 
442
448
 
443
449
  class ValidationPassedItem(BaseModel):
@@ -257,6 +257,12 @@ class ValidationErrorRow(BaseModel):
257
257
  error_message: str | None = Field(
258
258
  None, description="错误信息"
259
259
  ) # 校验失败的具体错误描述,如"值不在允许列表中",可选
260
+ error_code: str | None = Field(
261
+ None, description="稳定错误码(UPPER_SNAKE),供前端映射 i18n key 按当前语言渲染"
262
+ ) # 与 error_message 同时给出:message 为后端默认语言的兜底文案
263
+ error_params: dict | None = Field(
264
+ None, description="错误码对应的插值参数(JSON 标量),如 {column: 'Total', row: 1}"
265
+ ) # 供前端 t(key, params) 插值
260
266
 
261
267
 
262
268
  class ValidationResult(BaseModel):
@@ -117,7 +117,11 @@ def diagnose_hardware() -> HardwareDiagnoseResponse:
117
117
  import subprocess
118
118
 
119
119
  result = subprocess.run(
120
- ["nvidia-smi", "--query-gpu=name,memory.total", "--format=csv,noheader"], capture_output=True, text=True
120
+ ["nvidia-smi", "--query-gpu=name,memory.total", "--format=csv,noheader"],
121
+ capture_output=True,
122
+ text=True,
123
+ encoding="utf-8",
124
+ errors="replace", # 中文 Windows 下 text=True 默认按 GBK 解码会乱码/抛错
121
125
  )
122
126
  if result.returncode == 0:
123
127
  for line in result.stdout.strip().split("\n"):
@@ -138,12 +138,19 @@ def expand_paths(
138
138
 
139
139
  数据文件类型:.xlsx, .xls, .csv, .json, .jsonl
140
140
  """
141
+ # 还原 header 线上编码(GUI 契约 percent-encode / TUI 原始 UTF-8 字节,见
142
+ # app.api.dependencies._decode_header_path):前端出口统一转义后,未解码的
143
+ # 百分号串作 base 解析相对路径会全 miss,中文项目下静默返回空列表
144
+ from app.api.dependencies import _decode_header_path
145
+
146
+ base_path = _decode_header_path(x_project_config_path) if x_project_config_path else None
147
+
141
148
  result = []
142
149
  seen = set()
143
150
 
144
151
  for raw_path in paths:
145
152
  # 1. 解析为绝对路径
146
- path = _resolve_path(raw_path, x_project_config_path)
153
+ path = _resolve_path(raw_path, base_path)
147
154
 
148
155
  # 2. 如果是目录,递归展开
149
156
  if os.path.isdir(path):
@@ -86,7 +86,7 @@ def load_workspace_config(project_root: str) -> dict[str, Any]:
86
86
  }
87
87
 
88
88
  try:
89
- with open(config_path, encoding="utf-8") as f:
89
+ with open(config_path, encoding="utf-8-sig") as f:
90
90
  return yaml.safe_load(f) or {}
91
91
  except Exception as e:
92
92
  raise HTTPException(
@@ -223,7 +223,7 @@ def get_reporting_config(store: ProjectStore = Depends(get_project_store)) -> Re
223
223
  )
224
224
  try:
225
225
  # 读取并解析 YAML 配置文件
226
- with open(config_path, encoding="utf-8") as f:
226
+ with open(config_path, encoding="utf-8-sig") as f:
227
227
  config_data = yaml.safe_load(f)
228
228
  return ReportingConfig(**config_data)
229
229
  except Exception as e:
@@ -106,7 +106,7 @@ def handle_header_row_changed(
106
106
 
107
107
  if os.path.exists(schema_path):
108
108
  try:
109
- with open(schema_path, encoding="utf-8") as f:
109
+ with open(schema_path, encoding="utf-8-sig") as f:
110
110
  schema_content = yaml.safe_load(f)
111
111
 
112
112
  if "header_row" not in schema_content:
@@ -67,7 +67,7 @@ def _load_yaml_file(path: str) -> dict:
67
67
  if not os.path.isfile(path):
68
68
  return {}
69
69
  try:
70
- with open(path, encoding="utf-8") as f:
70
+ with open(path, encoding="utf-8-sig") as f:
71
71
  return yaml.safe_load(f) or {}
72
72
  except yaml.YAMLError:
73
73
  return {}
@@ -36,7 +36,7 @@ def _get_project_name(project_path: str) -> str:
36
36
  """从 project.precis.yaml 中读取项目名称,失败时返回目录名。"""
37
37
  manifest_path = os.path.join(project_path, "project.precis.yaml")
38
38
  try:
39
- with open(manifest_path, encoding="utf-8") as f:
39
+ with open(manifest_path, encoding="utf-8-sig") as f:
40
40
  manifest = yaml.safe_load(f)
41
41
  if isinstance(manifest, dict):
42
42
  project = manifest.get("project", {})
@@ -69,7 +69,7 @@ def scan_projects(
69
69
  def _parse_project(project_path: str, manifest_path: str) -> ProjectInfo | None:
70
70
  """解析单个项目的 manifest 文件获取元信息。"""
71
71
  try:
72
- with open(manifest_path, encoding="utf-8") as f:
72
+ with open(manifest_path, encoding="utf-8-sig") as f:
73
73
  manifest = yaml.safe_load(f)
74
74
  except Exception:
75
75
  return None
@@ -189,11 +189,14 @@ def execute_dataframe_validation(
189
189
  )
190
190
 
191
191
  # 将原始错误行列表转换为标准化的 ValidationErrorRow 对象列表
192
+ # error_code/error_params 透传给前端,供按当前语言渲染错误文案
192
193
  error_rows = [
193
194
  ValidationErrorRow(
194
195
  row_index=err.get("row_index", 0),
195
196
  cell_value=str(err.get("cell_value", "")),
196
197
  error_message=err.get("error_message"),
198
+ error_code=err.get("error_code"),
199
+ error_params=err.get("error_params"),
197
200
  )
198
201
  for err in result.error_rows
199
202
  ]
@@ -150,6 +150,9 @@ class FullValidationResponseBuilder:
150
150
  source_path=err.get("source_path"),
151
151
  source_file=err.get("source_file"),
152
152
  source_sheet=err.get("source_sheet"),
153
+ # i18n:稳定错误码 + 插值参数透传,message 保留兜底文案
154
+ error_code=err.get("error_code"),
155
+ error_params=err.get("error_params"),
153
156
  )
154
157
  )
155
158
 
@@ -371,7 +371,7 @@ def set_config_value_in_file(project_path: str, filename: str, key_path: str, va
371
371
  yaml_parser.preserve_quotes = True
372
372
 
373
373
  try:
374
- with open(config_path, encoding="utf-8") as f:
374
+ with open(config_path, encoding="utf-8-sig") as f:
375
375
  data = yaml_parser.load(f)
376
376
  except RuamelYAMLError as e:
377
377
  return False, f"YAML 解析失败: {e}"
@@ -482,7 +482,7 @@ def load_config_content(project_path: str, filename: str) -> dict | str:
482
482
  if not config_path:
483
483
  return f"配置文件不存在: {filename}"
484
484
  try:
485
- with open(config_path, encoding="utf-8") as f:
485
+ with open(config_path, encoding="utf-8-sig") as f:
486
486
  content = yaml.safe_load(f)
487
487
  if content:
488
488
  return content if isinstance(content, dict) else str(content)
@@ -162,7 +162,9 @@ def read_yaml(path: Path) -> dict[str, Any]:
162
162
  :raises FileNotFoundError: 当指定路径的文件不存在时抛出
163
163
  :raises yaml.YAMLError: 当 YAML 格式错误时抛出
164
164
  """
165
- with open(path, encoding="utf-8") as f:
165
+ # utf-8-sig:兼容记事本等编辑器保存的"UTF-8 带 BOM"(BOM 若混入会被
166
+ # yaml 误认Control Character抛错);无 BOM 时解码行为与 utf-8 完全一致
167
+ with open(path, encoding="utf-8-sig") as f:
166
168
  return cast(dict[str, Any], yaml.safe_load(f))
167
169
 
168
170
 
@@ -100,6 +100,10 @@ CONSTRAINT_TYPE_ALIASES: dict[str, str] = {
100
100
  # 日期逻辑约束别名
101
101
  "datelogic": "DateLogic",
102
102
  "date_logic": "DateLogic",
103
+ # 字符集约束别名
104
+ "charset": "Charset",
105
+ # 复合约束别名
106
+ "composite": "Composite",
103
107
  }
104
108
 
105
109
 
@@ -27,7 +27,7 @@
27
27
 
28
28
  输入示例:
29
29
  从外部导入所需的报告器:
30
- from backend.app.shared.core.reporter.reporters import (
30
+ from app.shared.core.reporter.reporters import (
31
31
  Reporter, # 抽象基类,用于自定义报告器
32
32
  LocalFileReporter, # 本地文件报告器
33
33
  EmailReporter, # 邮件报告器
@@ -141,6 +141,8 @@ class AllowedValuesConstraint(Constraint):
141
141
  errors.append(
142
142
  {
143
143
  "error_type": "ConstraintConfigError",
144
+ "error_code": "ALLOWED_VALUES_TABLE_NOT_FOUND",
145
+ "error_params": {"table": self.table},
144
146
  "table": self.table,
145
147
  "column": self.column,
146
148
  "message": f"允许值约束失败: 表 '{self.table}' 不在数据集中。",
@@ -155,6 +157,8 @@ class AllowedValuesConstraint(Constraint):
155
157
  errors.append(
156
158
  {
157
159
  "error_type": "ConstraintConfigError",
160
+ "error_code": "ALLOWED_VALUES_COLUMN_NOT_FOUND",
161
+ "error_params": {"column": self.column, "table": self.table},
158
162
  "table": self.table,
159
163
  "column": self.column,
160
164
  "message": f"允许值约束失败: 列 '{self.column}' 在表 '{self.table}' 中不存在。",
@@ -194,6 +198,8 @@ class AllowedValuesConstraint(Constraint):
194
198
  row_index = int(index) if index is not None else 0
195
199
  error: dict[str, Any] = {
196
200
  "error_type": "AllowedValuesViolation",
201
+ "error_code": "ALLOWED_VALUES_NOT_PERMITTED",
202
+ "error_params": {"value": str(value), "allowed": str(self.allowed_values)},
197
203
  "table": self.table,
198
204
  "row_index": row_index,
199
205
  "column": self.column,
@@ -149,6 +149,8 @@ class CharsetConstraint(Constraint):
149
149
  errors.append(
150
150
  {
151
151
  "error_type": "ConstraintConfigError",
152
+ "error_code": "CHARSET_TABLE_NOT_FOUND",
153
+ "error_params": {"table": self.table},
152
154
  "table": self.table,
153
155
  "column": self.column,
154
156
  "message": f"字符集约束失败: 表 '{self.table}' 不在数据集中。",
@@ -163,6 +165,8 @@ class CharsetConstraint(Constraint):
163
165
  errors.append(
164
166
  {
165
167
  "error_type": "ConstraintConfigError",
168
+ "error_code": "CHARSET_COLUMN_NOT_FOUND",
169
+ "error_params": {"column": self.column, "table": self.table},
166
170
  "table": self.table,
167
171
  "column": self.column,
168
172
  "message": f"字符集约束失败: 列 '{self.column}' 在表 '{self.table}' 中不存在。",
@@ -186,6 +190,11 @@ class CharsetConstraint(Constraint):
186
190
  errors.append(
187
191
  {
188
192
  "error_type": "ConstraintConfigError",
193
+ "error_code": "CHARSET_INVALID_MODE",
194
+ "error_params": {
195
+ "charset_mode": self.charset_mode,
196
+ "valid_modes": ", ".join(sorted(valid_modes)),
197
+ },
189
198
  "table": self.table,
190
199
  "column": self.column,
191
200
  "message": (
@@ -216,6 +225,12 @@ class CharsetConstraint(Constraint):
216
225
  errors.append(
217
226
  {
218
227
  "error_type": "CharsetViolation",
228
+ "error_code": "CHARSET_INVALID_CHARACTER",
229
+ "error_params": {
230
+ "value": cell_value_str,
231
+ "charset_mode": self.charset_mode,
232
+ "charset_name": charset_name,
233
+ },
219
234
  "table": self.table,
220
235
  "row_index": int(index) if index is not None else 0,
221
236
  "column": self.column,
@@ -138,6 +138,8 @@ class CompositeConstraint(Constraint):
138
138
  final_errors = [
139
139
  {
140
140
  "error_type": "CompositeConstraint",
141
+ "error_code": "COMPOSITE_ANY_ALL_FAILED",
142
+ "error_params": {"total": len(sub_results)},
141
143
  "message": (
142
144
  f"复合约束(logic=any)要求至少一个子约束通过,但全部 {len(sub_results)} 个子约束均失败"
143
145
  ),
@@ -151,6 +153,8 @@ class CompositeConstraint(Constraint):
151
153
  final_errors = [
152
154
  {
153
155
  "error_type": "CompositeConstraint",
156
+ "error_code": "COMPOSITE_NONE_HAS_PASSED",
157
+ "error_params": {"passed": passed_count},
154
158
  "message": (f"复合约束(logic=none)要求全部子约束失败,但有 {passed_count} 个子约束通过"),
155
159
  "table": self.table,
156
160
  }
@@ -352,6 +352,8 @@ class ConditionalConstraint(Constraint):
352
352
  errors.append(
353
353
  {
354
354
  "error_type": "ConstraintConfigError",
355
+ "error_code": "CONDITIONAL_TABLE_NOT_FOUND",
356
+ "error_params": {"table": self.table},
355
357
  "table": self.table,
356
358
  "column": self.then_column,
357
359
  "message": f"条件约束失败: 表 '{self.table}' 不在数据集中。",
@@ -366,6 +368,8 @@ class ConditionalConstraint(Constraint):
366
368
  errors.append(
367
369
  {
368
370
  "error_type": "ConstraintConfigError",
371
+ "error_code": "CONDITIONAL_COLUMN_NOT_FOUND",
372
+ "error_params": {"column": self.then_column, "table": self.table},
369
373
  "table": self.table,
370
374
  "column": self.then_column,
371
375
  "message": f"条件约束失败: 列 '{self.then_column}' 不在表 '{self.table}' 中。",
@@ -382,6 +386,8 @@ class ConditionalConstraint(Constraint):
382
386
  errors.append(
383
387
  {
384
388
  "error_type": "ConstraintConfigError",
389
+ "error_code": "CONDITIONAL_REF_COLUMN_NOT_FOUND",
390
+ "error_params": {"column": ref_col, "table": self.table},
385
391
  "table": self.table,
386
392
  "column": ref_col,
387
393
  "message": f"条件约束失败: 引用列 '{ref_col}' 不在表 '{self.table}' 中。",
@@ -406,6 +412,13 @@ class ConditionalConstraint(Constraint):
406
412
  errors.append(
407
413
  {
408
414
  "error_type": "ConstraintConfigError",
415
+ "error_code": "CONDITIONAL_THEN_THRESHOLD_NOT_NUMERIC",
416
+ "error_params": {
417
+ "operator": _then_op,
418
+ "threshold": str(_then_threshold),
419
+ "column": self.then_column,
420
+ "table": self.table,
421
+ },
409
422
  "table": self.table,
410
423
  "column": self.then_column,
411
424
  "message": (
@@ -494,6 +507,8 @@ class ConditionalConstraint(Constraint):
494
507
  errors.append(
495
508
  {
496
509
  "error_type": "ConstraintConfigError",
510
+ "error_code": "CONDITIONAL_UNKNOWN_IF_LOGIC",
511
+ "error_params": {"if_logic": self.if_logic},
497
512
  "table": self.table,
498
513
  "message": f"条件约束失败: 未知的 if_logic '{self.if_logic}',支持的值为: and, or。",
499
514
  }
@@ -506,6 +521,8 @@ class ConditionalConstraint(Constraint):
506
521
  errors.append(
507
522
  {
508
523
  "error_type": "ConstraintConfigError",
524
+ "error_code": "CONDITIONAL_IF_COLUMN_NOT_FOUND",
525
+ "error_params": {"column": missing, "table": self.table},
509
526
  "table": self.table,
510
527
  "column": missing,
511
528
  "message": f"条件约束失败: 列 '{missing}' 不在表 '{self.table}' 中。",
@@ -516,6 +533,8 @@ class ConditionalConstraint(Constraint):
516
533
  errors.append(
517
534
  {
518
535
  "error_type": "ConstraintConfigError",
536
+ "error_code": "CONDITIONAL_INVALID_IF_CONDITION",
537
+ "error_params": {"detail": str(e)},
519
538
  "table": self.table,
520
539
  "message": f"条件约束失败: {e}",
521
540
  }
@@ -540,6 +559,8 @@ class ConditionalConstraint(Constraint):
540
559
  errors.append(
541
560
  {
542
561
  "error_type": "ConstraintConfigError",
562
+ "error_code": "CONDITIONAL_IF_COLUMN_NOT_FOUND",
563
+ "error_params": {"column": self.if_column, "table": self.table},
543
564
  "table": self.table,
544
565
  "column": self.if_column,
545
566
  "message": f"条件约束失败: 列 '{self.if_column}' 不在表 '{self.table}' 中。",
@@ -552,6 +573,8 @@ class ConditionalConstraint(Constraint):
552
573
  errors.append(
553
574
  {
554
575
  "error_type": "ConstraintConfigError",
576
+ "error_code": "CONDITIONAL_IF_VALUE_MISSING",
577
+ "error_params": {"if_column": self.if_column},
555
578
  "table": self.table,
556
579
  "column": self.if_column,
557
580
  "message": (
@@ -580,6 +603,8 @@ class ConditionalConstraint(Constraint):
580
603
  errors.append(
581
604
  {
582
605
  "error_type": "Timeout",
606
+ "error_code": "CONDITIONAL_TIMEOUT",
607
+ "error_params": {"processed": i, "total": len(triggered_dict)},
583
608
  "stage": "constraint",
584
609
  "table": self.table,
585
610
  "message": (
@@ -619,6 +644,12 @@ class ConditionalConstraint(Constraint):
619
644
  errors.append(
620
645
  {
621
646
  "error_type": "ConditionalViolation",
647
+ "error_code": "CONDITIONAL_THEN_VIOLATION",
648
+ "error_params": {
649
+ "column": self.then_column,
650
+ "value": str(value_to_check),
651
+ "condition": self._condition_str,
652
+ },
622
653
  "table": self.table,
623
654
  "row_index": row_index,
624
655
  "value": {**if_value_payload, self.then_column: value_to_check},