algo-cli-runtime 0.14.0__py3-none-any.whl

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 (237) hide show
  1. algo_cli/__init__.py +3 -0
  2. algo_cli/__main__.py +7 -0
  3. algo_cli/_internal/__init__.py +12 -0
  4. algo_cli/_internal/policy_chain.py +259 -0
  5. algo_cli/action_registry.py +1047 -0
  6. algo_cli/agent_blocks.py +550 -0
  7. algo_cli/agent_pipeline.py +1457 -0
  8. algo_cli/agent_threads.py +308 -0
  9. algo_cli/animations.py +316 -0
  10. algo_cli/cache_admission.py +209 -0
  11. algo_cli/capability_mask.py +66 -0
  12. algo_cli/chat_protocol.py +116 -0
  13. algo_cli/chatgpt_auth.py +510 -0
  14. algo_cli/chatgpt_client.py +657 -0
  15. algo_cli/code_rag.py +479 -0
  16. algo_cli/config.py +651 -0
  17. algo_cli/context_budget.py +679 -0
  18. algo_cli/credential_helpers.py +315 -0
  19. algo_cli/deliberation.py +29 -0
  20. algo_cli/display.py +1470 -0
  21. algo_cli/evals/__init__.py +21 -0
  22. algo_cli/evals/algorithm_effectiveness.py +560 -0
  23. algo_cli/evals/competitive_harness_rating.py +702 -0
  24. algo_cli/evals/cot_quality.py +220 -0
  25. algo_cli/evals/harness_retrieval_benchmark.py +401 -0
  26. algo_cli/evals/performance_regression.py +136 -0
  27. algo_cli/evals/scorecard_grading.py +308 -0
  28. algo_cli/evals/session_distribution.py +84 -0
  29. algo_cli/execution_guardrails.py +806 -0
  30. algo_cli/extensions_manifest.py +84 -0
  31. algo_cli/git_evidence.py +227 -0
  32. algo_cli/google_workspace.py +407 -0
  33. algo_cli/google_workspace_auth.py +523 -0
  34. algo_cli/harness.py +2587 -0
  35. algo_cli/identity.py +557 -0
  36. algo_cli/index_compute_lab.py +228 -0
  37. algo_cli/inference_harness.py +70 -0
  38. algo_cli/intelligence/__init__.py +1103 -0
  39. algo_cli/intelligence/acrobat_config.py +307 -0
  40. algo_cli/intelligence/acrobat_manifests.py +338 -0
  41. algo_cli/intelligence/acrobat_models.py +195 -0
  42. algo_cli/intelligence/acrobat_pipeline.py +295 -0
  43. algo_cli/intelligence/acrobat_runtime.py +302 -0
  44. algo_cli/intelligence/acrobat_security.py +261 -0
  45. algo_cli/intelligence/acrobat_workflows.py +226 -0
  46. algo_cli/intelligence/actionability.py +165 -0
  47. algo_cli/intelligence/adversarial_audit.py +136 -0
  48. algo_cli/intelligence/agent_arena.py +92 -0
  49. algo_cli/intelligence/agent_benchmark.py +236 -0
  50. algo_cli/intelligence/agent_runtime.py +171 -0
  51. algo_cli/intelligence/agents_as_tools.py +70 -0
  52. algo_cli/intelligence/artifact_binding.py +80 -0
  53. algo_cli/intelligence/autonomous_engineer.py +1976 -0
  54. algo_cli/intelligence/backpressure.py +99 -0
  55. algo_cli/intelligence/bloom_filter.py +186 -0
  56. algo_cli/intelligence/bonferroni.py +66 -0
  57. algo_cli/intelligence/boundary_compaction.py +98 -0
  58. algo_cli/intelligence/catalog_verifier.py +172 -0
  59. algo_cli/intelligence/cavecrew.py +118 -0
  60. algo_cli/intelligence/changelog.py +176 -0
  61. algo_cli/intelligence/checkpoint_resume.py +92 -0
  62. algo_cli/intelligence/circuit_breaker.py +88 -0
  63. algo_cli/intelligence/clarification_gate.py +101 -0
  64. algo_cli/intelligence/code_graph.py +180 -0
  65. algo_cli/intelligence/coderank.py +97 -0
  66. algo_cli/intelligence/consistent_hash.py +150 -0
  67. algo_cli/intelligence/consortium_synthesis.py +139 -0
  68. algo_cli/intelligence/construction/__init__.py +241 -0
  69. algo_cli/intelligence/construction/common.py +273 -0
  70. algo_cli/intelligence/construction/documents.py +496 -0
  71. algo_cli/intelligence/construction/labor_units.py +1395 -0
  72. algo_cli/intelligence/construction/payments.py +470 -0
  73. algo_cli/intelligence/construction/risk.py +784 -0
  74. algo_cli/intelligence/content_extractor.py +132 -0
  75. algo_cli/intelligence/context_adaptive.py +102 -0
  76. algo_cli/intelligence/context_ops.py +95 -0
  77. algo_cli/intelligence/count_min.py +145 -0
  78. algo_cli/intelligence/cow_state.py +103 -0
  79. algo_cli/intelligence/critic_loop.py +119 -0
  80. algo_cli/intelligence/cross_source.py +113 -0
  81. algo_cli/intelligence/daemon_mode.py +99 -0
  82. algo_cli/intelligence/dag_orchestration.py +151 -0
  83. algo_cli/intelligence/deep_research.py +155 -0
  84. algo_cli/intelligence/degenerate_detector.py +78 -0
  85. algo_cli/intelligence/delta_report.py +92 -0
  86. algo_cli/intelligence/discovery_event_log.py +92 -0
  87. algo_cli/intelligence/document_ingest.py +298 -0
  88. algo_cli/intelligence/dual_layer_validate.py +151 -0
  89. algo_cli/intelligence/echo_fidelity.py +73 -0
  90. algo_cli/intelligence/ema_tuning.py +104 -0
  91. algo_cli/intelligence/event_log.py +92 -0
  92. algo_cli/intelligence/evidence_graph.py +114 -0
  93. algo_cli/intelligence/extension_host.py +162 -0
  94. algo_cli/intelligence/extension_manifest.py +115 -0
  95. algo_cli/intelligence/falsification_suite.py +178 -0
  96. algo_cli/intelligence/finance/__init__.py +169 -0
  97. algo_cli/intelligence/finance/anomalies.py +135 -0
  98. algo_cli/intelligence/finance/ap_ar.py +351 -0
  99. algo_cli/intelligence/finance/cash.py +162 -0
  100. algo_cli/intelligence/finance/close.py +332 -0
  101. algo_cli/intelligence/finance/common.py +244 -0
  102. algo_cli/intelligence/finance/construction.py +135 -0
  103. algo_cli/intelligence/finance/controls.py +172 -0
  104. algo_cli/intelligence/finance/evidence.py +119 -0
  105. algo_cli/intelligence/finance/exceptions.py +157 -0
  106. algo_cli/intelligence/finance/reconciliations.py +254 -0
  107. algo_cli/intelligence/finance/revenue.py +109 -0
  108. algo_cli/intelligence/finance/tax.py +74 -0
  109. algo_cli/intelligence/finance/workpapers.py +111 -0
  110. algo_cli/intelligence/finding_record.py +120 -0
  111. algo_cli/intelligence/flow_dag.py +267 -0
  112. algo_cli/intelligence/gatherer.py +223 -0
  113. algo_cli/intelligence/golden_master.py +98 -0
  114. algo_cli/intelligence/graph_rag.py +195 -0
  115. algo_cli/intelligence/group_chat.py +143 -0
  116. algo_cli/intelligence/hash_dedup.py +145 -0
  117. algo_cli/intelligence/hyperloglog.py +128 -0
  118. algo_cli/intelligence/incremental_index.py +316 -0
  119. algo_cli/intelligence/index_store.py +16 -0
  120. algo_cli/intelligence/iteration_plan.py +133 -0
  121. algo_cli/intelligence/kernel_plugins.py +167 -0
  122. algo_cli/intelligence/lesson_catalog.py +135 -0
  123. algo_cli/intelligence/llm_fallback.py +169 -0
  124. algo_cli/intelligence/log2_histogram.py +267 -0
  125. algo_cli/intelligence/lsp_integration.py +147 -0
  126. algo_cli/intelligence/memory_evolution.py +117 -0
  127. algo_cli/intelligence/minhash_lsh.py +182 -0
  128. algo_cli/intelligence/multi_model_score.py +174 -0
  129. algo_cli/intelligence/multi_tier_grade.py +211 -0
  130. algo_cli/intelligence/negative_controls.py +113 -0
  131. algo_cli/intelligence/numeric_clamp.py +63 -0
  132. algo_cli/intelligence/occ_editor.py +66 -0
  133. algo_cli/intelligence/output_normalize.py +112 -0
  134. algo_cli/intelligence/parallel_delegation.py +98 -0
  135. algo_cli/intelligence/parallel_fanout.py +104 -0
  136. algo_cli/intelligence/permission_modes.py +105 -0
  137. algo_cli/intelligence/pre_push_gate.py +68 -0
  138. algo_cli/intelligence/prefetch.py +171 -0
  139. algo_cli/intelligence/process_framework.py +217 -0
  140. algo_cli/intelligence/project_graph.py +387 -0
  141. algo_cli/intelligence/query_expansion.py +146 -0
  142. algo_cli/intelligence/ralph_loop.py +117 -0
  143. algo_cli/intelligence/rate_limiter.py +153 -0
  144. algo_cli/intelligence/refactor_transaction.py +94 -0
  145. algo_cli/intelligence/research_workspace.py +108 -0
  146. algo_cli/intelligence/retraction_ledger.py +72 -0
  147. algo_cli/intelligence/saga_pattern.py +88 -0
  148. algo_cli/intelligence/session_fork.py +100 -0
  149. algo_cli/intelligence/shadow_editor.py +67 -0
  150. algo_cli/intelligence/shell_session.py +213 -0
  151. algo_cli/intelligence/source_registry.py +143 -0
  152. algo_cli/intelligence/spawn_scales.py +99 -0
  153. algo_cli/intelligence/stat_stability.py +104 -0
  154. algo_cli/intelligence/structural_validator.py +148 -0
  155. algo_cli/intelligence/subagent_spawner.py +111 -0
  156. algo_cli/intelligence/symmetric_verify.py +70 -0
  157. algo_cli/intelligence/task_classifier.py +129 -0
  158. algo_cli/intelligence/team_execution.py +122 -0
  159. algo_cli/intelligence/tiered_access.py +121 -0
  160. algo_cli/intelligence/utility_registry.py +159 -0
  161. algo_cli/intuition_engine.py +560 -0
  162. algo_cli/intuition_injector.py +82 -0
  163. algo_cli/kernels/__init__.py +5 -0
  164. algo_cli/kernels/manifest.py +763 -0
  165. algo_cli/main.py +3903 -0
  166. algo_cli/memory_candidates.py +541 -0
  167. algo_cli/memory_echo_veil.py +394 -0
  168. algo_cli/memory_runtime.py +112 -0
  169. algo_cli/model_info.py +548 -0
  170. algo_cli/model_profile.py +160 -0
  171. algo_cli/model_routing.py +74 -0
  172. algo_cli/oneshot.py +331 -0
  173. algo_cli/perf_telemetry.py +389 -0
  174. algo_cli/plugins.py +245 -0
  175. algo_cli/private_event_store.py +654 -0
  176. algo_cli/quantization/__init__.py +24 -0
  177. algo_cli/quantization/lloyd_max.py +98 -0
  178. algo_cli/quantization/turbo_quant.py +308 -0
  179. algo_cli/reasoning/__init__.py +46 -0
  180. algo_cli/reasoning/combinatorial.py +356 -0
  181. algo_cli/reasoning/graph_of_thought.py +297 -0
  182. algo_cli/reasoning/mcts.py +220 -0
  183. algo_cli/reasoning/neuro_symbolic.py +250 -0
  184. algo_cli/reasoning/react.py +246 -0
  185. algo_cli/reasoning/reflexion.py +225 -0
  186. algo_cli/reasoning/tree_of_thought.py +241 -0
  187. algo_cli/reasoning_bridge.py +150 -0
  188. algo_cli/reconciliation.py +284 -0
  189. algo_cli/reflex.py +385 -0
  190. algo_cli/resources/docs/ALGO.md +13958 -0
  191. algo_cli/resources/docs/algo-cli-algorithm-evidence-contract.md +60 -0
  192. algo_cli/resources/docs/algo-cli-execution-verification-contract.md +59 -0
  193. algo_cli/resources/docs/algo-cli-memory-lifecycle-contract.md +72 -0
  194. algo_cli/resources/docs/harness-extension-cleanup-recommendation.md +41 -0
  195. algo_cli/resources/docs/index-compute-lab-integration.md +32 -0
  196. algo_cli/resources/docs/inference-harness-loop-blueprint-2026-06.md +55 -0
  197. algo_cli/resources/docs/main-split-map.md +35 -0
  198. algo_cli/resources/docs/privacy-and-context.md +48 -0
  199. algo_cli/resources/docs/reflex-loop-v0.2.md +354 -0
  200. algo_cli/resources/skills/README.md +26 -0
  201. algo_cli/resources/skills/algo-cli.md +59 -0
  202. algo_cli/resources/skills/edit-file-precision.md +49 -0
  203. algo_cli/resources/skills/harness-search-first.md +47 -0
  204. algo_cli/resources/skills/memory-recall-ritual.md +51 -0
  205. algo_cli/resources/skills/qol-algorithms.md +224 -0
  206. algo_cli/resources/skills/smart-error-recovery.md +56 -0
  207. algo_cli/resources/skills/tool-selection-cheatsheet.md +65 -0
  208. algo_cli/retrieval_algorithms.py +127 -0
  209. algo_cli/runtime_qos.py +236 -0
  210. algo_cli/runtime_services.py +320 -0
  211. algo_cli/session_commands.py +95 -0
  212. algo_cli/session_mode.py +113 -0
  213. algo_cli/skills.py +430 -0
  214. algo_cli/slash_dispatch.py +1265 -0
  215. algo_cli/small_context.py +206 -0
  216. algo_cli/spawn_budget.py +89 -0
  217. algo_cli/task_ledger.py +84 -0
  218. algo_cli/task_router.py +197 -0
  219. algo_cli/tool_context.py +94 -0
  220. algo_cli/tool_contract.py +99 -0
  221. algo_cli/tool_policy.py +357 -0
  222. algo_cli/tool_runtime.py +647 -0
  223. algo_cli/tools.py +3056 -0
  224. algo_cli/url_scheme.py +174 -0
  225. algo_cli/verify.py +154 -0
  226. algo_cli/version_manifest.py +178 -0
  227. algo_cli/vision_screenshot_verify.py +76 -0
  228. algo_cli/workspace_resolver.py +68 -0
  229. algo_cli/x_account.py +209 -0
  230. algo_cli/xai_auth.py +374 -0
  231. algo_cli/xai_client.py +600 -0
  232. algo_cli_runtime-0.14.0.dist-info/METADATA +369 -0
  233. algo_cli_runtime-0.14.0.dist-info/RECORD +237 -0
  234. algo_cli_runtime-0.14.0.dist-info/WHEEL +4 -0
  235. algo_cli_runtime-0.14.0.dist-info/entry_points.txt +3 -0
  236. algo_cli_runtime-0.14.0.dist-info/licenses/LICENSE +21 -0
  237. ollama_cli/__init__.py +67 -0
@@ -0,0 +1,241 @@
1
+ """Construction contracts / subcontracts / independent-contractor patterns B106-B126."""
2
+
3
+ from .labor_units import (
4
+ BUILDING_HEIGHT_FACTORS,
5
+ CONCEALED_FACTORS,
6
+ LADDER_HEIGHT_FACTORS,
7
+ LABOR_COMPOSITION,
8
+ REPETITIVE_FACTORS,
9
+ RESIDENTIAL_DEFAULTS,
10
+ ChartSituation,
11
+ CrewSizeEstimate,
12
+ LaborAdjustmentChart,
13
+ LaborFactorScoreSheet,
14
+ LaborUnit,
15
+ LaborUnitDatabase,
16
+ ScoreCondition,
17
+ SearchResult,
18
+ build_database,
19
+ building_height_adjustment,
20
+ crew_size_curve,
21
+ crew_size_straight_line,
22
+ difficulty_from_chart_score,
23
+ difficulty_from_score,
24
+ durand_core_multiplier,
25
+ durand_horizontal_setup_hours,
26
+ durand_vertical_multiplier,
27
+ ladder_height_adjustment,
28
+ non_working_supervision,
29
+ repetitive_adjustment,
30
+ residential_minutes,
31
+ )
32
+ from .common import (
33
+ ClauseHit,
34
+ ConstructionIssue,
35
+ Deadline,
36
+ Jurisdiction,
37
+ PatternResult,
38
+ ProjectType,
39
+ ProjectUse,
40
+ ReviewGate,
41
+ RiskLevel,
42
+ SourceRef,
43
+ add_business_days,
44
+ add_months_approx,
45
+ contains_any,
46
+ decimalize,
47
+ hash_source_bytes,
48
+ make_issue,
49
+ normalize_label,
50
+ normalize_space,
51
+ parse_date,
52
+ stable_issue_id,
53
+ )
54
+ from .documents import (
55
+ ContractDocument,
56
+ ContractDocumentGraph,
57
+ ContractDocumentGraphCompiler,
58
+ DelegatedDesignGate,
59
+ DelegatedDesignItem,
60
+ DelegatedDesignResult,
61
+ DisputeProtocol,
62
+ DisputeProtocolExtractor,
63
+ DocumentEdge,
64
+ FlowDownObligation,
65
+ FlowDownResult,
66
+ FlowDownRiskMapper,
67
+ LowerTierFlowdownPack,
68
+ LowerTierFlowdownResult,
69
+ LowerTierGap,
70
+ ScopeAtom,
71
+ ScopeMatrix,
72
+ ScopeMatrixBuilder,
73
+ ScopeStatus,
74
+ )
75
+ from .payments import (
76
+ ChangeEvent,
77
+ ChangeNotice,
78
+ ChangeNoticeEngine,
79
+ ChangeNoticeResult,
80
+ ContingentPaymentReview,
81
+ ContingentPaymentRiskGate,
82
+ ContingentPaymentType,
83
+ LienBondDeadlineCalendar,
84
+ LienWaiverClassifier,
85
+ LienWaiverReview,
86
+ PayApplication,
87
+ PaymentAnalysis,
88
+ PaymentRetainageAnalyzer,
89
+ RightsCalendar,
90
+ WaiverType,
91
+ )
92
+ from .risk import (
93
+ BackchargeDocumentationGate,
94
+ BackchargeReview,
95
+ ClassificationFactor,
96
+ CloseoutItem,
97
+ CloseoutMatrix,
98
+ ContractRedFlagQueue,
99
+ CoverageGap,
100
+ CureGate,
101
+ DelayAccelerationAnalyzer,
102
+ DelayAnalysis,
103
+ DelayEvent,
104
+ IndemnityInsuranceRiskSplitter,
105
+ IndemnityScope,
106
+ IndependentContractorClassifier,
107
+ InsuranceRequirement,
108
+ InsuranceRiskResult,
109
+ JurisdictionOverlayResult,
110
+ JurisdictionOverlayRouter,
111
+ OSHAEmployerRole,
112
+ OSHAMultiEmployerClassifier,
113
+ OnboardingCompliancePack,
114
+ OnboardingPackResult,
115
+ OnboardingRequirement,
116
+ OverlayRoute,
117
+ RedFlag,
118
+ RedFlagQueueResult,
119
+ SafetyEvent,
120
+ SafetyRoleResult,
121
+ TerminationDefaultGate,
122
+ TerminationMode,
123
+ WarrantyCloseoutMatrix,
124
+ WorkerClassificationResult,
125
+ )
126
+
127
+ __all__ = [
128
+ "LaborUnit",
129
+ "LaborUnitDatabase",
130
+ "SearchResult",
131
+ "build_database",
132
+ "difficulty_from_score",
133
+ "difficulty_from_chart_score",
134
+ "building_height_adjustment",
135
+ "ladder_height_adjustment",
136
+ "repetitive_adjustment",
137
+ "residential_minutes",
138
+ "ChartSituation",
139
+ "CrewSizeEstimate",
140
+ "LaborAdjustmentChart",
141
+ "LaborFactorScoreSheet",
142
+ "ScoreCondition",
143
+ "crew_size_curve",
144
+ "crew_size_straight_line",
145
+ "durand_core_multiplier",
146
+ "durand_horizontal_setup_hours",
147
+ "durand_vertical_multiplier",
148
+ "non_working_supervision",
149
+ "BUILDING_HEIGHT_FACTORS",
150
+ "LADDER_HEIGHT_FACTORS",
151
+ "CONCEALED_FACTORS",
152
+ "REPETITIVE_FACTORS",
153
+ "LABOR_COMPOSITION",
154
+ "RESIDENTIAL_DEFAULTS",
155
+ "ClauseHit",
156
+ "ConstructionIssue",
157
+ "Deadline",
158
+ "Jurisdiction",
159
+ "PatternResult",
160
+ "ProjectType",
161
+ "ProjectUse",
162
+ "ReviewGate",
163
+ "RiskLevel",
164
+ "SourceRef",
165
+ "add_business_days",
166
+ "add_months_approx",
167
+ "contains_any",
168
+ "decimalize",
169
+ "hash_source_bytes",
170
+ "make_issue",
171
+ "normalize_label",
172
+ "normalize_space",
173
+ "parse_date",
174
+ "stable_issue_id",
175
+ "ContractDocument",
176
+ "ContractDocumentGraph",
177
+ "ContractDocumentGraphCompiler",
178
+ "DelegatedDesignGate",
179
+ "DelegatedDesignItem",
180
+ "DelegatedDesignResult",
181
+ "DisputeProtocol",
182
+ "DisputeProtocolExtractor",
183
+ "DocumentEdge",
184
+ "FlowDownObligation",
185
+ "FlowDownResult",
186
+ "FlowDownRiskMapper",
187
+ "LowerTierFlowdownPack",
188
+ "LowerTierFlowdownResult",
189
+ "LowerTierGap",
190
+ "ScopeAtom",
191
+ "ScopeMatrix",
192
+ "ScopeMatrixBuilder",
193
+ "ScopeStatus",
194
+ "ChangeEvent",
195
+ "ChangeNotice",
196
+ "ChangeNoticeEngine",
197
+ "ChangeNoticeResult",
198
+ "ContingentPaymentReview",
199
+ "ContingentPaymentRiskGate",
200
+ "ContingentPaymentType",
201
+ "LienBondDeadlineCalendar",
202
+ "LienWaiverClassifier",
203
+ "LienWaiverReview",
204
+ "PayApplication",
205
+ "PaymentAnalysis",
206
+ "PaymentRetainageAnalyzer",
207
+ "RightsCalendar",
208
+ "WaiverType",
209
+ "BackchargeDocumentationGate",
210
+ "BackchargeReview",
211
+ "ClassificationFactor",
212
+ "CloseoutItem",
213
+ "CloseoutMatrix",
214
+ "ContractRedFlagQueue",
215
+ "CoverageGap",
216
+ "CureGate",
217
+ "DelayAccelerationAnalyzer",
218
+ "DelayAnalysis",
219
+ "DelayEvent",
220
+ "IndemnityInsuranceRiskSplitter",
221
+ "IndemnityScope",
222
+ "IndependentContractorClassifier",
223
+ "InsuranceRequirement",
224
+ "InsuranceRiskResult",
225
+ "JurisdictionOverlayResult",
226
+ "JurisdictionOverlayRouter",
227
+ "OSHAEmployerRole",
228
+ "OSHAMultiEmployerClassifier",
229
+ "OnboardingCompliancePack",
230
+ "OnboardingPackResult",
231
+ "OnboardingRequirement",
232
+ "OverlayRoute",
233
+ "RedFlag",
234
+ "RedFlagQueueResult",
235
+ "SafetyEvent",
236
+ "SafetyRoleResult",
237
+ "TerminationDefaultGate",
238
+ "TerminationMode",
239
+ "WarrantyCloseoutMatrix",
240
+ "WorkerClassificationResult",
241
+ ]
@@ -0,0 +1,273 @@
1
+ """Shared contracts for construction contract intelligence patterns B106-B126."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import re
7
+ from dataclasses import dataclass, field
8
+ from datetime import date, datetime, timedelta
9
+ from decimal import Decimal, InvalidOperation
10
+ from enum import Enum
11
+ from typing import Any, Iterable, Mapping
12
+
13
+
14
+ class RiskLevel(str, Enum):
15
+ """Coarse risk levels used by construction contract analyzers."""
16
+
17
+ LOW = "low"
18
+ MEDIUM = "medium"
19
+ HIGH = "high"
20
+ CRITICAL = "critical"
21
+
22
+
23
+ class ReviewGate(str, Enum):
24
+ """Human-review gates for consequential construction-contract actions."""
25
+
26
+ NONE = "none"
27
+ BUSINESS_REVIEW = "business_review"
28
+ ATTORNEY_REVIEW = "attorney_review"
29
+ INSURANCE_REVIEW = "insurance_review"
30
+ TAX_HR_REVIEW = "tax_hr_review"
31
+ SAFETY_REVIEW = "safety_review"
32
+ STOP_EXTERNAL_ACTION = "stop_external_action"
33
+
34
+
35
+ class ProjectType(str, Enum):
36
+ """Project routing used for lien/bond/payment overlays."""
37
+
38
+ PRIVATE = "private"
39
+ PUBLIC = "public"
40
+ FEDERAL = "federal"
41
+ UNKNOWN = "unknown"
42
+
43
+
44
+ class ProjectUse(str, Enum):
45
+ """Commercial/residential routing where statutes differ."""
46
+
47
+ COMMERCIAL = "commercial"
48
+ RESIDENTIAL = "residential"
49
+ UNKNOWN = "unknown"
50
+
51
+
52
+ @dataclass(frozen=True)
53
+ class SourceRef:
54
+ """Reference to a clause, document, row, or supporting artifact."""
55
+
56
+ document: str
57
+ clause: str | None = None
58
+ page: int | None = None
59
+ row: int | None = None
60
+ quote: str | None = None
61
+ url: str | None = None
62
+ document_hash: str | None = None
63
+
64
+
65
+ @dataclass(frozen=True)
66
+ class ConstructionIssue:
67
+ """A contract issue/red flag produced by a pattern engine."""
68
+
69
+ id: str
70
+ pattern_id: str
71
+ title: str
72
+ message: str
73
+ risk_level: RiskLevel = RiskLevel.MEDIUM
74
+ review_gate: ReviewGate = ReviewGate.BUSINESS_REVIEW
75
+ source_refs: tuple[SourceRef, ...] = ()
76
+ tags: frozenset[str] = frozenset()
77
+ amount: Decimal | None = None
78
+ deadline: date | None = None
79
+
80
+ @property
81
+ def requires_human_review(self) -> bool:
82
+ return self.review_gate is not ReviewGate.NONE
83
+
84
+
85
+ @dataclass(frozen=True)
86
+ class Jurisdiction:
87
+ """State/project context for contract overlays."""
88
+
89
+ state: str | None = None
90
+ county: str | None = None
91
+ city: str | None = None
92
+ project_type: ProjectType = ProjectType.UNKNOWN
93
+ project_use: ProjectUse = ProjectUse.UNKNOWN
94
+ tier: str | None = None
95
+
96
+ @property
97
+ def normalized_state(self) -> str | None:
98
+ if not self.state:
99
+ return None
100
+ value = self.state.strip().upper()
101
+ aliases = {"KANSAS": "KS", "MISSOURI": "MO", "FEDERAL": "FEDERAL"}
102
+ return aliases.get(value, value)
103
+
104
+ @property
105
+ def is_kansas_private(self) -> bool:
106
+ return self.normalized_state == "KS" and self.project_type is ProjectType.PRIVATE
107
+
108
+ @property
109
+ def is_federal(self) -> bool:
110
+ return self.project_type is ProjectType.FEDERAL or self.normalized_state == "FEDERAL"
111
+
112
+
113
+ @dataclass(frozen=True)
114
+ class Deadline:
115
+ """A computed review deadline. Not a legal deadline/sign-off."""
116
+
117
+ name: str
118
+ due_date: date
119
+ source: str
120
+ pattern_id: str
121
+ review_gate: ReviewGate = ReviewGate.ATTORNEY_REVIEW
122
+ confidence: str = "review"
123
+ notes: tuple[str, ...] = ()
124
+
125
+
126
+ @dataclass(frozen=True)
127
+ class ClauseHit:
128
+ """A simple keyword/regex extraction hit."""
129
+
130
+ label: str
131
+ text: str
132
+ source_ref: SourceRef
133
+
134
+
135
+ @dataclass
136
+ class PatternResult:
137
+ """Generic result envelope for construction pattern engines."""
138
+
139
+ pattern_id: str
140
+ issues: list[ConstructionIssue] = field(default_factory=list)
141
+ source_refs: list[SourceRef] = field(default_factory=list)
142
+ review_gate: ReviewGate = ReviewGate.BUSINESS_REVIEW
143
+
144
+ @property
145
+ def requires_human_review(self) -> bool:
146
+ return self.review_gate is not ReviewGate.NONE or any(issue.requires_human_review for issue in self.issues)
147
+
148
+
149
+ def decimalize(value: Any, default: Decimal = Decimal("0")) -> Decimal:
150
+ """Parse construction dollar/percent-ish numeric values safely."""
151
+
152
+ if value is None:
153
+ return default
154
+ if isinstance(value, Decimal):
155
+ return value
156
+ if isinstance(value, int):
157
+ return Decimal(value)
158
+ if isinstance(value, float):
159
+ return Decimal(str(value))
160
+ text = str(value).strip()
161
+ if not text:
162
+ return default
163
+ negative = text.startswith("(") and text.endswith(")")
164
+ text = text.strip("()")
165
+ text = text.replace("$", "").replace(",", "").replace("%", "")
166
+ try:
167
+ number = Decimal(text)
168
+ except (InvalidOperation, ValueError):
169
+ return default
170
+ return -number if negative else number
171
+
172
+
173
+ def parse_date(value: Any) -> date | None:
174
+ """Parse common date forms used in tests/imports."""
175
+
176
+ if value is None:
177
+ return None
178
+ if isinstance(value, date) and not isinstance(value, datetime):
179
+ return value
180
+ if isinstance(value, datetime):
181
+ return value.date()
182
+ text = str(value).strip()
183
+ if not text:
184
+ return None
185
+ for fmt in ("%Y-%m-%d", "%m/%d/%Y", "%m/%d/%y"):
186
+ try:
187
+ return datetime.strptime(text, fmt).date()
188
+ except ValueError:
189
+ continue
190
+ try:
191
+ return datetime.fromisoformat(text).date()
192
+ except ValueError:
193
+ return None
194
+
195
+
196
+ def add_business_days(start: date, days: int) -> date:
197
+ """Add business days, skipping Saturday/Sunday."""
198
+
199
+ current = start
200
+ remaining = days
201
+ step = 1 if days >= 0 else -1
202
+ while remaining:
203
+ current += timedelta(days=step)
204
+ if current.weekday() < 5:
205
+ remaining -= step
206
+ return current
207
+
208
+
209
+ def add_months_approx(start: date, months: int) -> date:
210
+ """Add months while clamping day to the target month length."""
211
+
212
+ month_index = start.month - 1 + months
213
+ year = start.year + month_index // 12
214
+ month = month_index % 12 + 1
215
+ month_lengths = [31, 29 if year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) else 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
216
+ return date(year, month, min(start.day, month_lengths[month - 1]))
217
+
218
+
219
+ def hash_source_bytes(data: bytes) -> str:
220
+ return hashlib.sha256(data).hexdigest()[:16]
221
+
222
+
223
+ def normalize_space(text: str) -> str:
224
+ return re.sub(r"\s+", " ", text or "").strip()
225
+
226
+
227
+ def normalize_label(text: str) -> str:
228
+ return re.sub(r"[^a-z0-9]+", "_", (text or "").strip().lower()).strip("_")
229
+
230
+
231
+ def contains_any(text: str, terms: Iterable[str]) -> bool:
232
+ haystack = (text or "").lower()
233
+ return any(term.lower() in haystack for term in terms)
234
+
235
+
236
+ def stable_issue_id(pattern_id: str, *parts: object) -> str:
237
+ payload = "|".join(str(part) for part in (pattern_id, *parts))
238
+ return f"{pattern_id.lower()}-{hashlib.sha1(payload.encode('utf-8')).hexdigest()[:10]}"
239
+
240
+
241
+ def make_issue(
242
+ pattern_id: str,
243
+ title: str,
244
+ message: str,
245
+ *,
246
+ risk_level: RiskLevel = RiskLevel.MEDIUM,
247
+ review_gate: ReviewGate = ReviewGate.BUSINESS_REVIEW,
248
+ source_refs: Iterable[SourceRef] = (),
249
+ tags: Iterable[str] = (),
250
+ amount: Decimal | str | int | None = None,
251
+ deadline: date | None = None,
252
+ ) -> ConstructionIssue:
253
+ parsed_amount = decimalize(amount) if amount is not None else None
254
+ return ConstructionIssue(
255
+ id=stable_issue_id(pattern_id, title, message, deadline or ""),
256
+ pattern_id=pattern_id,
257
+ title=title,
258
+ message=message,
259
+ risk_level=risk_level,
260
+ review_gate=review_gate,
261
+ source_refs=tuple(source_refs),
262
+ tags=frozenset(tags),
263
+ amount=parsed_amount,
264
+ deadline=deadline,
265
+ )
266
+
267
+
268
+ def source_from_mapping(data: Mapping[str, Any], default_doc: str = "input") -> tuple[SourceRef, ...]:
269
+ refs = data.get("source_refs")
270
+ if refs:
271
+ return tuple(ref for ref in refs if isinstance(ref, SourceRef))
272
+ document = str(data.get("document") or default_doc)
273
+ return (SourceRef(document, clause=data.get("clause"), quote=data.get("text") or data.get("quote")),)