pdl-taskmaster 2.4.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.
- pdl_taskmaster/__init__.py +6 -0
- pdl_taskmaster/contracts/AUTHORITY_MAP.json +19 -0
- pdl_taskmaster/contracts/CALIBRATION.json +7 -0
- pdl_taskmaster/contracts/CONTRACT_MANIFEST.json +231 -0
- pdl_taskmaster/contracts/EXECUTION_CONTRACT.json +615 -0
- pdl_taskmaster/contracts/IMPLEMENTATION_BOUNDARY.json +32 -0
- pdl_taskmaster/contracts/VERIFICATION_CONTRACT.json +379 -0
- pdl_taskmaster/contracts/standards/ARTIFACT_STANDARD.md +7 -0
- pdl_taskmaster/contracts/standards/AUTHORITY_STANDARD.md +17 -0
- pdl_taskmaster/contracts/standards/CONFORMANCE_STANDARD.md +15 -0
- pdl_taskmaster/contracts/standards/CONTEXT_STANDARD.md +15 -0
- pdl_taskmaster/contracts/standards/EXECUTION_STANDARD.md +14 -0
- pdl_taskmaster/contracts/standards/HANDOFF_STANDARD.md +21 -0
- pdl_taskmaster/contracts/standards/INSTALLATION_STANDARD.md +17 -0
- pdl_taskmaster/contracts/standards/PDL_STANDARD.md +19 -0
- pdl_taskmaster/contracts/standards/PROMPT_STANDARD.md +13 -0
- pdl_taskmaster/contracts/standards/PROTOCOL_STANDARD.md +17 -0
- pdl_taskmaster/contracts/standards/RESPONSE_PLAN_STANDARD.md +24 -0
- pdl_taskmaster/contracts/standards/RESULT_STANDARD.md +35 -0
- pdl_taskmaster/contracts/standards/REVIEW_STANDARD.md +31 -0
- pdl_taskmaster/contracts/standards/SEMANTIC_INPUT_STANDARD.md +15 -0
- pdl_taskmaster/contracts/standards/TASK_SEMANTICS_STANDARD.md +9 -0
- pdl_taskmaster/controller/__init__.py +0 -0
- pdl_taskmaster/controller/mechanical_controller.py +542 -0
- pdl_taskmaster/controller/schemas/activation_decision.schema.json +34 -0
- pdl_taskmaster/controller/schemas/artifact_body.schema.json +14 -0
- pdl_taskmaster/controller/schemas/artifact_review_facts.schema.json +91 -0
- pdl_taskmaster/controller/schemas/bootstrap_analysis.schema.json +60 -0
- pdl_taskmaster/controller/schemas/execution_draft.schema.json +47 -0
- pdl_taskmaster/controller/schemas/execution_input_decision.schema.json +43 -0
- pdl_taskmaster/controller/schemas/execution_outcome.schema.json +201 -0
- pdl_taskmaster/controller/schemas/plan_artifact.schema.json +14 -0
- pdl_taskmaster/controller/schemas/prompt_artifact.schema.json +63 -0
- pdl_taskmaster/controller/schemas/protocol_discussion.schema.json +8 -0
- pdl_taskmaster/controller/schemas/result_ir_repair.schema.json +140 -0
- pdl_taskmaster/eval/__init__.py +1 -0
- pdl_taskmaster/eval/build_adversarial_battery.py +351 -0
- pdl_taskmaster/eval/compare_eval_runs.py +251 -0
- pdl_taskmaster/eval/control_api_call.py +428 -0
- pdl_taskmaster/eval/export_rlcd_dataset.py +799 -0
- pdl_taskmaster/eval/fidelity_scan.py +268 -0
- pdl_taskmaster/eval/gen_fidelity_battery.py +457 -0
- pdl_taskmaster/eval/leak_scan.py +260 -0
- pdl_taskmaster/eval/rerecord_fixtures.py +139 -0
- pdl_taskmaster/eval/run_canary_shape_probe.py +229 -0
- pdl_taskmaster/eval/run_dual_gate_probe.py +404 -0
- pdl_taskmaster/eval/run_qualified_batch.py +841 -0
- pdl_taskmaster/eval/summarize_run.py +194 -0
- pdl_taskmaster/host/__init__.py +1 -0
- pdl_taskmaster/host/app.py +164 -0
- pdl_taskmaster/host/cli.py +100 -0
- pdl_taskmaster/host/repl.py +866 -0
- pdl_taskmaster/observation/__init__.py +1 -0
- pdl_taskmaster/observation/cli.py +47 -0
- pdl_taskmaster/observation/observed_session.py +219 -0
- pdl_taskmaster/observation/parsers.py +66 -0
- pdl_taskmaster/observation/records.py +58 -0
- pdl_taskmaster/observation/session.py +3 -0
- pdl_taskmaster/observation/sink.py +3 -0
- pdl_taskmaster/observation/sinks.py +20 -0
- pdl_taskmaster/providers/README.md +66 -0
- pdl_taskmaster/providers/__init__.py +1 -0
- pdl_taskmaster/providers/api_worker.py +411 -0
- pdl_taskmaster/providers/base.py +26 -0
- pdl_taskmaster/providers/codex_worker.py +328 -0
- pdl_taskmaster/providers/fixtures.py +157 -0
- pdl_taskmaster/providers/live_stub.py +66 -0
- pdl_taskmaster/providers/recorded.py +120 -0
- pdl_taskmaster/py.typed +1 -0
- pdl_taskmaster/runtime/__init__.py +0 -0
- pdl_taskmaster/runtime/context_compiler.py +151 -0
- pdl_taskmaster/runtime/model_classification.py +290 -0
- pdl_taskmaster/runtime/normative_store.py +157 -0
- pdl_taskmaster/runtime/operation_bridge.py +336 -0
- pdl_taskmaster/runtime/presentation.py +18 -0
- pdl_taskmaster/runtime/quarantine.py +91 -0
- pdl_taskmaster/runtime/result_ir.py +401 -0
- pdl_taskmaster/runtime/semantic_observer.py +40 -0
- pdl_taskmaster/runtime/session_engine.py +1168 -0
- pdl_taskmaster/runtime/standard_registry.py +55 -0
- pdl_taskmaster/runtime/wire_payloads.py +462 -0
- pdl_taskmaster/runtime/worker-bootstrap.txt +4 -0
- pdl_taskmaster/runtime/workspace.py +602 -0
- pdl_taskmaster/tracking/__init__.py +1 -0
- pdl_taskmaster/tracking/log_live_session.py +98 -0
- pdl_taskmaster/tracking/mlflow_sink.py +58 -0
- pdl_taskmaster/verify/verify_repl_baseline.py +299 -0
- pdl_taskmaster-2.4.0.dist-info/METADATA +155 -0
- pdl_taskmaster-2.4.0.dist-info/RECORD +92 -0
- pdl_taskmaster-2.4.0.dist-info/WHEEL +4 -0
- pdl_taskmaster-2.4.0.dist-info/entry_points.txt +2 -0
- pdl_taskmaster-2.4.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from hashlib import sha256
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
import json
|
|
8
|
+
|
|
9
|
+
from pdl_taskmaster.runtime.standard_registry import StandardRegistry
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
_AUTO_SYMBOLS = {"OPERATION_ID", "APPLICABLE_STANDARD_CLAUSES", "HIGHER_PRIORITY_CONSTRAINTS"}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class CompiledProjection:
|
|
17
|
+
operation: str
|
|
18
|
+
output_kind: str
|
|
19
|
+
output_fields: tuple[str, ...]
|
|
20
|
+
document: dict[str, Any]
|
|
21
|
+
manifest: dict[str, Any]
|
|
22
|
+
|
|
23
|
+
def render(self, bootstrap: str, *, compact: bool = False) -> str:
|
|
24
|
+
"""Render bootstrap + projection document.
|
|
25
|
+
|
|
26
|
+
compact=True serializes the document without indentation (~23% smaller);
|
|
27
|
+
the parsed JSON is identical, so semantics are unchanged. Fixture replay
|
|
28
|
+
hashes the full rendered prompt, so recorded fixtures must keep the
|
|
29
|
+
default pretty rendering.
|
|
30
|
+
"""
|
|
31
|
+
if compact:
|
|
32
|
+
body = json.dumps(self.document, ensure_ascii=False, separators=(",", ":"))
|
|
33
|
+
else:
|
|
34
|
+
body = json.dumps(self.document, ensure_ascii=False, indent=2)
|
|
35
|
+
return bootstrap.rstrip() + "\n\n" + body + "\n"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ContextCompiler:
|
|
39
|
+
def __init__(self, repo_root: str | Path, standards_root: str | Path | None = None):
|
|
40
|
+
self.repo_root = Path(repo_root)
|
|
41
|
+
from pdl_taskmaster.runtime.normative_store import NormativeStore
|
|
42
|
+
self.standards_root = Path(standards_root) if standards_root else NormativeStore.resolve_standards_root(self.repo_root)
|
|
43
|
+
contract_path = NormativeStore.resolve_contract(self.repo_root, "EXECUTION_CONTRACT.json")
|
|
44
|
+
if not contract_path.is_file():
|
|
45
|
+
contract_path = self.repo_root / "contracts" / "EXECUTION_CONTRACT.json"
|
|
46
|
+
self.execution_contract = json.loads(contract_path.read_text(encoding="utf-8"))
|
|
47
|
+
self.registry = StandardRegistry(self.repo_root, standards_root=self.standards_root)
|
|
48
|
+
|
|
49
|
+
def compile(
|
|
50
|
+
self,
|
|
51
|
+
operation: str,
|
|
52
|
+
values: dict[str, Any],
|
|
53
|
+
*,
|
|
54
|
+
higher_priority_constraints: Any = None,
|
|
55
|
+
) -> CompiledProjection:
|
|
56
|
+
operations = self.execution_contract["operations"]
|
|
57
|
+
if operation not in operations:
|
|
58
|
+
raise ValueError(f"operation:{operation}")
|
|
59
|
+
spec = operations[operation]
|
|
60
|
+
include = tuple(spec["include"])
|
|
61
|
+
# Optional symbols (Phase 9 S4): supplied by the engine only when the
|
|
62
|
+
# session provides them (e.g. PREVIOUS_DELIVERABLE on chained turns);
|
|
63
|
+
# absent optional symbols are omitted from the projection entirely so
|
|
64
|
+
# single-turn projections stay byte-identical (fixture replay safe).
|
|
65
|
+
optional = tuple(spec.get("optional_include", ()))
|
|
66
|
+
expected = set(include) - _AUTO_SYMBOLS
|
|
67
|
+
provided = set(values)
|
|
68
|
+
missing = expected - provided
|
|
69
|
+
extra = (provided - expected) - set(optional)
|
|
70
|
+
if missing:
|
|
71
|
+
raise ValueError(f"missing_symbols:{sorted(missing)}")
|
|
72
|
+
if extra:
|
|
73
|
+
raise ValueError(f"extra_symbols:{sorted(extra)}")
|
|
74
|
+
|
|
75
|
+
clauses = self.registry.select(spec["requirements"])
|
|
76
|
+
clause_values = [
|
|
77
|
+
{"requirement_id": clause.requirement_id, "clause": clause.text}
|
|
78
|
+
for clause in clauses
|
|
79
|
+
]
|
|
80
|
+
ordered_inputs: dict[str, Any] = {}
|
|
81
|
+
for symbol in include:
|
|
82
|
+
if symbol == "OPERATION_ID":
|
|
83
|
+
ordered_inputs[symbol] = operation
|
|
84
|
+
elif symbol == "APPLICABLE_STANDARD_CLAUSES":
|
|
85
|
+
ordered_inputs[symbol] = clause_values
|
|
86
|
+
elif symbol == "HIGHER_PRIORITY_CONSTRAINTS":
|
|
87
|
+
ordered_inputs[symbol] = higher_priority_constraints
|
|
88
|
+
else:
|
|
89
|
+
ordered_inputs[symbol] = values[symbol]
|
|
90
|
+
for symbol in optional:
|
|
91
|
+
if symbol in provided and values[symbol] is not None:
|
|
92
|
+
ordered_inputs[symbol] = values[symbol]
|
|
93
|
+
|
|
94
|
+
schema_relative = spec.get("output_schema")
|
|
95
|
+
if not isinstance(schema_relative, str):
|
|
96
|
+
raise ValueError(f"output_schema:{operation}")
|
|
97
|
+
schema_path = Path(schema_relative)
|
|
98
|
+
if schema_path.is_absolute() or ".." in schema_path.parts:
|
|
99
|
+
raise ValueError(f"output_schema_path:{operation}")
|
|
100
|
+
full_schema_path = self.repo_root / schema_path
|
|
101
|
+
if not full_schema_path.is_file() and not schema_path.is_absolute():
|
|
102
|
+
rel = Path(*schema_path.parts[1:]) if schema_path.parts and schema_path.parts[0] == "scripts" else schema_path
|
|
103
|
+
pkg_root = Path(__file__).resolve().parents[1]
|
|
104
|
+
for c in (
|
|
105
|
+
pkg_root / rel,
|
|
106
|
+
self.repo_root / "src" / "pdl_taskmaster" / rel,
|
|
107
|
+
pkg_root / schema_path,
|
|
108
|
+
self.repo_root / "src" / "pdl_taskmaster" / schema_path,
|
|
109
|
+
self.repo_root / "scripts" / schema_path,
|
|
110
|
+
):
|
|
111
|
+
if c.is_file():
|
|
112
|
+
full_schema_path = c
|
|
113
|
+
break
|
|
114
|
+
if not full_schema_path.is_file():
|
|
115
|
+
raise ValueError(f"output_schema_missing:{operation}")
|
|
116
|
+
output_schema = json.loads(full_schema_path.read_text(encoding="utf-8"))
|
|
117
|
+
|
|
118
|
+
document: dict[str, Any] = {
|
|
119
|
+
"operation": operation,
|
|
120
|
+
"output_kind": spec["output_kind"],
|
|
121
|
+
"output_schema": output_schema,
|
|
122
|
+
"operation_inputs": ordered_inputs,
|
|
123
|
+
}
|
|
124
|
+
if spec.get("artifact_kind"):
|
|
125
|
+
document["artifact_kind"] = spec["artifact_kind"]
|
|
126
|
+
|
|
127
|
+
clause_digests = {
|
|
128
|
+
clause.requirement_id: sha256(clause.text.encode("utf-8")).hexdigest()
|
|
129
|
+
for clause in clauses
|
|
130
|
+
}
|
|
131
|
+
manifest = {
|
|
132
|
+
"operation": operation,
|
|
133
|
+
"included_symbols": list(include),
|
|
134
|
+
"excluded_symbols": list(spec.get("exclude", [])),
|
|
135
|
+
"requirement_ids": list(spec["requirements"]),
|
|
136
|
+
"clause_sha256": clause_digests,
|
|
137
|
+
"output_kind": spec["output_kind"],
|
|
138
|
+
"output_fields": list(spec.get("output_fields", [])),
|
|
139
|
+
"output_schema": schema_relative,
|
|
140
|
+
"output_schema_sha256": sha256(full_schema_path.read_bytes()).hexdigest(),
|
|
141
|
+
}
|
|
142
|
+
manifest["projection_sha256"] = sha256(
|
|
143
|
+
json.dumps(document, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode("utf-8")
|
|
144
|
+
).hexdigest()
|
|
145
|
+
return CompiledProjection(
|
|
146
|
+
operation=operation,
|
|
147
|
+
output_kind=spec["output_kind"],
|
|
148
|
+
output_fields=tuple(spec.get("output_fields", [])),
|
|
149
|
+
document=document,
|
|
150
|
+
manifest=manifest,
|
|
151
|
+
)
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
"""Model and Provider Classification Taxonomy (Track M2).
|
|
2
|
+
|
|
3
|
+
Prevents cross-tier and cross-provider false equivalences in adversarial evaluation.
|
|
4
|
+
Explicitly distinguishes between:
|
|
5
|
+
1. Capability Tier (Frontier Flagship vs. Mid-Tier Balanced vs. Lightweight Fast)
|
|
6
|
+
2. Provider Hosting Class (Direct Dedicated vs. Aggregator BYOK vs. Aggregator Shared Pool)
|
|
7
|
+
3. Reasoning Architecture (Disabled vs. Native Thinking Traces)
|
|
8
|
+
|
|
9
|
+
Under this taxonomy, comparing a Mid-Tier Balanced model (e.g. GLM-4.7) to a
|
|
10
|
+
Frontier Flagship model (e.g. DeepSeek-V4-Pro, Claude 3.5 Sonnet, GPT-4o) without
|
|
11
|
+
controlling for capability tier constitutes a methodological false equivalence.
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from dataclasses import asdict, dataclass
|
|
16
|
+
from enum import Enum
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class CapabilityTier(str, Enum):
|
|
21
|
+
FRONTIER_FLAGSHIP = "FRONTIER_FLAGSHIP" # Tier 1: DeepSeek-V4-Pro, GPT-4o, Claude 3.5 Sonnet, GLM-5.3
|
|
22
|
+
MID_BALANCED = "MID_BALANCED" # Tier 2: GLM-4.7, DeepSeek-Flash, Qwen-2.5-72B, Llama-3.3-70B
|
|
23
|
+
LIGHT_FAST = "LIGHT_FAST" # Tier 3: GLM-4.7-Flash, Gemini-2.0-Flash, Claude-3.5-Haiku
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ProviderHostingClass(str, Enum):
|
|
27
|
+
DIRECT_FIRST_PARTY = "DIRECT_FIRST_PARTY" # Direct vendor API with dedicated account quota (e.g. api.deepseek.com)
|
|
28
|
+
AGGREGATOR_BYOK = "AGGREGATOR_BYOK" # Aggregator proxy with user's own upstream account key
|
|
29
|
+
AGGREGATOR_SHARED = "AGGREGATOR_SHARED" # Aggregator shared public rate-limit pool (e.g. OpenRouter free/shared)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True)
|
|
33
|
+
class ModelClassification:
|
|
34
|
+
model_id: str
|
|
35
|
+
display_name: str
|
|
36
|
+
family: str
|
|
37
|
+
capability_tier: CapabilityTier
|
|
38
|
+
tier_rank: int # 1 = Frontier, 2 = Mid, 3 = Light
|
|
39
|
+
provider_class: ProviderHostingClass
|
|
40
|
+
upstream_provider: str
|
|
41
|
+
reasoning_mode: str
|
|
42
|
+
recommended_inter_call_delay_s: float
|
|
43
|
+
comparative_peers: list[str]
|
|
44
|
+
methodological_notes: str
|
|
45
|
+
|
|
46
|
+
def as_dict(self) -> dict[str, Any]:
|
|
47
|
+
d = asdict(self)
|
|
48
|
+
d["capability_tier"] = self.capability_tier.value
|
|
49
|
+
d["provider_class"] = self.provider_class.value
|
|
50
|
+
return d
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# Known model taxonomy registry
|
|
54
|
+
_TAXONOMY: dict[str, dict[str, Any]] = {
|
|
55
|
+
"z-ai/glm-4.7": {
|
|
56
|
+
"display_name": "GLM-4.7",
|
|
57
|
+
"family": "Zhipu GLM",
|
|
58
|
+
"capability_tier": CapabilityTier.MID_BALANCED,
|
|
59
|
+
"tier_rank": 2,
|
|
60
|
+
"upstream_provider": "Google Vertex (via OpenRouter)",
|
|
61
|
+
"recommended_inter_call_delay_s": 3.0,
|
|
62
|
+
"comparative_peers": ["deepseek-flash", "qwen/qwen-2.5-72b-instruct", "meta-llama/llama-3.3-70b-instruct"],
|
|
63
|
+
"methodological_notes": (
|
|
64
|
+
"GLM-4.7 is a Mid-Tier Balanced workhorse. Comparing it to Frontier Flagships "
|
|
65
|
+
"(e.g. DeepSeek-V4-Pro, Claude-3.5-Sonnet) represents a cross-tier false equivalence. "
|
|
66
|
+
"Valid comparative baselines must be drawn from Tier 2 peers or paired with GLM-5.3 if available."
|
|
67
|
+
),
|
|
68
|
+
},
|
|
69
|
+
"z-ai/glm-4.7-flash": {
|
|
70
|
+
"display_name": "GLM-4.7-Flash",
|
|
71
|
+
"family": "Zhipu GLM",
|
|
72
|
+
"capability_tier": CapabilityTier.LIGHT_FAST,
|
|
73
|
+
"tier_rank": 3,
|
|
74
|
+
"upstream_provider": "DeepInfra (via OpenRouter)",
|
|
75
|
+
"recommended_inter_call_delay_s": 1.5,
|
|
76
|
+
"comparative_peers": ["google/gemini-2.0-flash-001", "anthropic/claude-3.5-haiku"],
|
|
77
|
+
"methodological_notes": "High-speed Tier 3 lightweight model.",
|
|
78
|
+
},
|
|
79
|
+
"deepseek-flash": {
|
|
80
|
+
"display_name": "DeepSeek-V4.1-Flash",
|
|
81
|
+
"family": "DeepSeek",
|
|
82
|
+
"capability_tier": CapabilityTier.MID_BALANCED,
|
|
83
|
+
"tier_rank": 2,
|
|
84
|
+
"upstream_provider": "DeepSeek First-Party API",
|
|
85
|
+
"recommended_inter_call_delay_s": 1.0,
|
|
86
|
+
"comparative_peers": ["z-ai/glm-4.7", "qwen/qwen-2.5-72b-instruct"],
|
|
87
|
+
"methodological_notes": "Direct competitor to GLM-4.7 within Tier 2 (Mid-Tier Balanced).",
|
|
88
|
+
},
|
|
89
|
+
"deepseek-v4-pro": {
|
|
90
|
+
"display_name": "DeepSeek-V4-Pro",
|
|
91
|
+
"family": "DeepSeek",
|
|
92
|
+
"capability_tier": CapabilityTier.FRONTIER_FLAGSHIP,
|
|
93
|
+
"tier_rank": 1,
|
|
94
|
+
"upstream_provider": "DeepSeek First-Party API",
|
|
95
|
+
"recommended_inter_call_delay_s": 2.0,
|
|
96
|
+
"comparative_peers": ["claude-3-5-sonnet", "gpt-4o", "z-ai/glm-5.3"],
|
|
97
|
+
"methodological_notes": "Frontier Flagship (Tier 1). Symmetrically comparable only to other Frontier models.",
|
|
98
|
+
},
|
|
99
|
+
"google/gemini-2.0-flash-001": {
|
|
100
|
+
"display_name": "Gemini 2.0 Flash",
|
|
101
|
+
"family": "Google Gemini",
|
|
102
|
+
"capability_tier": CapabilityTier.LIGHT_FAST,
|
|
103
|
+
"tier_rank": 3,
|
|
104
|
+
"upstream_provider": "Google (via OpenRouter)",
|
|
105
|
+
"recommended_inter_call_delay_s": 1.0,
|
|
106
|
+
"comparative_peers": ["z-ai/glm-4.7-flash", "anthropic/claude-3.5-haiku"],
|
|
107
|
+
"methodological_notes": "Tier 3 Lightweight fast instruction-follower.",
|
|
108
|
+
},
|
|
109
|
+
"google/gemini-2.5-flash": {
|
|
110
|
+
"display_name": "Gemini 2.5 Flash",
|
|
111
|
+
"family": "Google Gemini",
|
|
112
|
+
"capability_tier": CapabilityTier.MID_BALANCED,
|
|
113
|
+
"tier_rank": 2,
|
|
114
|
+
"upstream_provider": "Google Vertex (via OpenRouter)",
|
|
115
|
+
"recommended_inter_call_delay_s": 0.5,
|
|
116
|
+
"comparative_peers": ["z-ai/glm-4.7", "deepseek-flash", "qwen/qwen-2.5-72b-instruct"],
|
|
117
|
+
"methodological_notes": (
|
|
118
|
+
"Google Vertex Tier 2 Mid-Tier Balanced workhorse model with high throughput and native structured outputs. "
|
|
119
|
+
"Directly comparable to GLM-4.7 and DeepSeek-Flash."
|
|
120
|
+
),
|
|
121
|
+
},
|
|
122
|
+
"qwen/qwen3-coder-30b-a3b-instruct": {
|
|
123
|
+
"display_name": "Qwen3 Coder 30B",
|
|
124
|
+
"family": "Qwen / Alibaba",
|
|
125
|
+
"capability_tier": CapabilityTier.MID_BALANCED,
|
|
126
|
+
"tier_rank": 2,
|
|
127
|
+
"upstream_provider": "Alibaba (via OpenRouter)",
|
|
128
|
+
"recommended_inter_call_delay_s": 1.0,
|
|
129
|
+
"comparative_peers": ["z-ai/glm-4.7", "meta-llama/llama-3.3-70b-instruct", "deepseek/deepseek-chat"],
|
|
130
|
+
"methodological_notes": "Tier 2 Mid-Tier Balanced coding MoE with 256k context. Primary open-weights distillation baseline.",
|
|
131
|
+
},
|
|
132
|
+
"meta-llama/llama-3.3-70b-instruct": {
|
|
133
|
+
"display_name": "Llama 3.3 70B Instruct",
|
|
134
|
+
"family": "Meta Llama",
|
|
135
|
+
"capability_tier": CapabilityTier.MID_BALANCED,
|
|
136
|
+
"tier_rank": 2,
|
|
137
|
+
"upstream_provider": "Meta (via OpenRouter)",
|
|
138
|
+
"recommended_inter_call_delay_s": 1.0,
|
|
139
|
+
"comparative_peers": ["z-ai/glm-4.7", "qwen/qwen3-coder-30b-a3b-instruct", "deepseek/deepseek-chat"],
|
|
140
|
+
"methodological_notes": "Tier 2 Mid-Tier Balanced dense 70B standard enterprise baseline.",
|
|
141
|
+
},
|
|
142
|
+
"deepseek/deepseek-chat": {
|
|
143
|
+
"display_name": "DeepSeek-V3",
|
|
144
|
+
"family": "DeepSeek",
|
|
145
|
+
"capability_tier": CapabilityTier.MID_BALANCED,
|
|
146
|
+
"tier_rank": 2,
|
|
147
|
+
"upstream_provider": "DeepSeek (via OpenRouter)",
|
|
148
|
+
"recommended_inter_call_delay_s": 1.0,
|
|
149
|
+
"comparative_peers": ["z-ai/glm-4.7", "qwen/qwen3-coder-30b-a3b-instruct", "meta-llama/llama-3.3-70b-instruct"],
|
|
150
|
+
"methodological_notes": "Tier 2 Mid-Tier Balanced MoE (671B total, 37B active). Direct architectural peer to GLM-4.7's 32B active MoE.",
|
|
151
|
+
},
|
|
152
|
+
"z-ai/glm-5.3-flash": {
|
|
153
|
+
"display_name": "GLM-5.3-Flash",
|
|
154
|
+
"family": "Zhipu GLM",
|
|
155
|
+
"capability_tier": CapabilityTier.LIGHT_FAST,
|
|
156
|
+
"tier_rank": 3,
|
|
157
|
+
"upstream_provider": "Zhipu AI (via OpenRouter)",
|
|
158
|
+
"recommended_inter_call_delay_s": 0.5,
|
|
159
|
+
"comparative_peers": ["openai/gpt-4o-mini", "z-ai/glm-4.7-flash"],
|
|
160
|
+
"methodological_notes": "Tier 3 Lightweight Fast high-throughput MoE (320B total, 18B active) with 1.3M context.",
|
|
161
|
+
},
|
|
162
|
+
"openai/gpt-4o-mini": {
|
|
163
|
+
"display_name": "GPT-4o-mini",
|
|
164
|
+
"family": "OpenAI",
|
|
165
|
+
"capability_tier": CapabilityTier.LIGHT_FAST,
|
|
166
|
+
"tier_rank": 3,
|
|
167
|
+
"upstream_provider": "OpenAI (via OpenRouter)",
|
|
168
|
+
"recommended_inter_call_delay_s": 0.5,
|
|
169
|
+
"comparative_peers": ["z-ai/glm-5.3-flash", "google/gemini-2.0-flash-001"],
|
|
170
|
+
"methodological_notes": "Tier 3 Lightweight Fast commercial baseline.",
|
|
171
|
+
},
|
|
172
|
+
"anthropic/claude-haiku-4.5": {
|
|
173
|
+
"display_name": "Claude Haiku 4.5",
|
|
174
|
+
"family": "Anthropic",
|
|
175
|
+
"capability_tier": CapabilityTier.FRONTIER_FLAGSHIP,
|
|
176
|
+
"tier_rank": 1,
|
|
177
|
+
"upstream_provider": "Anthropic (via OpenRouter)",
|
|
178
|
+
"recommended_inter_call_delay_s": 1.5,
|
|
179
|
+
"comparative_peers": ["deepseek-v4-pro", "openai/gpt-4o"],
|
|
180
|
+
"methodological_notes": "Tier 1 Frontier Flagship lightweight anchor. Frontier upper-bound audit model.",
|
|
181
|
+
},
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def classify_model(
|
|
186
|
+
model_id: str,
|
|
187
|
+
base_url: str = "https://openrouter.ai/api/v1",
|
|
188
|
+
reasoning_effort: str = "none",
|
|
189
|
+
) -> ModelClassification:
|
|
190
|
+
"""Classify model capability tier, provider class, and peers."""
|
|
191
|
+
if "api.deepseek.com" in base_url:
|
|
192
|
+
provider_class = ProviderHostingClass.DIRECT_FIRST_PARTY
|
|
193
|
+
elif "openrouter.ai" in base_url:
|
|
194
|
+
provider_class = ProviderHostingClass.AGGREGATOR_SHARED
|
|
195
|
+
else:
|
|
196
|
+
provider_class = ProviderHostingClass.DIRECT_FIRST_PARTY
|
|
197
|
+
|
|
198
|
+
reasoning_mode = "disabled" if reasoning_effort in ("none", "", None) else f"enabled({reasoning_effort})"
|
|
199
|
+
|
|
200
|
+
meta = _TAXONOMY.get(model_id)
|
|
201
|
+
if meta:
|
|
202
|
+
return ModelClassification(
|
|
203
|
+
model_id=model_id,
|
|
204
|
+
display_name=meta["display_name"],
|
|
205
|
+
family=meta["family"],
|
|
206
|
+
capability_tier=meta["capability_tier"],
|
|
207
|
+
tier_rank=meta["tier_rank"],
|
|
208
|
+
provider_class=provider_class,
|
|
209
|
+
upstream_provider=meta["upstream_provider"],
|
|
210
|
+
reasoning_mode=reasoning_mode,
|
|
211
|
+
recommended_inter_call_delay_s=meta["recommended_inter_call_delay_s"],
|
|
212
|
+
comparative_peers=list(meta["comparative_peers"]),
|
|
213
|
+
methodological_notes=meta["methodological_notes"],
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
return ModelClassification(
|
|
217
|
+
model_id=model_id,
|
|
218
|
+
display_name=model_id,
|
|
219
|
+
family="Unknown",
|
|
220
|
+
capability_tier=CapabilityTier.MID_BALANCED,
|
|
221
|
+
tier_rank=2,
|
|
222
|
+
provider_class=provider_class,
|
|
223
|
+
upstream_provider="Generic / Aggregator",
|
|
224
|
+
reasoning_mode=reasoning_mode,
|
|
225
|
+
recommended_inter_call_delay_s=3.0,
|
|
226
|
+
comparative_peers=[],
|
|
227
|
+
methodological_notes="Uncataloged model evaluated as generic Tier 2.",
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def get_proportional_reasoning_mapping(model_id: str) -> dict[str, str | int]:
|
|
232
|
+
"""Return the normative operational reasoning mapping per model class (ADR-0006).
|
|
233
|
+
|
|
234
|
+
Operational intent:
|
|
235
|
+
- BOOTSTRAP_ANALYSIS: Defensive reasoning (untangle injections from tasks)
|
|
236
|
+
- DRAFT_PROMPT / REVISE_PROMPT: Bounded pre-execution reasoning (entity preservation)
|
|
237
|
+
- DRAFT_PLAN / REVISE_PLAN / EXECUTE: Zero reasoning (mechanical translation)
|
|
238
|
+
"""
|
|
239
|
+
mid = model_id.lower()
|
|
240
|
+
if "glm-4.7" in mid:
|
|
241
|
+
# Class A: Native effort tiers (Zhipu GLM-4.7)
|
|
242
|
+
# ADR-0006 as amended by the ADR-0009 benchmark (2026-09-18): EXECUTE
|
|
243
|
+
# is now the primary semantic generation step (deliverable + Result IR
|
|
244
|
+
# emission), so it is priced HIGH; DRAFT_EXECUTE (entity-dense brief
|
|
245
|
+
# drafting) is likewise semantic -> HIGH; EMIT_RESULT_IR is mechanical
|
|
246
|
+
# correction against explicit host-side errors -> LOW. Translation ops
|
|
247
|
+
# keep the ratified LOW floor (D25: load-bearing); plan drafting stays
|
|
248
|
+
# NONE (measured: 144-token plans, zero reasoning, no quality loss).
|
|
249
|
+
return {
|
|
250
|
+
"BOOTSTRAP_ANALYSIS": "high",
|
|
251
|
+
"DRAFT_PROMPT": "low",
|
|
252
|
+
"REVISE_PROMPT": "low",
|
|
253
|
+
"DRAFT_PLAN": "none",
|
|
254
|
+
"REVISE_PLAN": "none",
|
|
255
|
+
"DRAFT_EXECUTE": "high",
|
|
256
|
+
"EXECUTE": "high",
|
|
257
|
+
"EMIT_RESULT_IR": "low",
|
|
258
|
+
}
|
|
259
|
+
elif "claude" in mid or "anthropic" in mid:
|
|
260
|
+
# Class B: Explicit thinking budget (Anthropic Claude 3.5/3.7 Sonnet, Haiku 4.5)
|
|
261
|
+
return {
|
|
262
|
+
"BOOTSTRAP_ANALYSIS": 4096,
|
|
263
|
+
"DRAFT_PROMPT": 1024,
|
|
264
|
+
"REVISE_PROMPT": 1024,
|
|
265
|
+
"DRAFT_PLAN": "none",
|
|
266
|
+
"REVISE_PLAN": "none",
|
|
267
|
+
"EXECUTE": "none",
|
|
268
|
+
}
|
|
269
|
+
elif "thinking" in mid or "r1" in mid or "o1" in mid or "o3" in mid or "o4" in mid:
|
|
270
|
+
# Class C / Native thinking open-weights / reasoning
|
|
271
|
+
return {
|
|
272
|
+
"BOOTSTRAP_ANALYSIS": "high",
|
|
273
|
+
"DRAFT_PROMPT": "low",
|
|
274
|
+
"REVISE_PROMPT": "low",
|
|
275
|
+
"DRAFT_PLAN": "none",
|
|
276
|
+
"REVISE_PLAN": "none",
|
|
277
|
+
"EXECUTE": "none",
|
|
278
|
+
}
|
|
279
|
+
else:
|
|
280
|
+
# Class D: Pure instruct / quantized models (Llama 3.3, Qwen Instruct, GPT-4o-mini)
|
|
281
|
+
# Native API reasoning disabled; deliberative compute provided in-band via schema.
|
|
282
|
+
return {
|
|
283
|
+
"BOOTSTRAP_ANALYSIS": "none",
|
|
284
|
+
"DRAFT_PROMPT": "none",
|
|
285
|
+
"REVISE_PROMPT": "none",
|
|
286
|
+
"DRAFT_PLAN": "none",
|
|
287
|
+
"REVISE_PLAN": "none",
|
|
288
|
+
"EXECUTE": "none",
|
|
289
|
+
}
|
|
290
|
+
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""Normative Store & Protocol Version Resolver (ADR-0008).
|
|
2
|
+
|
|
3
|
+
Formal 4-Tier Precedence Order for Normative Standards:
|
|
4
|
+
1. Priority 1 (Explicit Environment Override): `PDLT_STANDARDS_PATH` environment variable.
|
|
5
|
+
2. Priority 2 (Local Repository Override): `<repo_root>/contracts/` (if containing `CONTRACT_MANIFEST.json`).
|
|
6
|
+
3. Priority 3 (User Normative Store): `~/.pdlt/versions/<version>/contracts/` (ADR-0008 content-addressed store).
|
|
7
|
+
4. Priority 4 (Bundled Canonical Fallback): `pdl_taskmaster.contracts` package data (via `importlib.resources`).
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import importlib.resources
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
import shutil
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NormativeStoreError(RuntimeError):
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class NormativeStore:
|
|
23
|
+
DEFAULT_VERSION = "v2"
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def get_default_store_root(cls) -> Path:
|
|
27
|
+
env_root = os.environ.get("PDLT_STORE_ROOT")
|
|
28
|
+
if env_root:
|
|
29
|
+
return Path(env_root).resolve()
|
|
30
|
+
return Path.home() / ".pdlt"
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def resolve_version(cls, repo_root: str | Path | None = None) -> str:
|
|
34
|
+
"""Resolve pinned protocol version from .pdlt-version or pdlt.json."""
|
|
35
|
+
if repo_root is not None:
|
|
36
|
+
root = Path(repo_root).resolve()
|
|
37
|
+
pin_file = root / ".pdlt-version"
|
|
38
|
+
if pin_file.is_file():
|
|
39
|
+
v = pin_file.read_text(encoding="utf-8").strip()
|
|
40
|
+
if v:
|
|
41
|
+
return v
|
|
42
|
+
cfg_file = root / "pdlt.json"
|
|
43
|
+
if cfg_file.is_file():
|
|
44
|
+
try:
|
|
45
|
+
data = json.loads(cfg_file.read_text(encoding="utf-8"))
|
|
46
|
+
v = data.get("version")
|
|
47
|
+
if isinstance(v, str) and v.strip():
|
|
48
|
+
return v.strip()
|
|
49
|
+
except Exception:
|
|
50
|
+
pass
|
|
51
|
+
return cls.DEFAULT_VERSION
|
|
52
|
+
|
|
53
|
+
@classmethod
|
|
54
|
+
def get_bundled_contracts_path(cls) -> Path | None:
|
|
55
|
+
"""Resolve path to package-bundled contracts data directory."""
|
|
56
|
+
try:
|
|
57
|
+
bundled = importlib.resources.files("pdl_taskmaster").joinpath("contracts")
|
|
58
|
+
p = Path(str(bundled))
|
|
59
|
+
if p.is_dir() and (p / "CONTRACT_MANIFEST.json").is_file():
|
|
60
|
+
return p
|
|
61
|
+
except Exception:
|
|
62
|
+
pass
|
|
63
|
+
return None
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def resolve_standards_root(
|
|
67
|
+
cls,
|
|
68
|
+
repo_root: str | Path,
|
|
69
|
+
version: str | None = None,
|
|
70
|
+
store_root: str | Path | None = None,
|
|
71
|
+
) -> Path:
|
|
72
|
+
"""Resolve directory containing CONTRACT_MANIFEST.json and standards.
|
|
73
|
+
|
|
74
|
+
Strict 4-Tier Precedence:
|
|
75
|
+
1. PDLT_STANDARDS_PATH env var
|
|
76
|
+
2. Local <repo_root>/contracts/ (if present and valid)
|
|
77
|
+
3. ~/.pdlt/versions/<version>/contracts/ (if seeded)
|
|
78
|
+
4. Bundled package data in pdl_taskmaster.contracts
|
|
79
|
+
"""
|
|
80
|
+
# Tier 1: Explicit environment variable override
|
|
81
|
+
env_standards = os.environ.get("PDLT_STANDARDS_PATH")
|
|
82
|
+
if env_standards:
|
|
83
|
+
p = Path(env_standards).resolve()
|
|
84
|
+
if p.is_dir() and (p / "CONTRACT_MANIFEST.json").is_file():
|
|
85
|
+
return p
|
|
86
|
+
|
|
87
|
+
# Tier 2: Local repository contracts directory
|
|
88
|
+
repo_path = Path(repo_root).resolve()
|
|
89
|
+
local_candidate = repo_path / "contracts"
|
|
90
|
+
if local_candidate.is_dir() and (local_candidate / "CONTRACT_MANIFEST.json").is_file():
|
|
91
|
+
return local_candidate
|
|
92
|
+
|
|
93
|
+
# Tier 3: Centralized ~/.pdlt store
|
|
94
|
+
v = version or cls.resolve_version(repo_path)
|
|
95
|
+
base = Path(store_root).resolve() if store_root else cls.get_default_store_root()
|
|
96
|
+
user_candidate = base / "versions" / v / "contracts"
|
|
97
|
+
if user_candidate.is_dir() and (user_candidate / "CONTRACT_MANIFEST.json").is_file():
|
|
98
|
+
return user_candidate
|
|
99
|
+
|
|
100
|
+
# Tier 4: Bundled package data
|
|
101
|
+
bundled = cls.get_bundled_contracts_path()
|
|
102
|
+
if bundled is not None:
|
|
103
|
+
return bundled
|
|
104
|
+
|
|
105
|
+
return local_candidate
|
|
106
|
+
|
|
107
|
+
@classmethod
|
|
108
|
+
def resolve_contract(
|
|
109
|
+
cls,
|
|
110
|
+
repo_root: str | Path,
|
|
111
|
+
contract_name: str,
|
|
112
|
+
version: str | None = None,
|
|
113
|
+
store_root: str | Path | None = None,
|
|
114
|
+
) -> Path:
|
|
115
|
+
"""Resolve a specific contract file (e.g. EXECUTION_CONTRACT.json)."""
|
|
116
|
+
standards_root = cls.resolve_standards_root(repo_root, version, store_root)
|
|
117
|
+
target = standards_root / contract_name
|
|
118
|
+
if target.is_file():
|
|
119
|
+
return target
|
|
120
|
+
fallback = Path(repo_root).resolve() / "contracts" / contract_name
|
|
121
|
+
return fallback
|
|
122
|
+
|
|
123
|
+
@classmethod
|
|
124
|
+
def seed_directory(cls, target_dir: Path, source_dir: Path | None = None) -> Path:
|
|
125
|
+
"""Copy contract files into target directory from local source or bundled data."""
|
|
126
|
+
target_dir = Path(target_dir).resolve()
|
|
127
|
+
target_dir.mkdir(parents=True, exist_ok=True)
|
|
128
|
+
|
|
129
|
+
src = source_dir
|
|
130
|
+
if src is None or not (src / "CONTRACT_MANIFEST.json").is_file():
|
|
131
|
+
src = cls.get_bundled_contracts_path()
|
|
132
|
+
if src is None or not src.is_dir():
|
|
133
|
+
raise NormativeStoreError("cannot seed contracts: no valid local or bundled source found")
|
|
134
|
+
|
|
135
|
+
for item in src.iterdir():
|
|
136
|
+
dest = target_dir / item.name
|
|
137
|
+
if item.is_dir():
|
|
138
|
+
if dest.exists():
|
|
139
|
+
shutil.rmtree(dest)
|
|
140
|
+
shutil.copytree(item, dest)
|
|
141
|
+
else:
|
|
142
|
+
shutil.copy2(item, dest)
|
|
143
|
+
return target_dir
|
|
144
|
+
|
|
145
|
+
@classmethod
|
|
146
|
+
def seed_store(
|
|
147
|
+
cls,
|
|
148
|
+
repo_root: str | Path,
|
|
149
|
+
version: str = "v2",
|
|
150
|
+
store_root: str | Path | None = None,
|
|
151
|
+
) -> Path:
|
|
152
|
+
"""Seed the centralized ~/.pdlt store from the current repository contracts or bundled data."""
|
|
153
|
+
repo_path = Path(repo_root).resolve()
|
|
154
|
+
base = Path(store_root).resolve() if store_root else cls.get_default_store_root()
|
|
155
|
+
target_dir = base / "versions" / version / "contracts"
|
|
156
|
+
local_src = repo_path / "contracts" if (repo_path / "contracts").is_dir() else None
|
|
157
|
+
return cls.seed_directory(target_dir, source_dir=local_src)
|