millforge 0.1.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.
- millforge/__init__.py +1174 -0
- millforge/_forge/LICENSE +21 -0
- millforge/_forge/PROVENANCE.json +295 -0
- millforge/_forge/UPDATE_POLICY.md +24 -0
- millforge/_forge/__init__.py +14 -0
- millforge/_forge/adapter.py +2232 -0
- millforge/_forge/base_runner.py +121 -0
- millforge/_forge/clients/__init__.py +10 -0
- millforge/_forge/clients/base.py +200 -0
- millforge/_forge/context/__init__.py +23 -0
- millforge/_forge/context/manager.py +178 -0
- millforge/_forge/context/strategies.py +335 -0
- millforge/_forge/core/__init__.py +16 -0
- millforge/_forge/core/inference.py +433 -0
- millforge/_forge/core/messages.py +119 -0
- millforge/_forge/core/runner.py +479 -0
- millforge/_forge/core/steps.py +108 -0
- millforge/_forge/core/workflow.py +400 -0
- millforge/_forge/errors.py +222 -0
- millforge/_forge/guardrails/__init__.py +21 -0
- millforge/_forge/guardrails/error_tracker.py +71 -0
- millforge/_forge/guardrails/guardrails.py +194 -0
- millforge/_forge/guardrails/nudge.py +47 -0
- millforge/_forge/guardrails/response_validator.py +119 -0
- millforge/_forge/guardrails/step_enforcer.py +183 -0
- millforge/_forge/prompts/__init__.py +16 -0
- millforge/_forge/prompts/nudges.py +95 -0
- millforge/_forge/prompts/templates.py +285 -0
- millforge/_version.py +3 -0
- millforge/artifacts.py +570 -0
- millforge/base/__init__.py +97 -0
- millforge/base/composition.py +402 -0
- millforge/base/context.py +285 -0
- millforge/base/harness.py +138 -0
- millforge/base/identity.py +465 -0
- millforge/base/options.py +34 -0
- millforge/base/platform.py +17 -0
- millforge/base/prompt.py +317 -0
- millforge/base/runner.py +546 -0
- millforge/compiled_plan.py +970 -0
- millforge/compiler/__init__.py +231 -0
- millforge/compiler/artifact_validation.py +257 -0
- millforge/compiler/canonicalization.py +169 -0
- millforge/compiler/capabilities.py +66 -0
- millforge/compiler/catalogs.py +500 -0
- millforge/compiler/diagnostics.py +491 -0
- millforge/compiler/graph.py +678 -0
- millforge/compiler/lowering.py +198 -0
- millforge/compiler/output.py +692 -0
- millforge/compiler/parsing.py +1424 -0
- millforge/compiler/requests.py +1180 -0
- millforge/compiler/schema_validation.py +272 -0
- millforge/compiler/semantic.py +490 -0
- millforge/compiler/service.py +448 -0
- millforge/compiler/source.py +375 -0
- millforge/compiler/validators.py +184 -0
- millforge/connectors/__init__.py +95 -0
- millforge/connectors/admission.py +801 -0
- millforge/connectors/broker.py +202 -0
- millforge/connectors/contracts.py +1159 -0
- millforge/connectors/diagnostics.py +189 -0
- millforge/connectors/fake.py +66 -0
- millforge/connectors/runtime.py +236 -0
- millforge/contracts.py +2860 -0
- millforge/custom_tools/__init__.py +67 -0
- millforge/custom_tools/compiler.py +724 -0
- millforge/custom_tools/contracts.py +1093 -0
- millforge/custom_tools/diagnostics.py +205 -0
- millforge/eval_artifacts.py +952 -0
- millforge/eval_boundary.py +2435 -0
- millforge/eval_fixtures/__init__.py +1 -0
- millforge/eval_fixtures/default_pack/__init__.py +1 -0
- millforge/eval_fixtures/default_pack/fixtures/fixture.08a.bug_diagnosis.traceback.v1.json +52 -0
- millforge/eval_fixtures/default_pack/fixtures/fixture.08a.direct_edit.import_sort.v1.json +52 -0
- millforge/eval_fixtures/default_pack/fixtures/fixture.08a.evidence_discipline.no_source_change.v1.json +51 -0
- millforge/eval_fixtures/default_pack/fixtures/fixture.08a.false_closure.visible_green.v1.json +52 -0
- millforge/eval_fixtures/default_pack/fixtures/fixture.08a.multi_file.api_contract.v1.json +54 -0
- millforge/eval_fixtures/default_pack/fixtures/fixture.08a.recovery.malformed_artifact.v1.json +54 -0
- millforge/eval_fixtures/default_pack/manifest.json +12 -0
- millforge/eval_modes.py +1282 -0
- millforge/eval_presets.py +1398 -0
- millforge/eval_reports.py +2517 -0
- millforge/eval_suite.py +2429 -0
- millforge/eval_trials.py +2632 -0
- millforge/eval_workflow.py +794 -0
- millforge/exceptions.py +122 -0
- millforge/model_backend.py +2098 -0
- millforge/protocols.py +340 -0
- millforge/py.typed +0 -0
- millforge/runtime.py +1791 -0
- millforge/testing/__init__.py +1089 -0
- millforge/tools/__init__.py +83 -0
- millforge/tools/builtin_runtime.py +1339 -0
- millforge/tools/builtins.py +773 -0
- millforge/tools/execution.py +1545 -0
- millforge/tools/path_policy.py +155 -0
- millforge/tools/pi_compat/PI_LICENSE +21 -0
- millforge/tools/pi_compat/PROVENANCE.json +55 -0
- millforge/tools/pi_compat/UPDATE_POLICY.md +36 -0
- millforge/tools/pi_compat/__init__.py +34 -0
- millforge/tools/pi_compat/contracts.py +49 -0
- millforge/tools/pi_compat/editing.py +390 -0
- millforge/tools/pi_compat/mutations.py +57 -0
- millforge/tools/pi_compat/operations.py +401 -0
- millforge/tools/pi_compat/paths.py +155 -0
- millforge/tools/pi_compat/process.py +1375 -0
- millforge/tools/pi_compat/search.py +738 -0
- millforge/tools/pi_compat/truncation.py +267 -0
- millforge/tools/pi_compat_catalog.py +396 -0
- millforge/tools/pi_compat_runtime.py +460 -0
- millforge/tools/registry.py +553 -0
- millforge/tools/results.py +533 -0
- millforge-0.1.0.dist-info/METADATA +844 -0
- millforge-0.1.0.dist-info/RECORD +116 -0
- millforge-0.1.0.dist-info/WHEEL +4 -0
- millforge-0.1.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
"""Default validated compiler service orchestration."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Mapping
|
|
6
|
+
from typing import Protocol
|
|
7
|
+
|
|
8
|
+
from millforge import canonical_json_serialize, verify_compiled_plan_sha256
|
|
9
|
+
from millforge.compiled_plan import CompiledHarnessPlan
|
|
10
|
+
from millforge.compiled_plan import calculate_compiled_plan_sha256
|
|
11
|
+
from millforge.compiler.catalogs import (
|
|
12
|
+
ModelProfileCatalogSnapshot,
|
|
13
|
+
ToolCatalogSnapshot,
|
|
14
|
+
)
|
|
15
|
+
from millforge.compiler.canonicalization import source_sha256
|
|
16
|
+
from millforge.compiler.diagnostics import (
|
|
17
|
+
CompilerDiagnostic,
|
|
18
|
+
CompilerPhase,
|
|
19
|
+
DiagnosticField,
|
|
20
|
+
DiagnosticSeverity,
|
|
21
|
+
bound_diagnostics,
|
|
22
|
+
)
|
|
23
|
+
from millforge.compiler.lowering import (
|
|
24
|
+
CompiledPlanValidationError,
|
|
25
|
+
LoweringInvariantError,
|
|
26
|
+
SourceSemanticHashError,
|
|
27
|
+
lower_resolved_harness,
|
|
28
|
+
)
|
|
29
|
+
from millforge.compiler.output import persist_compile_outputs
|
|
30
|
+
from millforge.compiler.parsing import ParsedHarnessSource
|
|
31
|
+
from millforge.compiler.requests import (
|
|
32
|
+
CompileStatus,
|
|
33
|
+
DefaultHarnessCompileRequestAdmission,
|
|
34
|
+
HarnessCompileRequest,
|
|
35
|
+
HarnessCompileRequestAdmission,
|
|
36
|
+
HarnessCompileResult,
|
|
37
|
+
HarnessRequestAdmissionResult,
|
|
38
|
+
PlanCommitCertainty,
|
|
39
|
+
_post_parse_source_diagnostics,
|
|
40
|
+
)
|
|
41
|
+
from millforge.compiler.source import HarnessSource
|
|
42
|
+
from millforge.compiler.semantic import ResolvedHarness, compile_semantic_from_admission
|
|
43
|
+
from millforge.contracts import CapabilityEnvelope
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class HarnessCompiler(Protocol):
|
|
47
|
+
"""Public typed compiler service boundary."""
|
|
48
|
+
|
|
49
|
+
def compile(
|
|
50
|
+
self,
|
|
51
|
+
request: HarnessCompileRequest,
|
|
52
|
+
*,
|
|
53
|
+
tool_catalog: ToolCatalogSnapshot,
|
|
54
|
+
model_profile_catalog: ModelProfileCatalogSnapshot,
|
|
55
|
+
) -> HarnessCompileResult:
|
|
56
|
+
"""Compile an admitted harness request."""
|
|
57
|
+
...
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class InMemoryHarnessCompileError(Exception):
|
|
61
|
+
"""Raised when a validated in-memory harness source cannot compile."""
|
|
62
|
+
|
|
63
|
+
diagnostics: tuple[CompilerDiagnostic, ...]
|
|
64
|
+
|
|
65
|
+
def __init__(self, diagnostics: tuple[CompilerDiagnostic, ...]) -> None:
|
|
66
|
+
self.diagnostics = tuple(
|
|
67
|
+
diagnostic.model_copy(update={"source_reference": None})
|
|
68
|
+
for diagnostic in bound_diagnostics(diagnostics)
|
|
69
|
+
)
|
|
70
|
+
super().__init__(
|
|
71
|
+
self.diagnostics[0].message
|
|
72
|
+
if self.diagnostics
|
|
73
|
+
else "in-memory harness compilation failed"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def compile(
|
|
78
|
+
request: HarnessCompileRequest,
|
|
79
|
+
*,
|
|
80
|
+
tool_catalog: ToolCatalogSnapshot,
|
|
81
|
+
model_profile_catalog: ModelProfileCatalogSnapshot,
|
|
82
|
+
) -> HarnessCompileResult:
|
|
83
|
+
"""Compile an admitted request through semantic validation, lowering, and output."""
|
|
84
|
+
return _compile_validated(
|
|
85
|
+
request,
|
|
86
|
+
tool_catalog=tool_catalog,
|
|
87
|
+
model_profile_catalog=model_profile_catalog,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def compile_harness_source_in_memory(
|
|
92
|
+
*,
|
|
93
|
+
request_id: str,
|
|
94
|
+
source: HarnessSource,
|
|
95
|
+
stage_kind_id: str,
|
|
96
|
+
legal_terminal_results: tuple[str, ...],
|
|
97
|
+
capability_envelope: CapabilityEnvelope,
|
|
98
|
+
tool_catalog: ToolCatalogSnapshot,
|
|
99
|
+
model_profile_catalog: ModelProfileCatalogSnapshot,
|
|
100
|
+
) -> CompiledHarnessPlan:
|
|
101
|
+
"""Compile a validated harness source without filesystem admission or publication."""
|
|
102
|
+
request = HarnessCompileRequest(
|
|
103
|
+
request_id=request_id,
|
|
104
|
+
source_path="in-memory",
|
|
105
|
+
source_root="/",
|
|
106
|
+
source_format="json",
|
|
107
|
+
output_dir="in-memory",
|
|
108
|
+
output_root="/",
|
|
109
|
+
expected_harness_id=source.harness_id,
|
|
110
|
+
stage_kind_id=stage_kind_id,
|
|
111
|
+
legal_terminal_results=legal_terminal_results,
|
|
112
|
+
capability_envelope=capability_envelope,
|
|
113
|
+
)
|
|
114
|
+
parsed_source = ParsedHarnessSource(
|
|
115
|
+
source=source,
|
|
116
|
+
source_document_sha256="0" * 64,
|
|
117
|
+
)
|
|
118
|
+
diagnostics = _post_parse_source_diagnostics(
|
|
119
|
+
request=request,
|
|
120
|
+
parsed=parsed_source,
|
|
121
|
+
)
|
|
122
|
+
if diagnostics:
|
|
123
|
+
raise InMemoryHarnessCompileError(diagnostics)
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
outcome = _compile_post_parse(
|
|
127
|
+
HarnessRequestAdmissionResult(
|
|
128
|
+
request=request,
|
|
129
|
+
parsed_source=parsed_source,
|
|
130
|
+
),
|
|
131
|
+
tool_catalog=tool_catalog,
|
|
132
|
+
model_profile_catalog=model_profile_catalog,
|
|
133
|
+
)
|
|
134
|
+
except Exception as exc:
|
|
135
|
+
raise InMemoryHarnessCompileError(
|
|
136
|
+
(
|
|
137
|
+
_diagnostic(
|
|
138
|
+
"MF-I001",
|
|
139
|
+
CompilerPhase.INTERNAL,
|
|
140
|
+
"Compiler service failed internally.",
|
|
141
|
+
fields={"error_type": type(exc).__name__},
|
|
142
|
+
),
|
|
143
|
+
)
|
|
144
|
+
) from exc
|
|
145
|
+
if isinstance(outcome, HarnessCompileResult):
|
|
146
|
+
raise InMemoryHarnessCompileError(outcome.diagnostics)
|
|
147
|
+
return outcome
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _compile_validated(
|
|
151
|
+
request: HarnessCompileRequest,
|
|
152
|
+
*,
|
|
153
|
+
tool_catalog: ToolCatalogSnapshot,
|
|
154
|
+
model_profile_catalog: ModelProfileCatalogSnapshot,
|
|
155
|
+
) -> HarnessCompileResult:
|
|
156
|
+
"""Private implementation for the public typed compiler entry point."""
|
|
157
|
+
try:
|
|
158
|
+
admission = DefaultHarnessCompileRequestAdmission().admit(
|
|
159
|
+
request.model_dump(mode="python")
|
|
160
|
+
)
|
|
161
|
+
return _compile_admitted(
|
|
162
|
+
admission,
|
|
163
|
+
tool_catalog=tool_catalog,
|
|
164
|
+
model_profile_catalog=model_profile_catalog,
|
|
165
|
+
)
|
|
166
|
+
except Exception as exc:
|
|
167
|
+
return _failed_result(
|
|
168
|
+
request=request,
|
|
169
|
+
phase=CompilerPhase.INTERNAL,
|
|
170
|
+
diagnostics=(
|
|
171
|
+
_diagnostic(
|
|
172
|
+
"MF-I001",
|
|
173
|
+
CompilerPhase.INTERNAL,
|
|
174
|
+
"Compiler service failed internally.",
|
|
175
|
+
fields={"error_type": type(exc).__name__},
|
|
176
|
+
),
|
|
177
|
+
),
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def compile_raw(
|
|
182
|
+
raw_request: Mapping[str, object],
|
|
183
|
+
*,
|
|
184
|
+
tool_catalog: ToolCatalogSnapshot,
|
|
185
|
+
model_profile_catalog: ModelProfileCatalogSnapshot,
|
|
186
|
+
admission: HarnessCompileRequestAdmission | None = None,
|
|
187
|
+
) -> HarnessCompileResult:
|
|
188
|
+
"""Admit a raw request, then compile through the validated typed service."""
|
|
189
|
+
admitted = (admission or DefaultHarnessCompileRequestAdmission()).admit(raw_request)
|
|
190
|
+
if admitted.result is None and admitted.request is not None:
|
|
191
|
+
request = admitted.request
|
|
192
|
+
else:
|
|
193
|
+
request = HarnessCompileRequest.model_construct(
|
|
194
|
+
request_id="request.invalid",
|
|
195
|
+
source_path="invalid",
|
|
196
|
+
source_root="/",
|
|
197
|
+
source_format="json",
|
|
198
|
+
output_dir="invalid",
|
|
199
|
+
output_root="/",
|
|
200
|
+
expected_harness_id="millforge.invalid",
|
|
201
|
+
stage_kind_id="builder",
|
|
202
|
+
legal_terminal_results=("BLOCKED",),
|
|
203
|
+
capability_envelope={"grants": ()},
|
|
204
|
+
)
|
|
205
|
+
try:
|
|
206
|
+
return _compile_admitted(
|
|
207
|
+
admitted,
|
|
208
|
+
tool_catalog=tool_catalog,
|
|
209
|
+
model_profile_catalog=model_profile_catalog,
|
|
210
|
+
)
|
|
211
|
+
except Exception as exc:
|
|
212
|
+
return _failed_result(
|
|
213
|
+
request=request,
|
|
214
|
+
phase=CompilerPhase.INTERNAL,
|
|
215
|
+
diagnostics=(
|
|
216
|
+
_diagnostic(
|
|
217
|
+
"MF-I001",
|
|
218
|
+
CompilerPhase.INTERNAL,
|
|
219
|
+
"Compiler service failed internally.",
|
|
220
|
+
fields={"error_type": type(exc).__name__},
|
|
221
|
+
),
|
|
222
|
+
),
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _compile_admitted(
|
|
227
|
+
admission: HarnessRequestAdmissionResult,
|
|
228
|
+
*,
|
|
229
|
+
tool_catalog: ToolCatalogSnapshot,
|
|
230
|
+
model_profile_catalog: ModelProfileCatalogSnapshot,
|
|
231
|
+
) -> HarnessCompileResult:
|
|
232
|
+
if admission.result is not None:
|
|
233
|
+
return admission.result
|
|
234
|
+
assert admission.request is not None
|
|
235
|
+
assert admission.parsed_source is not None
|
|
236
|
+
outcome = _compile_post_parse(
|
|
237
|
+
admission,
|
|
238
|
+
tool_catalog=tool_catalog,
|
|
239
|
+
model_profile_catalog=model_profile_catalog,
|
|
240
|
+
)
|
|
241
|
+
if isinstance(outcome, HarnessCompileResult):
|
|
242
|
+
return outcome
|
|
243
|
+
return persist_compile_outputs(
|
|
244
|
+
request=admission.request,
|
|
245
|
+
plan=outcome,
|
|
246
|
+
source_document_sha256=admission.parsed_source.source_document_sha256,
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def _compile_post_parse(
|
|
251
|
+
admission: HarnessRequestAdmissionResult,
|
|
252
|
+
*,
|
|
253
|
+
tool_catalog: ToolCatalogSnapshot,
|
|
254
|
+
model_profile_catalog: ModelProfileCatalogSnapshot,
|
|
255
|
+
) -> CompiledHarnessPlan | HarnessCompileResult:
|
|
256
|
+
"""Run the shared semantic, lowering, and compiled-hash phases."""
|
|
257
|
+
assert admission.request is not None
|
|
258
|
+
assert admission.parsed_source is not None
|
|
259
|
+
source = admission.parsed_source.source
|
|
260
|
+
semantic = compile_semantic_from_admission(
|
|
261
|
+
admission,
|
|
262
|
+
source,
|
|
263
|
+
tool_snapshot=tool_catalog,
|
|
264
|
+
model_profile_snapshot=model_profile_catalog,
|
|
265
|
+
)
|
|
266
|
+
if semantic.frontend_result is not None:
|
|
267
|
+
return semantic.frontend_result
|
|
268
|
+
if semantic.resolved_harness is None or semantic.diagnostics:
|
|
269
|
+
return _failed_result(
|
|
270
|
+
request=admission.request,
|
|
271
|
+
phase=_failure_phase(semantic.diagnostics),
|
|
272
|
+
diagnostics=semantic.diagnostics
|
|
273
|
+
or (
|
|
274
|
+
_diagnostic(
|
|
275
|
+
"MF-I001",
|
|
276
|
+
CompilerPhase.INTERNAL,
|
|
277
|
+
"Semantic compilation returned no resolved harness.",
|
|
278
|
+
),
|
|
279
|
+
),
|
|
280
|
+
source_document_sha256=admission.parsed_source.source_document_sha256,
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
try:
|
|
284
|
+
plan = lower_resolved_harness(semantic.resolved_harness)
|
|
285
|
+
except SourceSemanticHashError as exc:
|
|
286
|
+
return _failed_result(
|
|
287
|
+
request=admission.request,
|
|
288
|
+
phase=CompilerPhase.LOWERING,
|
|
289
|
+
diagnostics=(
|
|
290
|
+
_diagnostic(
|
|
291
|
+
"MF-L003",
|
|
292
|
+
CompilerPhase.LOWERING,
|
|
293
|
+
"Source semantic hash calculation failed during lowering.",
|
|
294
|
+
fields={"error_type": type(exc).__name__},
|
|
295
|
+
),
|
|
296
|
+
),
|
|
297
|
+
source_document_sha256=admission.parsed_source.source_document_sha256,
|
|
298
|
+
)
|
|
299
|
+
except CompiledPlanValidationError as exc:
|
|
300
|
+
return _lowering_failed_result(
|
|
301
|
+
request=admission.request,
|
|
302
|
+
source_document_sha256=admission.parsed_source.source_document_sha256,
|
|
303
|
+
resolved=semantic.resolved_harness,
|
|
304
|
+
code="MF-L002",
|
|
305
|
+
message="Compiled plan model validation failed during lowering.",
|
|
306
|
+
error_type=type(exc).__name__,
|
|
307
|
+
)
|
|
308
|
+
except LoweringInvariantError as exc:
|
|
309
|
+
return _lowering_failed_result(
|
|
310
|
+
request=admission.request,
|
|
311
|
+
source_document_sha256=admission.parsed_source.source_document_sha256,
|
|
312
|
+
resolved=semantic.resolved_harness,
|
|
313
|
+
code="MF-L001",
|
|
314
|
+
message="Lowering invariant failed.",
|
|
315
|
+
error_type=type(exc).__name__,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
hash_failure = _compiled_hash_failure(plan)
|
|
319
|
+
if hash_failure is not None:
|
|
320
|
+
return _failed_result(
|
|
321
|
+
request=admission.request,
|
|
322
|
+
phase=CompilerPhase.LOWERING,
|
|
323
|
+
diagnostics=(hash_failure,),
|
|
324
|
+
source_document_sha256=admission.parsed_source.source_document_sha256,
|
|
325
|
+
source_sha256=plan.source_sha256,
|
|
326
|
+
harness_id=plan.harness_id,
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
return plan
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def _compiled_hash_failure(plan: object) -> CompilerDiagnostic | None:
|
|
333
|
+
try:
|
|
334
|
+
payload = plan.model_dump(mode="json") # type: ignore[attr-defined]
|
|
335
|
+
raw = canonical_json_serialize(payload)
|
|
336
|
+
computed = calculate_compiled_plan_sha256(payload)
|
|
337
|
+
if computed != plan.compiled_sha256: # type: ignore[attr-defined]
|
|
338
|
+
return _compiled_hash_diagnostic(computed_hash=computed)
|
|
339
|
+
verified, verified_computed, warnings, _restored = verify_compiled_plan_sha256(
|
|
340
|
+
raw,
|
|
341
|
+
expected_compiled_hash=plan.compiled_sha256, # type: ignore[attr-defined]
|
|
342
|
+
expected_harness_id=plan.harness_id, # type: ignore[attr-defined]
|
|
343
|
+
expected_harness_version=plan.harness_version, # type: ignore[attr-defined]
|
|
344
|
+
)
|
|
345
|
+
except Exception as exc:
|
|
346
|
+
return _compiled_hash_diagnostic(error_type=type(exc).__name__)
|
|
347
|
+
if verified and verified_computed == plan.compiled_sha256: # type: ignore[attr-defined]
|
|
348
|
+
return None
|
|
349
|
+
computed_hash = verified_computed if verified_computed else computed
|
|
350
|
+
return _compiled_hash_diagnostic(
|
|
351
|
+
warning_count=len(warnings),
|
|
352
|
+
computed_hash=computed_hash,
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
def _compiled_hash_diagnostic(
|
|
357
|
+
*,
|
|
358
|
+
warning_count: int | None = None,
|
|
359
|
+
computed_hash: str | None = None,
|
|
360
|
+
error_type: str | None = None,
|
|
361
|
+
) -> CompilerDiagnostic:
|
|
362
|
+
fields: dict[str, str | int] = {}
|
|
363
|
+
if warning_count is not None:
|
|
364
|
+
fields["warning_count"] = warning_count
|
|
365
|
+
if computed_hash is not None:
|
|
366
|
+
fields["computed_hash"] = computed_hash
|
|
367
|
+
if error_type is not None:
|
|
368
|
+
fields["error_type"] = error_type
|
|
369
|
+
return _diagnostic(
|
|
370
|
+
"MF-L004",
|
|
371
|
+
CompilerPhase.LOWERING,
|
|
372
|
+
"Compiled plan canonical hash verification failed.",
|
|
373
|
+
fields=fields,
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def _failed_result(
|
|
378
|
+
*,
|
|
379
|
+
request: HarnessCompileRequest,
|
|
380
|
+
phase: CompilerPhase,
|
|
381
|
+
diagnostics: tuple[CompilerDiagnostic, ...],
|
|
382
|
+
source_document_sha256: str | None = None,
|
|
383
|
+
source_sha256: str | None = None,
|
|
384
|
+
harness_id: str | None = None,
|
|
385
|
+
) -> HarnessCompileResult:
|
|
386
|
+
return HarnessCompileResult(
|
|
387
|
+
request_id=request.request_id,
|
|
388
|
+
status=CompileStatus.FAILED,
|
|
389
|
+
plan_commit_certainty=PlanCommitCertainty.ABSENT,
|
|
390
|
+
failure_phase=phase,
|
|
391
|
+
source_document_sha256=source_document_sha256,
|
|
392
|
+
source_sha256=source_sha256,
|
|
393
|
+
harness_id=harness_id,
|
|
394
|
+
diagnostics=bound_diagnostics(diagnostics),
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def _lowering_failed_result(
|
|
399
|
+
*,
|
|
400
|
+
request: HarnessCompileRequest,
|
|
401
|
+
source_document_sha256: str,
|
|
402
|
+
resolved: ResolvedHarness,
|
|
403
|
+
code: str,
|
|
404
|
+
message: str,
|
|
405
|
+
error_type: str,
|
|
406
|
+
) -> HarnessCompileResult:
|
|
407
|
+
try:
|
|
408
|
+
semantic_hash = source_sha256(resolved)
|
|
409
|
+
except Exception:
|
|
410
|
+
semantic_hash = None
|
|
411
|
+
return _failed_result(
|
|
412
|
+
request=request,
|
|
413
|
+
phase=CompilerPhase.LOWERING,
|
|
414
|
+
diagnostics=(
|
|
415
|
+
_diagnostic(
|
|
416
|
+
code,
|
|
417
|
+
CompilerPhase.LOWERING,
|
|
418
|
+
message,
|
|
419
|
+
fields={"error_type": error_type},
|
|
420
|
+
),
|
|
421
|
+
),
|
|
422
|
+
source_document_sha256=source_document_sha256,
|
|
423
|
+
source_sha256=semantic_hash,
|
|
424
|
+
harness_id=resolved.source.harness_id,
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
def _failure_phase(diagnostics: tuple[CompilerDiagnostic, ...]) -> CompilerPhase:
|
|
429
|
+
return diagnostics[0].phase if diagnostics else CompilerPhase.INTERNAL
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
def _diagnostic(
|
|
433
|
+
code: str,
|
|
434
|
+
phase: CompilerPhase,
|
|
435
|
+
message: str,
|
|
436
|
+
*,
|
|
437
|
+
fields: Mapping[str, str | int] | None = None,
|
|
438
|
+
) -> CompilerDiagnostic:
|
|
439
|
+
return CompilerDiagnostic(
|
|
440
|
+
code=code,
|
|
441
|
+
severity=DiagnosticSeverity.ERROR,
|
|
442
|
+
phase=phase,
|
|
443
|
+
message=message,
|
|
444
|
+
fields=tuple(
|
|
445
|
+
DiagnosticField(key=key, value=value)
|
|
446
|
+
for key, value in sorted((fields or {}).items())
|
|
447
|
+
),
|
|
448
|
+
)
|