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.
Files changed (116) hide show
  1. millforge/__init__.py +1174 -0
  2. millforge/_forge/LICENSE +21 -0
  3. millforge/_forge/PROVENANCE.json +295 -0
  4. millforge/_forge/UPDATE_POLICY.md +24 -0
  5. millforge/_forge/__init__.py +14 -0
  6. millforge/_forge/adapter.py +2232 -0
  7. millforge/_forge/base_runner.py +121 -0
  8. millforge/_forge/clients/__init__.py +10 -0
  9. millforge/_forge/clients/base.py +200 -0
  10. millforge/_forge/context/__init__.py +23 -0
  11. millforge/_forge/context/manager.py +178 -0
  12. millforge/_forge/context/strategies.py +335 -0
  13. millforge/_forge/core/__init__.py +16 -0
  14. millforge/_forge/core/inference.py +433 -0
  15. millforge/_forge/core/messages.py +119 -0
  16. millforge/_forge/core/runner.py +479 -0
  17. millforge/_forge/core/steps.py +108 -0
  18. millforge/_forge/core/workflow.py +400 -0
  19. millforge/_forge/errors.py +222 -0
  20. millforge/_forge/guardrails/__init__.py +21 -0
  21. millforge/_forge/guardrails/error_tracker.py +71 -0
  22. millforge/_forge/guardrails/guardrails.py +194 -0
  23. millforge/_forge/guardrails/nudge.py +47 -0
  24. millforge/_forge/guardrails/response_validator.py +119 -0
  25. millforge/_forge/guardrails/step_enforcer.py +183 -0
  26. millforge/_forge/prompts/__init__.py +16 -0
  27. millforge/_forge/prompts/nudges.py +95 -0
  28. millforge/_forge/prompts/templates.py +285 -0
  29. millforge/_version.py +3 -0
  30. millforge/artifacts.py +570 -0
  31. millforge/base/__init__.py +97 -0
  32. millforge/base/composition.py +402 -0
  33. millforge/base/context.py +285 -0
  34. millforge/base/harness.py +138 -0
  35. millforge/base/identity.py +465 -0
  36. millforge/base/options.py +34 -0
  37. millforge/base/platform.py +17 -0
  38. millforge/base/prompt.py +317 -0
  39. millforge/base/runner.py +546 -0
  40. millforge/compiled_plan.py +970 -0
  41. millforge/compiler/__init__.py +231 -0
  42. millforge/compiler/artifact_validation.py +257 -0
  43. millforge/compiler/canonicalization.py +169 -0
  44. millforge/compiler/capabilities.py +66 -0
  45. millforge/compiler/catalogs.py +500 -0
  46. millforge/compiler/diagnostics.py +491 -0
  47. millforge/compiler/graph.py +678 -0
  48. millforge/compiler/lowering.py +198 -0
  49. millforge/compiler/output.py +692 -0
  50. millforge/compiler/parsing.py +1424 -0
  51. millforge/compiler/requests.py +1180 -0
  52. millforge/compiler/schema_validation.py +272 -0
  53. millforge/compiler/semantic.py +490 -0
  54. millforge/compiler/service.py +448 -0
  55. millforge/compiler/source.py +375 -0
  56. millforge/compiler/validators.py +184 -0
  57. millforge/connectors/__init__.py +95 -0
  58. millforge/connectors/admission.py +801 -0
  59. millforge/connectors/broker.py +202 -0
  60. millforge/connectors/contracts.py +1159 -0
  61. millforge/connectors/diagnostics.py +189 -0
  62. millforge/connectors/fake.py +66 -0
  63. millforge/connectors/runtime.py +236 -0
  64. millforge/contracts.py +2860 -0
  65. millforge/custom_tools/__init__.py +67 -0
  66. millforge/custom_tools/compiler.py +724 -0
  67. millforge/custom_tools/contracts.py +1093 -0
  68. millforge/custom_tools/diagnostics.py +205 -0
  69. millforge/eval_artifacts.py +952 -0
  70. millforge/eval_boundary.py +2435 -0
  71. millforge/eval_fixtures/__init__.py +1 -0
  72. millforge/eval_fixtures/default_pack/__init__.py +1 -0
  73. millforge/eval_fixtures/default_pack/fixtures/fixture.08a.bug_diagnosis.traceback.v1.json +52 -0
  74. millforge/eval_fixtures/default_pack/fixtures/fixture.08a.direct_edit.import_sort.v1.json +52 -0
  75. millforge/eval_fixtures/default_pack/fixtures/fixture.08a.evidence_discipline.no_source_change.v1.json +51 -0
  76. millforge/eval_fixtures/default_pack/fixtures/fixture.08a.false_closure.visible_green.v1.json +52 -0
  77. millforge/eval_fixtures/default_pack/fixtures/fixture.08a.multi_file.api_contract.v1.json +54 -0
  78. millforge/eval_fixtures/default_pack/fixtures/fixture.08a.recovery.malformed_artifact.v1.json +54 -0
  79. millforge/eval_fixtures/default_pack/manifest.json +12 -0
  80. millforge/eval_modes.py +1282 -0
  81. millforge/eval_presets.py +1398 -0
  82. millforge/eval_reports.py +2517 -0
  83. millforge/eval_suite.py +2429 -0
  84. millforge/eval_trials.py +2632 -0
  85. millforge/eval_workflow.py +794 -0
  86. millforge/exceptions.py +122 -0
  87. millforge/model_backend.py +2098 -0
  88. millforge/protocols.py +340 -0
  89. millforge/py.typed +0 -0
  90. millforge/runtime.py +1791 -0
  91. millforge/testing/__init__.py +1089 -0
  92. millforge/tools/__init__.py +83 -0
  93. millforge/tools/builtin_runtime.py +1339 -0
  94. millforge/tools/builtins.py +773 -0
  95. millforge/tools/execution.py +1545 -0
  96. millforge/tools/path_policy.py +155 -0
  97. millforge/tools/pi_compat/PI_LICENSE +21 -0
  98. millforge/tools/pi_compat/PROVENANCE.json +55 -0
  99. millforge/tools/pi_compat/UPDATE_POLICY.md +36 -0
  100. millforge/tools/pi_compat/__init__.py +34 -0
  101. millforge/tools/pi_compat/contracts.py +49 -0
  102. millforge/tools/pi_compat/editing.py +390 -0
  103. millforge/tools/pi_compat/mutations.py +57 -0
  104. millforge/tools/pi_compat/operations.py +401 -0
  105. millforge/tools/pi_compat/paths.py +155 -0
  106. millforge/tools/pi_compat/process.py +1375 -0
  107. millforge/tools/pi_compat/search.py +738 -0
  108. millforge/tools/pi_compat/truncation.py +267 -0
  109. millforge/tools/pi_compat_catalog.py +396 -0
  110. millforge/tools/pi_compat_runtime.py +460 -0
  111. millforge/tools/registry.py +553 -0
  112. millforge/tools/results.py +533 -0
  113. millforge-0.1.0.dist-info/METADATA +844 -0
  114. millforge-0.1.0.dist-info/RECORD +116 -0
  115. millforge-0.1.0.dist-info/WHEEL +4 -0
  116. millforge-0.1.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,198 @@
1
+ """Lower resolved semantic compiler IR into immutable compiled plans."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Mapping
6
+ from importlib import metadata
7
+ from typing import Any
8
+
9
+ from pydantic import ValidationError
10
+
11
+ from millforge.compiled_plan import (
12
+ ArgumentMatch,
13
+ CompilerIdentity,
14
+ CompiledArtifactPolicy,
15
+ CompiledBudgetPolicy,
16
+ CompiledContextPolicy,
17
+ CompiledHarnessNode,
18
+ CompiledHarnessPlan,
19
+ CompiledPrerequisite,
20
+ CompiledPromptPolicy,
21
+ TerminalArtifactRequirement,
22
+ ToolBindingRef,
23
+ finalize_compiled_plan_sha256,
24
+ )
25
+ from millforge.compiler.canonicalization import source_sha256
26
+ from millforge.compiler.semantic import ResolvedHarness, ResolvedToolBinding
27
+
28
+ COMPILER_NAME = "millforge"
29
+ COMPILER_BUILD_ID = "millforge.compiler.lowering.v1"
30
+ _PLACEHOLDER_SHA256 = "0" * 64
31
+
32
+
33
+ class LoweringInvariantError(ValueError):
34
+ """Raised when resolved semantic IR violates a lowering invariant."""
35
+
36
+
37
+ class CompiledPlanValidationError(ValueError):
38
+ """Raised when the accepted compiled plan model rejects lowered values."""
39
+
40
+
41
+ class SourceSemanticHashError(ValueError):
42
+ """Raised when canonical source semantic hash calculation fails."""
43
+
44
+
45
+ def lower_resolved_harness(resolved: ResolvedHarness) -> CompiledHarnessPlan:
46
+ """Return a fully validated compiled plan for an accepted resolved harness."""
47
+ source = resolved.source
48
+ try:
49
+ semantic_hash = source_sha256(resolved)
50
+ except (TypeError, ValueError) as exc:
51
+ raise SourceSemanticHashError(
52
+ "source semantic hash calculation failed"
53
+ ) from exc
54
+
55
+ try:
56
+ plan = CompiledHarnessPlan(
57
+ schema_version=source.schema_version,
58
+ kind="compiled_millforge_harness",
59
+ harness_id=source.harness_id,
60
+ harness_version=source.harness_version,
61
+ source_sha256=semantic_hash,
62
+ compiled_sha256=_PLACEHOLDER_SHA256,
63
+ stage_kind_ids=tuple(sorted(source.stage_scope.stage_kind_ids)),
64
+ model_profile=resolved.model_profile.model_copy(deep=True),
65
+ prompt_policy=CompiledPromptPolicy(
66
+ policy_id=source.prompt.policy_id,
67
+ system_instructions=source.prompt.system_instructions,
68
+ include_request_context=source.prompt.include_request_context,
69
+ ),
70
+ budgets=CompiledBudgetPolicy(
71
+ max_iterations=source.budgets.max_iterations,
72
+ max_validation_retries=source.budgets.max_validation_retries,
73
+ max_tool_errors=source.budgets.max_tool_errors,
74
+ max_prerequisite_violations=(
75
+ source.budgets.max_prerequisite_violations
76
+ ),
77
+ max_premature_terminal_attempts=(
78
+ source.budgets.max_premature_terminal_attempts
79
+ ),
80
+ ),
81
+ context_policy=CompiledContextPolicy(
82
+ strategy_id=source.context.strategy_id,
83
+ budget_tokens=source.context.budget_tokens,
84
+ keep_recent_iterations=source.context.keep_recent_iterations,
85
+ phase_thresholds=(
86
+ source.context.phase_thresholds[0],
87
+ source.context.phase_thresholds[1],
88
+ source.context.phase_thresholds[2],
89
+ ),
90
+ ),
91
+ nodes=tuple(
92
+ _lower_node(node)
93
+ for node in sorted(
94
+ resolved.resolved_nodes, key=lambda item: item.node_id
95
+ )
96
+ ),
97
+ required_capabilities=tuple(sorted(resolved.required_capability_ids)),
98
+ terminal_result_map=dict(sorted(resolved.terminal_result_map.items())),
99
+ artifact_policy=CompiledArtifactPolicy(
100
+ declared_artifact_ids=tuple(
101
+ sorted(source.artifacts.declared_artifact_ids)
102
+ ),
103
+ required_by_terminal=tuple(
104
+ TerminalArtifactRequirement(
105
+ terminal_result=item.terminal_result,
106
+ artifact_ids=tuple(sorted(item.artifact_ids)),
107
+ )
108
+ for item in sorted(
109
+ source.artifacts.required_by_terminal,
110
+ key=lambda requirement: requirement.terminal_result,
111
+ )
112
+ ),
113
+ ),
114
+ compiler_identity=compiler_identity(),
115
+ )
116
+ return finalize_compiled_plan_sha256(plan)
117
+ except CompiledPlanValidationError:
118
+ raise
119
+ except ValidationError as exc:
120
+ raise CompiledPlanValidationError("compiled plan validation failed") from exc
121
+ except (AttributeError, IndexError, KeyError, TypeError, ValueError) as exc:
122
+ raise LoweringInvariantError("lowering invariant failed") from exc
123
+
124
+
125
+ def compiler_identity() -> CompilerIdentity:
126
+ """Return the deterministic compiler identity embedded in compiled plans."""
127
+ return CompilerIdentity(
128
+ name=COMPILER_NAME,
129
+ version=_installed_version(),
130
+ build_id=COMPILER_BUILD_ID,
131
+ )
132
+
133
+
134
+ def _lower_node(node: ResolvedToolBinding) -> CompiledHarnessNode:
135
+ descriptor = node.descriptor
136
+ source = node.source
137
+ return CompiledHarnessNode(
138
+ node_id=node.node_id,
139
+ model_tool_name=descriptor.model_tool_name,
140
+ description=descriptor.description,
141
+ input_schema=_fresh_json_object(descriptor.input_schema),
142
+ binding=ToolBindingRef(
143
+ tool_id=node.binding.tool_id,
144
+ tool_version=node.binding.tool_version,
145
+ descriptor_sha256=node.binding.descriptor_sha256,
146
+ implementation_id=node.binding.implementation_id,
147
+ ),
148
+ prerequisites=tuple(
149
+ CompiledPrerequisite(
150
+ node_id=prerequisite.node_id,
151
+ argument_matches=tuple(
152
+ ArgumentMatch(
153
+ prerequisite_argument=match.prior_argument,
154
+ current_argument=match.current_argument,
155
+ )
156
+ for match in sorted(
157
+ prerequisite.argument_matches,
158
+ key=lambda item: (item.prior_argument, item.current_argument),
159
+ )
160
+ ),
161
+ )
162
+ for prerequisite in sorted(
163
+ source.prerequisites, key=lambda item: item.node_id
164
+ )
165
+ ),
166
+ required=source.required,
167
+ terminal_result=source.terminal_result,
168
+ required_capabilities=tuple(sorted(descriptor.required_capabilities)),
169
+ produced_artifact_ids=tuple(sorted(descriptor.produced_artifact_ids)),
170
+ side_effect_class=descriptor.side_effect_class,
171
+ idempotency=descriptor.idempotency,
172
+ )
173
+
174
+
175
+ def _installed_version() -> str:
176
+ try:
177
+ return metadata.version("millforge")
178
+ except metadata.PackageNotFoundError:
179
+ from millforge import __version__
180
+
181
+ return __version__
182
+
183
+
184
+ def _fresh_json_object(value: Any) -> dict[str, Any]:
185
+ copied = _fresh_json_value(value)
186
+ if not isinstance(copied, dict):
187
+ raise TypeError("expected JSON object")
188
+ return copied
189
+
190
+
191
+ def _fresh_json_value(value: Any) -> Any:
192
+ if value is None or isinstance(value, str | int | float | bool):
193
+ return value
194
+ if isinstance(value, Mapping):
195
+ return {str(key): _fresh_json_value(item) for key, item in value.items()}
196
+ if isinstance(value, tuple | list):
197
+ return [_fresh_json_value(item) for item in value]
198
+ raise TypeError(f"unsupported JSON value {type(value).__name__}")