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,138 @@
|
|
|
1
|
+
"""Ordinary compiler source for the unrestricted Millforge base preset."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from millforge.compiler.source import HarnessSource
|
|
6
|
+
from millforge.compiler.validators import validate_terminal_result, validate_unique
|
|
7
|
+
from millforge.tools.pi_compat_catalog import (
|
|
8
|
+
DEFAULT_BASE_TERMINAL_RESULTS,
|
|
9
|
+
_terminal_token,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = ["millforge_base_harness_source"]
|
|
13
|
+
|
|
14
|
+
_CONFIG_ID = "millforge-base.v1"
|
|
15
|
+
_HARNESS_ID = "millforge.base.unrestricted_agent.v1"
|
|
16
|
+
_TOOL_PACK_ID = "millforge.toolpack.pi_compat.unrestricted.v1"
|
|
17
|
+
_STAGE_KIND = "millforge_base"
|
|
18
|
+
_PROMPT_POLICY_ID = "millforge.base.prompt.v1"
|
|
19
|
+
|
|
20
|
+
_NODES = (
|
|
21
|
+
("read", "builtin.pi_compat.read@1", None),
|
|
22
|
+
("bash", "builtin.pi_compat.bash@1", None),
|
|
23
|
+
("edit", "builtin.pi_compat.edit@1", None),
|
|
24
|
+
("write", "builtin.pi_compat.write@1", None),
|
|
25
|
+
("grep", "builtin.pi_compat.grep@1", None),
|
|
26
|
+
("find", "builtin.pi_compat.find@1", None),
|
|
27
|
+
("ls", "builtin.pi_compat.ls@1", None),
|
|
28
|
+
("submit", "builtin.pi_compat.submit@1", "COMPLETE"),
|
|
29
|
+
("block", "builtin.pi_compat.block@1", "BLOCKED"),
|
|
30
|
+
("reject", "builtin.pi_compat.reject@1", "REJECTED"),
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def canonicalize_base_terminal_results(
|
|
35
|
+
legal_terminal_results: tuple[str, ...],
|
|
36
|
+
) -> tuple[str, ...]:
|
|
37
|
+
"""Validate and sort the bounded terminal vocabulary once at the public edge."""
|
|
38
|
+
|
|
39
|
+
if not isinstance(legal_terminal_results, tuple):
|
|
40
|
+
raise ValueError("legal_terminal_results must be a tuple")
|
|
41
|
+
if not 1 <= len(legal_terminal_results) <= 64:
|
|
42
|
+
raise ValueError("legal_terminal_results must contain 1 through 64 values")
|
|
43
|
+
if any(not isinstance(result, str) for result in legal_terminal_results):
|
|
44
|
+
raise ValueError("legal_terminal_results values must be strings")
|
|
45
|
+
for result in legal_terminal_results:
|
|
46
|
+
validate_terminal_result(result)
|
|
47
|
+
validate_unique(legal_terminal_results, "legal_terminal_results")
|
|
48
|
+
return tuple(sorted(legal_terminal_results))
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _terminal_nodes(
|
|
52
|
+
legal_terminal_results: tuple[str, ...],
|
|
53
|
+
) -> tuple[tuple[str, str, str], ...]:
|
|
54
|
+
if legal_terminal_results == DEFAULT_BASE_TERMINAL_RESULTS:
|
|
55
|
+
return _NODES[-3:]
|
|
56
|
+
tokens = tuple(_terminal_token(result) for result in legal_terminal_results)
|
|
57
|
+
if len(set(tokens)) != len(tokens):
|
|
58
|
+
raise ValueError("configured terminal tool identities collide")
|
|
59
|
+
return tuple(
|
|
60
|
+
(
|
|
61
|
+
f"terminal_{token}",
|
|
62
|
+
f"builtin.pi_compat.terminal.{token}@1",
|
|
63
|
+
result,
|
|
64
|
+
)
|
|
65
|
+
for result, token in zip(legal_terminal_results, tokens, strict=True)
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def millforge_base_harness_source(
|
|
70
|
+
*,
|
|
71
|
+
model_profile_id: str,
|
|
72
|
+
system_instructions: str,
|
|
73
|
+
) -> HarnessSource:
|
|
74
|
+
"""Materialize the unrestricted preset as an ordinary harness source."""
|
|
75
|
+
|
|
76
|
+
return _millforge_base_harness_source_for_terminal_results(
|
|
77
|
+
model_profile_id=model_profile_id,
|
|
78
|
+
system_instructions=system_instructions,
|
|
79
|
+
legal_terminal_results=DEFAULT_BASE_TERMINAL_RESULTS,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _millforge_base_harness_source_for_terminal_results(
|
|
84
|
+
*,
|
|
85
|
+
model_profile_id: str,
|
|
86
|
+
system_instructions: str,
|
|
87
|
+
legal_terminal_results: tuple[str, ...],
|
|
88
|
+
) -> HarnessSource:
|
|
89
|
+
"""Materialize the preset from already-canonical terminal configuration."""
|
|
90
|
+
|
|
91
|
+
return HarnessSource.model_validate(
|
|
92
|
+
{
|
|
93
|
+
"schema_version": "1.0",
|
|
94
|
+
"kind": "millforge_harness",
|
|
95
|
+
"harness_id": _HARNESS_ID,
|
|
96
|
+
"harness_version": 1,
|
|
97
|
+
"stage_scope": {"stage_kind_ids": (_STAGE_KIND,)},
|
|
98
|
+
"model_profile_id": model_profile_id,
|
|
99
|
+
"prompt": {
|
|
100
|
+
"policy_id": _PROMPT_POLICY_ID,
|
|
101
|
+
"system_instructions": system_instructions,
|
|
102
|
+
"include_request_context": True,
|
|
103
|
+
},
|
|
104
|
+
"budgets": {
|
|
105
|
+
"max_iterations": 100,
|
|
106
|
+
"max_validation_retries": 4,
|
|
107
|
+
"max_tool_errors": 16,
|
|
108
|
+
"max_prerequisite_violations": 16,
|
|
109
|
+
"max_premature_terminal_attempts": 8,
|
|
110
|
+
},
|
|
111
|
+
"context": {
|
|
112
|
+
"strategy_id": "forge.tiered.v1",
|
|
113
|
+
"budget_tokens": 32_768,
|
|
114
|
+
"keep_recent_iterations": 4,
|
|
115
|
+
"phase_thresholds": (0.6, 0.75, 0.9),
|
|
116
|
+
},
|
|
117
|
+
"graph": {
|
|
118
|
+
"nodes": tuple(
|
|
119
|
+
{
|
|
120
|
+
"node_id": node_id,
|
|
121
|
+
"tool_ref": tool_ref,
|
|
122
|
+
"required": False,
|
|
123
|
+
"prerequisites": (),
|
|
124
|
+
"terminal_result": terminal_result,
|
|
125
|
+
"produces": (),
|
|
126
|
+
}
|
|
127
|
+
for node_id, tool_ref, terminal_result in (
|
|
128
|
+
*_NODES[:-3],
|
|
129
|
+
*_terminal_nodes(legal_terminal_results),
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
},
|
|
133
|
+
"artifacts": {
|
|
134
|
+
"declared_artifact_ids": (),
|
|
135
|
+
"required_by_terminal": (),
|
|
136
|
+
},
|
|
137
|
+
}
|
|
138
|
+
)
|
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
"""Stable base-runner identity and per-invocation evidence contracts."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
from importlib.resources import files
|
|
9
|
+
from typing import Any, Literal, Mapping
|
|
10
|
+
|
|
11
|
+
from pydantic import (
|
|
12
|
+
BaseModel,
|
|
13
|
+
ConfigDict,
|
|
14
|
+
Field,
|
|
15
|
+
StrictBool,
|
|
16
|
+
StrictInt,
|
|
17
|
+
StrictStr,
|
|
18
|
+
field_validator,
|
|
19
|
+
model_validator,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
import millforge
|
|
23
|
+
from millforge.compiled_plan import StageIdentity, calculate_compiled_plan_sha256
|
|
24
|
+
from millforge.compiler.catalogs import (
|
|
25
|
+
CatalogLookupClassification,
|
|
26
|
+
ToolCatalogSnapshot,
|
|
27
|
+
)
|
|
28
|
+
from millforge.compiler.source import HarnessSource
|
|
29
|
+
from millforge.compiler.validators import parse_tool_reference
|
|
30
|
+
from millforge.contracts import (
|
|
31
|
+
CapabilityEnvelope,
|
|
32
|
+
TerminalSelectedOutputRequirement,
|
|
33
|
+
_selected_output_requirements_by_terminal_result,
|
|
34
|
+
)
|
|
35
|
+
from millforge.model_backend import CapabilitySupport, ResolvedModelProfile
|
|
36
|
+
from millforge.tools.pi_compat_catalog import (
|
|
37
|
+
_create_pi_compat_tool_snapshot_for_terminal_results,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
from .composition import MillforgeBaseComponents
|
|
41
|
+
from .harness import (
|
|
42
|
+
_TOOL_PACK_ID,
|
|
43
|
+
DEFAULT_BASE_TERMINAL_RESULTS,
|
|
44
|
+
_millforge_base_harness_source_for_terminal_results,
|
|
45
|
+
canonicalize_base_terminal_results,
|
|
46
|
+
)
|
|
47
|
+
from .platform import SUPPORTED_PLATFORMS, SupportedPlatform
|
|
48
|
+
|
|
49
|
+
__all__ = [
|
|
50
|
+
"MillforgeBaseRunnerDescriptor",
|
|
51
|
+
"MillforgeInvocationEvidence",
|
|
52
|
+
"describe_millforge_base",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
_SHA256_RE = re.compile(r"[0-9a-f]{64}")
|
|
56
|
+
_DESCRIPTOR_SCHEMA_VERSION = "1.0"
|
|
57
|
+
_INVOCATION_SCHEMA_VERSION = "1.3"
|
|
58
|
+
_PACKAGE_NAME = "millforge"
|
|
59
|
+
_RUNNER_ID = "millforge-base"
|
|
60
|
+
_RUNNER_VERSION = 2
|
|
61
|
+
_TOOL_PACK_VERSION = 1
|
|
62
|
+
_REQUIRED_MODEL_CAPABILITY_IDS = ("tool_calls",)
|
|
63
|
+
_ARTIFACT_CONTRACT_VERSION = "millforge.runtime-artifacts.v2"
|
|
64
|
+
_PROMPT_CONTRACT_VERSION = "millforge-base.prompt.v1"
|
|
65
|
+
_CONTEXT_CONTRACT_VERSION = "millforge-base.context.v1"
|
|
66
|
+
_SUPPORTED_PLATFORMS = SUPPORTED_PLATFORMS
|
|
67
|
+
_MILLFORGE_BASE_STAGE_IDENTITY = StageIdentity(
|
|
68
|
+
plane="execution",
|
|
69
|
+
node_id="millforge-base",
|
|
70
|
+
stage_kind_id="millforge_base",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _canonical_json_bytes(value: Any) -> bytes:
|
|
75
|
+
return json.dumps(
|
|
76
|
+
value,
|
|
77
|
+
sort_keys=True,
|
|
78
|
+
separators=(",", ":"),
|
|
79
|
+
ensure_ascii=True,
|
|
80
|
+
allow_nan=False,
|
|
81
|
+
).encode("utf-8")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _payload_sha256(value: Mapping[str, Any], digest_field: str) -> str:
|
|
85
|
+
payload = {key: item for key, item in value.items() if key != digest_field}
|
|
86
|
+
return hashlib.sha256(_canonical_json_bytes(payload)).hexdigest()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _with_payload_digest(
|
|
90
|
+
payload: Mapping[str, Any], *, digest_field: str
|
|
91
|
+
) -> dict[str, Any]:
|
|
92
|
+
copied = dict(payload)
|
|
93
|
+
copied[digest_field] = _payload_sha256(copied, digest_field)
|
|
94
|
+
return copied
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class MillforgeBaseRunnerDescriptor(BaseModel):
|
|
98
|
+
"""Immutable installed-package identity for the ``millforge-base`` runner."""
|
|
99
|
+
|
|
100
|
+
model_config = ConfigDict(
|
|
101
|
+
extra="forbid",
|
|
102
|
+
frozen=True,
|
|
103
|
+
revalidate_instances="always",
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
schema_version: Literal["1.0"]
|
|
107
|
+
package_name: StrictStr
|
|
108
|
+
package_version: StrictStr
|
|
109
|
+
runner_id: StrictStr
|
|
110
|
+
runner_version: StrictInt = Field(ge=1)
|
|
111
|
+
harness_id: StrictStr
|
|
112
|
+
harness_version: StrictInt = Field(ge=1)
|
|
113
|
+
tool_pack_id: StrictStr
|
|
114
|
+
tool_pack_version: StrictInt = Field(ge=1)
|
|
115
|
+
required_model_capability_ids: tuple[StrictStr, ...]
|
|
116
|
+
required_capability_ids: tuple[StrictStr, ...]
|
|
117
|
+
legal_terminal_result_ids: tuple[StrictStr, ...]
|
|
118
|
+
artifact_contract_version: StrictStr
|
|
119
|
+
prompt_contract_version: StrictStr
|
|
120
|
+
context_contract_version: StrictStr
|
|
121
|
+
tool_catalog_sha256: StrictStr
|
|
122
|
+
forge_provenance_sha256: StrictStr
|
|
123
|
+
pi_provenance_sha256: StrictStr
|
|
124
|
+
supported_platforms: tuple[SupportedPlatform, ...]
|
|
125
|
+
descriptor_sha256: StrictStr
|
|
126
|
+
|
|
127
|
+
@field_validator(
|
|
128
|
+
"tool_catalog_sha256",
|
|
129
|
+
"forge_provenance_sha256",
|
|
130
|
+
"pi_provenance_sha256",
|
|
131
|
+
"descriptor_sha256",
|
|
132
|
+
)
|
|
133
|
+
@classmethod
|
|
134
|
+
def _hashes_are_lowercase_sha256(cls, value: str) -> str:
|
|
135
|
+
if not _SHA256_RE.fullmatch(value):
|
|
136
|
+
raise ValueError("descriptor hashes must be lowercase SHA-256 values")
|
|
137
|
+
return value
|
|
138
|
+
|
|
139
|
+
@model_validator(mode="after")
|
|
140
|
+
def _digest_matches_payload(self) -> MillforgeBaseRunnerDescriptor:
|
|
141
|
+
payload = self.model_dump(mode="json")
|
|
142
|
+
if self.descriptor_sha256 != _payload_sha256(payload, "descriptor_sha256"):
|
|
143
|
+
raise ValueError("descriptor_sha256 does not match canonical payload")
|
|
144
|
+
return self
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class MillforgeInvocationEvidence(BaseModel):
|
|
148
|
+
"""Immutable sanitized evidence for one admitted base-runner request."""
|
|
149
|
+
|
|
150
|
+
model_config = ConfigDict(
|
|
151
|
+
extra="forbid",
|
|
152
|
+
frozen=True,
|
|
153
|
+
revalidate_instances="always",
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
schema_version: Literal["1.3"]
|
|
157
|
+
request_id: StrictStr
|
|
158
|
+
run_id: StrictStr
|
|
159
|
+
selected_output_requirements_sha256: StrictStr | None = Field(
|
|
160
|
+
default=None,
|
|
161
|
+
exclude_if=lambda value: value is None,
|
|
162
|
+
)
|
|
163
|
+
descriptor_sha256: StrictStr
|
|
164
|
+
compiled_plan_sha256: StrictStr
|
|
165
|
+
model_profile_id: StrictStr
|
|
166
|
+
model_behavior_sha256: StrictStr
|
|
167
|
+
capability_envelope_sha256: StrictStr
|
|
168
|
+
effective_prompt_sha256: StrictStr
|
|
169
|
+
context_sha256: StrictStr
|
|
170
|
+
context_file_count: StrictInt = Field(ge=0)
|
|
171
|
+
context_truncated: StrictBool
|
|
172
|
+
prompt_truncated: StrictBool
|
|
173
|
+
cwd_sha256: StrictStr
|
|
174
|
+
invocation_sha256: StrictStr
|
|
175
|
+
|
|
176
|
+
@field_validator(
|
|
177
|
+
"selected_output_requirements_sha256",
|
|
178
|
+
"descriptor_sha256",
|
|
179
|
+
"compiled_plan_sha256",
|
|
180
|
+
"model_behavior_sha256",
|
|
181
|
+
"capability_envelope_sha256",
|
|
182
|
+
"effective_prompt_sha256",
|
|
183
|
+
"context_sha256",
|
|
184
|
+
"cwd_sha256",
|
|
185
|
+
"invocation_sha256",
|
|
186
|
+
)
|
|
187
|
+
@classmethod
|
|
188
|
+
def _hashes_are_lowercase_sha256(cls, value: str | None) -> str | None:
|
|
189
|
+
if value is None:
|
|
190
|
+
return None
|
|
191
|
+
if not _SHA256_RE.fullmatch(value):
|
|
192
|
+
raise ValueError("evidence hashes must be lowercase SHA-256 values")
|
|
193
|
+
return value
|
|
194
|
+
|
|
195
|
+
@field_validator("request_id", "run_id")
|
|
196
|
+
@classmethod
|
|
197
|
+
def _correlation_values_are_nonblank(cls, value: str) -> str:
|
|
198
|
+
if not value.strip():
|
|
199
|
+
raise ValueError("evidence correlation values must be non-empty strings")
|
|
200
|
+
return value
|
|
201
|
+
|
|
202
|
+
@model_validator(mode="after")
|
|
203
|
+
def _digest_matches_payload(self) -> MillforgeInvocationEvidence:
|
|
204
|
+
payload = self.model_dump(mode="json")
|
|
205
|
+
if self.invocation_sha256 != _payload_sha256(payload, "invocation_sha256"):
|
|
206
|
+
raise ValueError("invocation_sha256 does not match canonical payload")
|
|
207
|
+
return self
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _reject_duplicate_json_keys(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
|
|
211
|
+
result: dict[str, Any] = {}
|
|
212
|
+
for key, value in pairs:
|
|
213
|
+
if key in result:
|
|
214
|
+
raise ValueError("provenance record contains duplicate keys")
|
|
215
|
+
result[key] = value
|
|
216
|
+
return result
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def _reject_json_constant(value: str) -> None:
|
|
220
|
+
raise ValueError(f"provenance record contains unsupported constant {value}")
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def _canonical_provenance_sha256(raw: bytes) -> str:
|
|
224
|
+
try:
|
|
225
|
+
parsed = json.loads(
|
|
226
|
+
raw.decode("utf-8"),
|
|
227
|
+
object_pairs_hook=_reject_duplicate_json_keys,
|
|
228
|
+
parse_constant=_reject_json_constant,
|
|
229
|
+
)
|
|
230
|
+
except (UnicodeDecodeError, json.JSONDecodeError, ValueError) as exc:
|
|
231
|
+
raise ValueError("packaged provenance record is not valid JSON") from exc
|
|
232
|
+
if not isinstance(parsed, dict):
|
|
233
|
+
raise ValueError("packaged provenance record must be a JSON object")
|
|
234
|
+
return hashlib.sha256(_canonical_json_bytes(parsed)).hexdigest()
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def _provenance_sha256(*parts: str) -> str:
|
|
238
|
+
resource = files("millforge").joinpath(*parts)
|
|
239
|
+
return _canonical_provenance_sha256(resource.read_bytes())
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def _required_capabilities_for_source(
|
|
243
|
+
source: HarnessSource,
|
|
244
|
+
tool_snapshot: ToolCatalogSnapshot,
|
|
245
|
+
) -> tuple[str, ...]:
|
|
246
|
+
capabilities: set[str] = set()
|
|
247
|
+
seen_refs: set[tuple[str, int]] = set()
|
|
248
|
+
for node in source.graph.nodes:
|
|
249
|
+
reference = parse_tool_reference(node.tool_ref)
|
|
250
|
+
key = (reference.tool_id, reference.version)
|
|
251
|
+
if key in seen_refs:
|
|
252
|
+
raise ValueError("base harness contains a duplicate exact tool reference")
|
|
253
|
+
seen_refs.add(key)
|
|
254
|
+
lookup = tool_snapshot.resolve_exact(reference.tool_id, reference.version)
|
|
255
|
+
if (
|
|
256
|
+
lookup.classification is not CatalogLookupClassification.FOUND
|
|
257
|
+
or lookup.entry is None
|
|
258
|
+
):
|
|
259
|
+
raise ValueError("base harness tool reference is not in the Pi catalog")
|
|
260
|
+
capabilities.update(lookup.entry.required_capabilities)
|
|
261
|
+
return tuple(sorted(capabilities))
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def _static_contract_for_terminal_results(
|
|
265
|
+
legal_terminal_results: tuple[str, ...],
|
|
266
|
+
) -> tuple[
|
|
267
|
+
str,
|
|
268
|
+
int,
|
|
269
|
+
str,
|
|
270
|
+
tuple[str, ...],
|
|
271
|
+
tuple[str, ...],
|
|
272
|
+
str,
|
|
273
|
+
]:
|
|
274
|
+
source = _millforge_base_harness_source_for_terminal_results(
|
|
275
|
+
model_profile_id="millforge-base.descriptor",
|
|
276
|
+
system_instructions="millforge-base descriptor inspection",
|
|
277
|
+
legal_terminal_results=legal_terminal_results,
|
|
278
|
+
)
|
|
279
|
+
tool_snapshot = _create_pi_compat_tool_snapshot_for_terminal_results(
|
|
280
|
+
legal_terminal_results
|
|
281
|
+
)
|
|
282
|
+
required_capabilities = _required_capabilities_for_source(source, tool_snapshot)
|
|
283
|
+
terminals = tuple(
|
|
284
|
+
sorted(
|
|
285
|
+
node.terminal_result
|
|
286
|
+
for node in source.graph.nodes
|
|
287
|
+
if node.terminal_result is not None
|
|
288
|
+
)
|
|
289
|
+
)
|
|
290
|
+
return (
|
|
291
|
+
source.harness_id,
|
|
292
|
+
source.harness_version,
|
|
293
|
+
_TOOL_PACK_ID,
|
|
294
|
+
required_capabilities,
|
|
295
|
+
terminals,
|
|
296
|
+
tool_snapshot.snapshot_sha256,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def describe_millforge_base(
|
|
301
|
+
*,
|
|
302
|
+
legal_terminal_results: tuple[str, ...] = DEFAULT_BASE_TERMINAL_RESULTS,
|
|
303
|
+
) -> MillforgeBaseRunnerDescriptor:
|
|
304
|
+
"""Return the side-effect-free installed ``millforge-base`` descriptor."""
|
|
305
|
+
|
|
306
|
+
return _describe_millforge_base(
|
|
307
|
+
canonicalize_base_terminal_results(legal_terminal_results)
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def _describe_millforge_base(
|
|
312
|
+
legal_terminal_results: tuple[str, ...],
|
|
313
|
+
) -> MillforgeBaseRunnerDescriptor:
|
|
314
|
+
"""Describe an already-canonical terminal vocabulary without side effects."""
|
|
315
|
+
|
|
316
|
+
(
|
|
317
|
+
harness_id,
|
|
318
|
+
harness_version,
|
|
319
|
+
tool_pack_id,
|
|
320
|
+
capabilities,
|
|
321
|
+
terminals,
|
|
322
|
+
tool_catalog_sha256,
|
|
323
|
+
) = _static_contract_for_terminal_results(legal_terminal_results)
|
|
324
|
+
payload = {
|
|
325
|
+
"schema_version": _DESCRIPTOR_SCHEMA_VERSION,
|
|
326
|
+
"package_name": _PACKAGE_NAME,
|
|
327
|
+
"package_version": millforge.__version__,
|
|
328
|
+
"runner_id": _RUNNER_ID,
|
|
329
|
+
"runner_version": _RUNNER_VERSION,
|
|
330
|
+
"harness_id": harness_id,
|
|
331
|
+
"harness_version": harness_version,
|
|
332
|
+
"tool_pack_id": tool_pack_id,
|
|
333
|
+
"tool_pack_version": _TOOL_PACK_VERSION,
|
|
334
|
+
"required_model_capability_ids": _REQUIRED_MODEL_CAPABILITY_IDS,
|
|
335
|
+
"required_capability_ids": capabilities,
|
|
336
|
+
"legal_terminal_result_ids": terminals,
|
|
337
|
+
"artifact_contract_version": _ARTIFACT_CONTRACT_VERSION,
|
|
338
|
+
"prompt_contract_version": _PROMPT_CONTRACT_VERSION,
|
|
339
|
+
"context_contract_version": _CONTEXT_CONTRACT_VERSION,
|
|
340
|
+
"tool_catalog_sha256": tool_catalog_sha256,
|
|
341
|
+
"forge_provenance_sha256": _provenance_sha256("_forge", "PROVENANCE.json"),
|
|
342
|
+
"pi_provenance_sha256": _provenance_sha256(
|
|
343
|
+
"tools", "pi_compat", "PROVENANCE.json"
|
|
344
|
+
),
|
|
345
|
+
"supported_platforms": _SUPPORTED_PLATFORMS,
|
|
346
|
+
}
|
|
347
|
+
return MillforgeBaseRunnerDescriptor.model_validate(
|
|
348
|
+
_with_payload_digest(payload, digest_field="descriptor_sha256")
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def _model_behavior_payload(profile: ResolvedModelProfile) -> dict[str, Any]:
|
|
353
|
+
payload = profile.model_dump(
|
|
354
|
+
mode="json",
|
|
355
|
+
exclude={"profile_id", "source_name", "source_digest"},
|
|
356
|
+
)
|
|
357
|
+
authentication = dict(payload["authentication"])
|
|
358
|
+
authentication.pop("secret_ref", None)
|
|
359
|
+
payload["authentication"] = authentication
|
|
360
|
+
return payload
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def _model_behavior_sha256(profile: ResolvedModelProfile) -> str:
|
|
364
|
+
return hashlib.sha256(
|
|
365
|
+
_canonical_json_bytes(_model_behavior_payload(profile))
|
|
366
|
+
).hexdigest()
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def _capability_envelope_sha256(envelope: CapabilityEnvelope) -> str:
|
|
370
|
+
return hashlib.sha256(
|
|
371
|
+
_canonical_json_bytes(envelope.model_dump(mode="json"))
|
|
372
|
+
).hexdigest()
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def _selected_output_requirements_sha256(
|
|
376
|
+
requirements: tuple[TerminalSelectedOutputRequirement, ...],
|
|
377
|
+
) -> str | None:
|
|
378
|
+
lookup = _selected_output_requirements_by_terminal_result(requirements)
|
|
379
|
+
if not lookup:
|
|
380
|
+
return None
|
|
381
|
+
payload = [
|
|
382
|
+
{
|
|
383
|
+
"required": requirement.required,
|
|
384
|
+
"schema_sha256": requirement.schema_sha256,
|
|
385
|
+
"terminal_result": terminal_result,
|
|
386
|
+
}
|
|
387
|
+
for terminal_result, requirement in lookup.items()
|
|
388
|
+
]
|
|
389
|
+
return hashlib.sha256(_canonical_json_bytes(payload)).hexdigest()
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def _build_invocation_evidence(
|
|
393
|
+
components: MillforgeBaseComponents,
|
|
394
|
+
descriptor: MillforgeBaseRunnerDescriptor,
|
|
395
|
+
*,
|
|
396
|
+
request_id: str,
|
|
397
|
+
run_id: str,
|
|
398
|
+
selected_output_requirements: tuple[TerminalSelectedOutputRequirement, ...] = (),
|
|
399
|
+
) -> MillforgeInvocationEvidence:
|
|
400
|
+
compiled_payload = components.compiled_plan.model_dump(mode="json")
|
|
401
|
+
if (
|
|
402
|
+
calculate_compiled_plan_sha256(compiled_payload)
|
|
403
|
+
!= components.compiled_plan.compiled_sha256
|
|
404
|
+
):
|
|
405
|
+
raise ValueError("compiled plan digest is invalid")
|
|
406
|
+
metadata = components.metadata
|
|
407
|
+
payload = {
|
|
408
|
+
"schema_version": _INVOCATION_SCHEMA_VERSION,
|
|
409
|
+
"request_id": request_id,
|
|
410
|
+
"run_id": run_id,
|
|
411
|
+
"descriptor_sha256": descriptor.descriptor_sha256,
|
|
412
|
+
"compiled_plan_sha256": components.compiled_plan.compiled_sha256,
|
|
413
|
+
"model_profile_id": components.model_profile.profile_id,
|
|
414
|
+
"model_behavior_sha256": _model_behavior_sha256(components.model_profile),
|
|
415
|
+
"capability_envelope_sha256": _capability_envelope_sha256(
|
|
416
|
+
components.capability_envelope
|
|
417
|
+
),
|
|
418
|
+
"effective_prompt_sha256": metadata.effective_prompt_sha256,
|
|
419
|
+
"context_sha256": metadata.context_sha256,
|
|
420
|
+
"context_file_count": metadata.context_file_count,
|
|
421
|
+
"context_truncated": metadata.context_truncated,
|
|
422
|
+
"prompt_truncated": metadata.prompt_truncated,
|
|
423
|
+
"cwd_sha256": metadata.cwd_sha256,
|
|
424
|
+
}
|
|
425
|
+
selected_output_digest = _selected_output_requirements_sha256(
|
|
426
|
+
selected_output_requirements
|
|
427
|
+
)
|
|
428
|
+
if selected_output_digest is not None:
|
|
429
|
+
payload["selected_output_requirements_sha256"] = selected_output_digest
|
|
430
|
+
return MillforgeInvocationEvidence.model_validate(
|
|
431
|
+
_with_payload_digest(payload, digest_field="invocation_sha256")
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
def _has_valid_descriptor_digest(descriptor: MillforgeBaseRunnerDescriptor) -> bool:
|
|
436
|
+
payload = descriptor.model_dump(mode="json")
|
|
437
|
+
return descriptor.descriptor_sha256 == _payload_sha256(payload, "descriptor_sha256")
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def _has_valid_invocation_digest(evidence: MillforgeInvocationEvidence) -> bool:
|
|
441
|
+
payload = evidence.model_dump(mode="json")
|
|
442
|
+
return evidence.invocation_sha256 == _payload_sha256(payload, "invocation_sha256")
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
def _descriptor_agrees_with_components(
|
|
446
|
+
descriptor: MillforgeBaseRunnerDescriptor,
|
|
447
|
+
components: MillforgeBaseComponents,
|
|
448
|
+
) -> bool:
|
|
449
|
+
plan = components.compiled_plan
|
|
450
|
+
metadata = components.metadata
|
|
451
|
+
profile = components.model_profile
|
|
452
|
+
terminals = tuple(sorted(plan.terminal_result_map.values()))
|
|
453
|
+
return (
|
|
454
|
+
descriptor.harness_id == plan.harness_id
|
|
455
|
+
and descriptor.harness_version == plan.harness_version
|
|
456
|
+
and descriptor.tool_pack_id == metadata.tool_pack_id
|
|
457
|
+
and descriptor.tool_catalog_sha256 == components.tool_snapshot.snapshot_sha256
|
|
458
|
+
and descriptor.required_capability_ids == plan.required_capabilities
|
|
459
|
+
and descriptor.legal_terminal_result_ids == components.legal_terminal_results
|
|
460
|
+
and terminals == components.legal_terminal_results
|
|
461
|
+
and all(
|
|
462
|
+
profile.capabilities.state_for(capability_id) is CapabilitySupport.SUPPORTED
|
|
463
|
+
for capability_id in descriptor.required_model_capability_ids
|
|
464
|
+
)
|
|
465
|
+
)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Validated options for the unrestricted Millforge base preset."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr, field_validator
|
|
8
|
+
|
|
9
|
+
__all__ = ["MillforgeBaseOptions"]
|
|
10
|
+
|
|
11
|
+
_MAX_PROMPT_INPUT_BYTES = 65_536
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MillforgeBaseOptions(BaseModel):
|
|
15
|
+
"""The complete base-specific option boundary."""
|
|
16
|
+
|
|
17
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
18
|
+
|
|
19
|
+
schema_version: Literal[1] = 1
|
|
20
|
+
config_id: Literal["millforge-base.v1"] = "millforge-base.v1"
|
|
21
|
+
load_context_files: StrictBool = True
|
|
22
|
+
system_prompt: StrictStr | None = None
|
|
23
|
+
append_system_prompt: StrictStr | None = None
|
|
24
|
+
|
|
25
|
+
@field_validator("system_prompt", "append_system_prompt")
|
|
26
|
+
@classmethod
|
|
27
|
+
def _prompt_is_nonblank_and_bounded(cls, value: str | None) -> str | None:
|
|
28
|
+
if value is None:
|
|
29
|
+
return value
|
|
30
|
+
if not value.strip():
|
|
31
|
+
raise ValueError("prompt values must be nonblank when set")
|
|
32
|
+
if len(value.encode("utf-8")) > _MAX_PROMPT_INPUT_BYTES:
|
|
33
|
+
raise ValueError("prompt values may contain at most 65536 UTF-8 bytes")
|
|
34
|
+
return value
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Supported-platform preflight for operational ``millforge-base`` APIs."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from typing import Literal, TypeAlias
|
|
7
|
+
|
|
8
|
+
from millforge.exceptions import UnsupportedPlatformError
|
|
9
|
+
|
|
10
|
+
SupportedPlatform: TypeAlias = Literal["linux", "darwin"]
|
|
11
|
+
SUPPORTED_PLATFORMS: tuple[SupportedPlatform, ...] = ("linux", "darwin")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _require_supported_platform() -> None:
|
|
15
|
+
platform_id = sys.platform
|
|
16
|
+
if platform_id not in SUPPORTED_PLATFORMS:
|
|
17
|
+
raise UnsupportedPlatformError(platform_id)
|