counterdex 0.3.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.
- counterdex/__init__.py +39 -0
- counterdex/__main__.py +116 -0
- counterdex/analytical.py +116 -0
- counterdex/application.py +345 -0
- counterdex/arithmetic.py +115 -0
- counterdex/baseline.py +119 -0
- counterdex/bridge.py +268 -0
- counterdex/capabilities.py +73 -0
- counterdex/checked.py +225 -0
- counterdex/errors.py +28 -0
- counterdex/exact.py +248 -0
- counterdex/followup.py +173 -0
- counterdex/historical.py +252 -0
- counterdex/identity.py +20 -0
- counterdex/interpretation.py +23 -0
- counterdex/models.py +338 -0
- counterdex/native_packet.py +255 -0
- counterdex/numerical.py +118 -0
- counterdex/pipeline.py +81 -0
- counterdex/replay.py +143 -0
- counterdex/replay_baseline.py +112 -0
- counterdex/replay_numeric.py +164 -0
- counterdex/resource.py +43 -0
- counterdex/search.py +276 -0
- counterdex-0.3.0.dist-info/METADATA +210 -0
- counterdex-0.3.0.dist-info/RECORD +29 -0
- counterdex-0.3.0.dist-info/WHEEL +5 -0
- counterdex-0.3.0.dist-info/entry_points.txt +2 -0
- counterdex-0.3.0.dist-info/top_level.txt +1 -0
counterdex/__init__.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Counterdex scientific adapter. Expensive/producer entry points load lazily."""
|
|
2
|
+
from .errors import AdapterError
|
|
3
|
+
from .identity import VERSION as __version__
|
|
4
|
+
from .models import normalize_design, normalize_problem, normalize_times
|
|
5
|
+
from .resource import ExecutionContext
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def create_suggestion(*args, **kwargs):
|
|
9
|
+
from .pipeline import create_suggestion as implementation
|
|
10
|
+
return implementation(*args, **kwargs)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def replay_bundle(*args, **kwargs):
|
|
14
|
+
from .replay import replay_bundle as implementation
|
|
15
|
+
return implementation(*args, **kwargs)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def capabilities():
|
|
19
|
+
from .capabilities import capabilities as implementation
|
|
20
|
+
return implementation()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def create_baseline(*args, **kwargs):
|
|
24
|
+
from .baseline import create_baseline as implementation
|
|
25
|
+
return implementation(*args, **kwargs)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def replay_baseline(*args, **kwargs):
|
|
29
|
+
from .replay_baseline import replay_baseline as implementation
|
|
30
|
+
return implementation(*args, **kwargs)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def replay_packet(*args, **kwargs):
|
|
34
|
+
from .native_packet import replay_packet as implementation
|
|
35
|
+
return implementation(*args, **kwargs)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
__all__ = ["AdapterError", "ExecutionContext", "normalize_design", "normalize_problem", "normalize_times",
|
|
39
|
+
"create_suggestion", "replay_bundle", "create_baseline", "replay_baseline", "replay_packet", "capabilities"]
|
counterdex/__main__.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Local commands; supplied evidence can never select a path, URL, or import."""
|
|
2
|
+
import argparse
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import sys
|
|
6
|
+
import tempfile
|
|
7
|
+
|
|
8
|
+
from .errors import AdapterError
|
|
9
|
+
from .exact import canonical_bytes, strict_json_loads
|
|
10
|
+
from .models import fields
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _read(path: str, maximum: int = 4 * 1024 * 1024) -> bytes:
|
|
14
|
+
with Path(path).open("rb") as stream:
|
|
15
|
+
data = stream.read(maximum + 1)
|
|
16
|
+
if len(data) > maximum:
|
|
17
|
+
raise AdapterError("resource_exhaustion", "Input file exceeds the admitted byte limit.")
|
|
18
|
+
return data
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _write_complete(path: str, content: bytes) -> None:
|
|
22
|
+
"""Link a fully written same-filesystem file without replacing a destination."""
|
|
23
|
+
destination = Path(path)
|
|
24
|
+
temporary = None
|
|
25
|
+
try:
|
|
26
|
+
with tempfile.NamedTemporaryFile(dir=destination.parent, prefix=".counterdex-", delete=False) as output:
|
|
27
|
+
temporary = Path(output.name)
|
|
28
|
+
output.write(content)
|
|
29
|
+
output.flush()
|
|
30
|
+
os.fsync(output.fileno())
|
|
31
|
+
os.link(temporary, destination)
|
|
32
|
+
finally:
|
|
33
|
+
if temporary is not None:
|
|
34
|
+
temporary.unlink(missing_ok=True)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def main(argv: list[str] | None = None) -> int:
|
|
38
|
+
parser = argparse.ArgumentParser(description="Counterdex bounded scientific adapter")
|
|
39
|
+
commands = parser.add_subparsers(dest="command", required=True)
|
|
40
|
+
commands.add_parser("capabilities", help="Print qualified scientific capability metadata")
|
|
41
|
+
commands.add_parser("bridge", help="Read one bounded application request from stdin and write one response")
|
|
42
|
+
baseline = commands.add_parser("baseline", help="Discover and exactly check candidates for a reviewed historical problem")
|
|
43
|
+
baseline.add_argument("request")
|
|
44
|
+
baseline.add_argument("--output", required=True)
|
|
45
|
+
historical = commands.add_parser("replay-baseline", help="Fresh exact historical replay")
|
|
46
|
+
historical.add_argument("bundle")
|
|
47
|
+
native = commands.add_parser("replay-native", help="Replay an application-bound native packet and its full lineage")
|
|
48
|
+
native.add_argument("bundle")
|
|
49
|
+
native.add_argument("--anchors", required=True)
|
|
50
|
+
run = commands.add_parser("run", help="Run a frozen scientific request (approval is the caller's responsibility)")
|
|
51
|
+
run.add_argument("request")
|
|
52
|
+
run.add_argument("--output", required=True)
|
|
53
|
+
replay = commands.add_parser("replay", help="Fresh exact replay against separately supplied trust anchors")
|
|
54
|
+
replay.add_argument("bundle")
|
|
55
|
+
for command in (run, replay, baseline, historical):
|
|
56
|
+
command.add_argument("--anchors", help="Separate trusted local identity file; never selected by evidence")
|
|
57
|
+
command.add_argument("--expected-problem")
|
|
58
|
+
run.add_argument("--expected-design")
|
|
59
|
+
replay.add_argument("--expected-suggestion")
|
|
60
|
+
historical.add_argument("--expected-baseline")
|
|
61
|
+
historical.add_argument("--expected-scenario")
|
|
62
|
+
args = parser.parse_args(argv)
|
|
63
|
+
try:
|
|
64
|
+
if args.command == "bridge":
|
|
65
|
+
from .bridge import main as bridge_main
|
|
66
|
+
return bridge_main()
|
|
67
|
+
if args.command == "capabilities":
|
|
68
|
+
from .capabilities import capabilities
|
|
69
|
+
result = capabilities()
|
|
70
|
+
elif args.command == "replay-native":
|
|
71
|
+
from .native_packet import replay_packet
|
|
72
|
+
result = replay_packet(_read(args.bundle), expected=strict_json_loads(_read(args.anchors, 4096)))
|
|
73
|
+
else:
|
|
74
|
+
anchors = strict_json_loads(_read(args.anchors, 4096), max_bytes=4096) if args.anchors else {}
|
|
75
|
+
allowed = {"problem_digest", "baseline_digest", "scenario_id"} if args.command in ("baseline", "replay-baseline") else {"problem_digest", "design_digest", "suggestion_digest"}
|
|
76
|
+
if not isinstance(anchors, dict) or set(anchors) - allowed:
|
|
77
|
+
raise AdapterError("invalid_input", "Unexpected trust-anchor fields.")
|
|
78
|
+
expected_problem = args.expected_problem or anchors.get("problem_digest")
|
|
79
|
+
if args.command == "baseline":
|
|
80
|
+
from .baseline import create_baseline
|
|
81
|
+
request = fields(strict_json_loads(_read(args.request)), {"problem", "scenario_id", "workflow", "search_settings"}, "request")
|
|
82
|
+
content = create_baseline(request["problem"], expected_problem_digest=expected_problem,
|
|
83
|
+
scenario_id=request["scenario_id"], workflow=request["workflow"], settings=request["search_settings"])
|
|
84
|
+
_write_complete(args.output, content)
|
|
85
|
+
result = {"output": args.output, "artifact_bytes": len(content), "baseline_digest": strict_json_loads(content)["baseline_digest"]}
|
|
86
|
+
elif args.command == "replay-baseline":
|
|
87
|
+
from .replay_baseline import replay_baseline
|
|
88
|
+
result = replay_baseline(_read(args.bundle), expected_problem_digest=expected_problem,
|
|
89
|
+
expected_baseline_digest=args.expected_baseline or anchors.get("baseline_digest"),
|
|
90
|
+
expected_scenario_id=args.expected_scenario or anchors.get("scenario_id"))
|
|
91
|
+
elif args.command == "run":
|
|
92
|
+
from .pipeline import create_suggestion
|
|
93
|
+
request = fields(strict_json_loads(_read(args.request)), {"problem", "design", "workflow"}, "request")
|
|
94
|
+
content = create_suggestion(request["problem"], request["design"], workflow=request["workflow"],
|
|
95
|
+
expected_problem_digest=expected_problem,
|
|
96
|
+
expected_design_digest=args.expected_design or anchors.get("design_digest"))
|
|
97
|
+
# User-specified destination only; never replace an existing file.
|
|
98
|
+
_write_complete(args.output, content)
|
|
99
|
+
result = {"output": args.output, "artifact_bytes": len(content),
|
|
100
|
+
"suggestion_digest": strict_json_loads(content)["suggestion_digest"]}
|
|
101
|
+
else:
|
|
102
|
+
from .replay import replay_bundle
|
|
103
|
+
result = replay_bundle(_read(args.bundle), expected_problem_digest=expected_problem,
|
|
104
|
+
expected_suggestion_digest=args.expected_suggestion or anchors.get("suggestion_digest"))
|
|
105
|
+
sys.stdout.buffer.write(canonical_bytes(result) + b"\n")
|
|
106
|
+
return 0 if result.get("replay") != "failed" else 1
|
|
107
|
+
except AdapterError as error:
|
|
108
|
+
sys.stderr.buffer.write(canonical_bytes({"error": error.to_dict()}) + b"\n")
|
|
109
|
+
return 2
|
|
110
|
+
except OSError:
|
|
111
|
+
sys.stderr.buffer.write(canonical_bytes({"error": {"code": "local_io_failure", "message": "Could not read or exclusively create the supplied local file."}}) + b"\n")
|
|
112
|
+
return 2
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
if __name__ == "__main__":
|
|
116
|
+
raise SystemExit(main())
|
counterdex/analytical.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Bounded exact enclosures for the declared two-rate analytic template.
|
|
2
|
+
|
|
3
|
+
For rational 0 <= u <= 1, the alternating Taylor series for exp(-u) has
|
|
4
|
+
nonincreasing term magnitudes and remainder of the next term's sign. Thus
|
|
5
|
+
S33 <= exp(-u) <= S32, where Sn = sum((-u)**j / j!, j=0..n).
|
|
6
|
+
Rational floor/ceiling to a 2**-128 lattice preserve these inequalities.
|
|
7
|
+
For z = 2**k * u, repeated squaring preserves enclosure on nonnegative
|
|
8
|
+
intervals; each step rounds outward again. Replacing a negative lower bound
|
|
9
|
+
by zero is valid because exp is positive. No floating-point value enters.
|
|
10
|
+
|
|
11
|
+
These are a new, fixed analytic-template calculation. They neither parse nor
|
|
12
|
+
check general ODE/polynomial evidence. The policy fixes degree, lattice and
|
|
13
|
+
resource limits; a difficult input cannot trigger hidden adaptive refinement.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from fractions import Fraction
|
|
17
|
+
|
|
18
|
+
from .errors import AdapterError
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
EXP_POLICY = "alternating32-dyadic128.v1"
|
|
22
|
+
MAX_ARGUMENT_BITS = 256
|
|
23
|
+
MAX_ARGUMENT = Fraction(1024)
|
|
24
|
+
MAX_REDUCTIONS = 10
|
|
25
|
+
TAYLOR_EVEN_DEGREE = 32
|
|
26
|
+
DYADIC_BITS = 128
|
|
27
|
+
_LATTICE = 1 << DYADIC_BITS
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _bounded_fraction(value: object, field: str) -> Fraction:
|
|
31
|
+
if type(value) is not Fraction:
|
|
32
|
+
raise AdapterError("invalid_input", "An exact Fraction is required.", (field,))
|
|
33
|
+
if max(value.numerator.bit_length(), value.denominator.bit_length()) > MAX_ARGUMENT_BITS:
|
|
34
|
+
raise AdapterError(
|
|
35
|
+
"construction_range", "Exact analytic input exceeds the fixed arithmetic limit.", (field,)
|
|
36
|
+
)
|
|
37
|
+
return value
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _round_down(value: Fraction) -> Fraction:
|
|
41
|
+
return Fraction((value.numerator * _LATTICE) // value.denominator, _LATTICE)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _round_up(value: Fraction) -> Fraction:
|
|
45
|
+
scaled = value.numerator * _LATTICE
|
|
46
|
+
return Fraction(-((-scaled) // value.denominator), _LATTICE)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def exp_neg_interval(z: Fraction) -> tuple[Fraction, Fraction]:
|
|
50
|
+
"""Enclose exp(-z), with 0 <= z <= 1024, using the fixed named policy.
|
|
51
|
+
|
|
52
|
+
Each argument numerator and denominator may have at most 256 bits.
|
|
53
|
+
Returned endpoints are rational dyadics whose denominators divide 2**128.
|
|
54
|
+
At large z the interval may have a zero lower endpoint; no relative-error
|
|
55
|
+
guarantee or zero-error trajectory claim follows from a narrow interval.
|
|
56
|
+
"""
|
|
57
|
+
z = _bounded_fraction(z, "argument")
|
|
58
|
+
if z < 0:
|
|
59
|
+
raise AdapterError("invalid_input", "The exponential argument must be nonnegative.", ("argument",))
|
|
60
|
+
if z > MAX_ARGUMENT:
|
|
61
|
+
raise AdapterError(
|
|
62
|
+
"construction_range", "The exponential argument exceeds the fixed analytic range.", ("argument",)
|
|
63
|
+
)
|
|
64
|
+
if z == 0:
|
|
65
|
+
return Fraction(1), Fraction(1)
|
|
66
|
+
|
|
67
|
+
reduced = z
|
|
68
|
+
reductions = 0
|
|
69
|
+
for _ in range(MAX_REDUCTIONS):
|
|
70
|
+
if reduced <= 1:
|
|
71
|
+
break
|
|
72
|
+
reduced /= 2
|
|
73
|
+
reductions += 1
|
|
74
|
+
if reduced > 1:
|
|
75
|
+
raise AdapterError(
|
|
76
|
+
"construction_range", "The fixed range-reduction budget is insufficient.", ("argument",)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
term = Fraction(1)
|
|
80
|
+
total = Fraction(1)
|
|
81
|
+
for degree in range(1, TAYLOR_EVEN_DEGREE + 1):
|
|
82
|
+
term *= -reduced / degree
|
|
83
|
+
total += term
|
|
84
|
+
upper = _round_up(total)
|
|
85
|
+
next_term = term * -reduced / (TAYLOR_EVEN_DEGREE + 1)
|
|
86
|
+
lower = max(Fraction(0), _round_down(total + next_term))
|
|
87
|
+
|
|
88
|
+
for _ in range(reductions):
|
|
89
|
+
lower = max(Fraction(0), _round_down(lower * lower))
|
|
90
|
+
upper = _round_up(upper * upper)
|
|
91
|
+
return lower, upper
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def concentration_interval(
|
|
95
|
+
A: Fraction, ke: Fraction, ka: Fraction, t: Fraction
|
|
96
|
+
) -> tuple[Fraction, Fraction]:
|
|
97
|
+
"""Enclose A*(exp(-ke*t)-exp(-ka*t)) for the fixed analytic template.
|
|
98
|
+
|
|
99
|
+
Requires A > 0, 0 < ke < ka, t >= 0 and bounded rational inputs. Each
|
|
100
|
+
rate*time product must also satisfy exp_neg_interval's admission policy.
|
|
101
|
+
Subtracting intervals and positive exact scaling are sound even if the
|
|
102
|
+
conservative lower concentration bound is negative.
|
|
103
|
+
"""
|
|
104
|
+
A = _bounded_fraction(A, "parameters/A")
|
|
105
|
+
ke = _bounded_fraction(ke, "parameters/ke")
|
|
106
|
+
ka = _bounded_fraction(ka, "parameters/ka")
|
|
107
|
+
t = _bounded_fraction(t, "time")
|
|
108
|
+
if A <= 0 or not 0 < ke < ka:
|
|
109
|
+
raise AdapterError(
|
|
110
|
+
"invalid_input", "The analytic template requires A > 0 and 0 < ke < ka.", ("parameters",)
|
|
111
|
+
)
|
|
112
|
+
if t < 0:
|
|
113
|
+
raise AdapterError("invalid_input", "Time must be nonnegative.", ("time",))
|
|
114
|
+
slow_lower, slow_upper = exp_neg_interval(ke * t)
|
|
115
|
+
fast_lower, fast_upper = exp_neg_interval(ka * t)
|
|
116
|
+
return A * (slow_lower - fast_upper), A * (slow_upper - fast_lower)
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
"""Reproducible scientific projection of authoritative DB-SC-1 application input.
|
|
2
|
+
|
|
3
|
+
The API owns application DTO validation and approval. This module does not
|
|
4
|
+
provide competing transport models. It binds the API's complete normalized
|
|
5
|
+
bodies, checks the narrower scientific admission rules, and records the exact
|
|
6
|
+
projection policy so an offline verifier can repeat the transformation.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from copy import deepcopy
|
|
12
|
+
import re
|
|
13
|
+
|
|
14
|
+
from .errors import AdapterError
|
|
15
|
+
from .exact import canonical_bytes, parse_rational, rational_text, semantic_digest
|
|
16
|
+
from .models import (CHECKED_POLICY, DESIGN_PROFILE, MODEL, NUMERICAL_POLICY,
|
|
17
|
+
PROBLEM_PROFILE, digest_value, normalize_design,
|
|
18
|
+
normalize_problem)
|
|
19
|
+
|
|
20
|
+
MAPPING_POLICY = "DB-SC-1-to-groundwork-v1"
|
|
21
|
+
DESIGN_MAPPING_POLICY = "DB-SC-1-design-to-groundwork-v2"
|
|
22
|
+
APPLICATION_BINDING = "counterdex.application-binding.v1"
|
|
23
|
+
DESIGN_BINDING = "counterdex.application-design-binding.v1"
|
|
24
|
+
APPLICATION_BODY_CAP = 1024 * 1024
|
|
25
|
+
_IDENTIFIER = re.compile(r"[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}\Z")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _error(code: str, message: str, path: str) -> AdapterError:
|
|
29
|
+
return AdapterError(code, message, (path,))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _object(value: object, path: str) -> dict:
|
|
33
|
+
if type(value) is not dict:
|
|
34
|
+
raise _error("invalid_input", "Expected an application object.", path)
|
|
35
|
+
return value
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _get(value: dict, key: str, path: str) -> object:
|
|
39
|
+
if key not in value:
|
|
40
|
+
raise _error("invalid_input", "The normalized application field is required.", path + "/" + key)
|
|
41
|
+
return value[key]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _identifier(value: object, path: str) -> str:
|
|
45
|
+
if type(value) is not str or _IDENTIFIER.fullmatch(value) is None:
|
|
46
|
+
raise _error("invalid_input", "Expected an application identifier.", path)
|
|
47
|
+
return value
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _exact(value: object, path: str, *, positive: bool = False, nonnegative: bool = False) -> str:
|
|
51
|
+
fraction = parse_rational(value, path)
|
|
52
|
+
if rational_text(fraction) != value:
|
|
53
|
+
raise _error("invalid_input", "Supply the application's normalized rational spelling.", path)
|
|
54
|
+
if (positive and fraction <= 0) or (nonnegative and fraction < 0):
|
|
55
|
+
raise _error("invalid_input", "The exact application value is outside its admitted range.", path)
|
|
56
|
+
return value
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _record(value: object, kind: str) -> dict:
|
|
60
|
+
record = _object(value, kind)
|
|
61
|
+
if record.get("kind", kind) != kind:
|
|
62
|
+
raise _error("wrong_specification_binding", "The application record has a different kind.", kind)
|
|
63
|
+
identifier = _identifier(_get(record, "id", kind), kind + "/id")
|
|
64
|
+
digest = digest_value(_get(record, "digest", kind), kind + "/digest")
|
|
65
|
+
body = _object(_get(record, "body", kind), kind + "/body")
|
|
66
|
+
if len(canonical_bytes(body)) > APPLICATION_BODY_CAP:
|
|
67
|
+
raise _error("resource_exhaustion", "Application body exceeds the admitted byte cap.", kind + "/body")
|
|
68
|
+
if body.get("schema_version") != "DB-SC-1":
|
|
69
|
+
raise _error("unsupported_model", "Only normalized DB-SC-1 application bodies are supported.", kind + "/body/schema_version")
|
|
70
|
+
if semantic_digest(kind, body) != digest:
|
|
71
|
+
raise _error("wrong_specification_binding", "Application body differs from its expected record digest.", kind + "/digest")
|
|
72
|
+
return deepcopy({"id": identifier, "digest": digest, "body": body})
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def project_application(problem_record: dict, dataset_record: dict) -> dict:
|
|
76
|
+
"""Bind full application bodies and return the admitted scientific payload.
|
|
77
|
+
|
|
78
|
+
Record envelopes may include server bookkeeping. The immutable binding
|
|
79
|
+
retains id/digest/body; authorization and workspace membership remain the
|
|
80
|
+
server's responsibility. No metadata is squeezed into scientific text caps.
|
|
81
|
+
"""
|
|
82
|
+
problem = _record(problem_record, "problem")
|
|
83
|
+
dataset = _record(dataset_record, "dataset")
|
|
84
|
+
p, d = problem["body"], dataset["body"]
|
|
85
|
+
if p.get("dataset_id") != dataset["id"] or p.get("dataset_digest") != dataset["digest"]:
|
|
86
|
+
raise _error("wrong_specification_binding", "Problem must bind the supplied dataset identity.", "problem/body/dataset_digest")
|
|
87
|
+
supported = {"model": "two_rate_concentration", "initial_concentration": "0/1",
|
|
88
|
+
"observable": "concentration", "time_unit": "h",
|
|
89
|
+
"concentration_unit": "mg/L", "rate_unit": "1/h"}
|
|
90
|
+
for key, expected in supported.items():
|
|
91
|
+
if p.get(key) != expected:
|
|
92
|
+
raise _error("unsupported_model", "Application model, initial state and units must match the fixed template.", "problem/body/" + key)
|
|
93
|
+
origin = d.get("origin")
|
|
94
|
+
if origin not in ("actual", "hypothetical", "synthetic"):
|
|
95
|
+
raise _error("unsupported_model", "Declare the application dataset origin.", "dataset/body/origin")
|
|
96
|
+
rows = _get(d, "rows", "dataset/body")
|
|
97
|
+
if type(rows) is not list or not 3 <= len(rows) <= 128:
|
|
98
|
+
raise _error("unsupported_model", "This scientific profile admits 3 to 128 rows without dropping excluded rows.", "dataset/body/rows")
|
|
99
|
+
domain = _object(_get(p, "domain", "problem/body"), "problem/body/domain")
|
|
100
|
+
if domain.get("rate_order") != "ke_lt_ka":
|
|
101
|
+
raise _error("unsupported_model", "The fixed model requires the reviewed ke < ka order.", "problem/body/domain/rate_order")
|
|
102
|
+
box = {}
|
|
103
|
+
for name in ("A", "ke", "ka"):
|
|
104
|
+
bounds = _object(_get(domain, name, "problem/body/domain"), "problem/body/domain/" + name)
|
|
105
|
+
box[name] = [_exact(_get(bounds, endpoint, "problem/body/domain/" + name),
|
|
106
|
+
"problem/body/domain/" + name + "/" + endpoint, positive=True)
|
|
107
|
+
for endpoint in ("lower", "upper")]
|
|
108
|
+
if parse_rational(box[name][0]) >= parse_rational(box[name][1]):
|
|
109
|
+
raise _error("unsupported_model", "The scientific profile requires positive-width parameter domains.", "problem/body/domain/" + name)
|
|
110
|
+
if parse_rational(box["ke"][1]) >= parse_rational(box["ka"][0]):
|
|
111
|
+
raise _error("unsupported_model", "This scientific profile requires upper(ke) < lower(ka).", "problem/body/domain")
|
|
112
|
+
target = _object(_get(p, "target", "problem/body"), "problem/body/target")
|
|
113
|
+
if target.get("parameter") != "ke" or target.get("closed") is not True:
|
|
114
|
+
raise _error("unsupported_model", "Only the reviewed closed ke interval is admitted.", "problem/body/target")
|
|
115
|
+
claim = [_exact(_get(target, endpoint, "problem/body/target"), "problem/body/target/" + endpoint)
|
|
116
|
+
for endpoint in ("lower", "upper")]
|
|
117
|
+
projected_rows = []
|
|
118
|
+
for index, source in enumerate(rows):
|
|
119
|
+
path = f"dataset/body/rows/{index}"
|
|
120
|
+
row = _object(source, path)
|
|
121
|
+
row_id = _identifier(_get(row, "id", path), path + "/id")
|
|
122
|
+
asset_id = _get(row, "source_asset_id", path)
|
|
123
|
+
if asset_id is not None:
|
|
124
|
+
_identifier(asset_id, path + "/source_asset_id")
|
|
125
|
+
included = _get(row, "included", path)
|
|
126
|
+
if type(included) is not bool:
|
|
127
|
+
raise _error("invalid_input", "Row inclusion must be an explicit boolean.", path + "/included")
|
|
128
|
+
row_origin = "hypothetical" if origin != "actual" else "transcription" if asset_id is not None else "actual"
|
|
129
|
+
projected_rows.append({
|
|
130
|
+
"id": row_id, "time": _exact(_get(row, "time", path), path + "/time", nonnegative=True),
|
|
131
|
+
"value": _exact(_get(row, "concentration", path), path + "/concentration", nonnegative=True),
|
|
132
|
+
"allowance": _exact(_get(row, "hard_allowance", path), path + "/hard_allowance", positive=True),
|
|
133
|
+
"included": included, "allowance_origin": "Reviewed DB-SC-1 row hard_allowance",
|
|
134
|
+
"origin": row_origin, "notes": _get(row, "notes", path),
|
|
135
|
+
"provenance": f"DB-SC-1 dataset {dataset['digest']}; row {row_id}; complete source in binding envelope",
|
|
136
|
+
})
|
|
137
|
+
if len({row["time"] for row in projected_rows if row["included"]}) < 3:
|
|
138
|
+
raise _error("unsupported_model", "At least three distinct included elapsed times are required.", "dataset/body/rows")
|
|
139
|
+
scientific = normalize_problem({
|
|
140
|
+
"schema_version": PROBLEM_PROFILE, "model": MODEL, "model_revision": 1,
|
|
141
|
+
"units": {"time": "h", "concentration": "mg/L", "rate": "1/h"},
|
|
142
|
+
"initial_conditions": {"x": "1/1", "c": "0/1"},
|
|
143
|
+
"time_origin": _get(d, "time_origin", "dataset/body"),
|
|
144
|
+
"dataset_kind": "actual" if origin == "actual" else "hypothetical",
|
|
145
|
+
"domain": box, "claim": {"parameter": "ke", "interval": claim},
|
|
146
|
+
"observations": projected_rows, "notes": _get(d, "change_reason", "dataset/body"),
|
|
147
|
+
"provenance": f"{MAPPING_POLICY}; application problem {problem['digest']}; dataset {dataset['digest']}; original origin {origin}",
|
|
148
|
+
})
|
|
149
|
+
binding = {"schema_version": APPLICATION_BINDING, "mapping_policy": MAPPING_POLICY,
|
|
150
|
+
"dataset": dataset, "problem": problem, "dataset_origin": origin,
|
|
151
|
+
"projection_digest": scientific.digest}
|
|
152
|
+
return {"binding": binding, "problem": scientific.to_payload(), "projection_digest": scientific.digest}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def verify_application_binding(binding: dict) -> dict:
|
|
156
|
+
"""Reproduce a stored mapping; an internally consistent binding is not approval."""
|
|
157
|
+
b = _object(binding, "binding")
|
|
158
|
+
if b.get("schema_version") != APPLICATION_BINDING or b.get("mapping_policy") != MAPPING_POLICY:
|
|
159
|
+
raise _error("unsupported_model", "Unsupported application projection policy.", "binding/mapping_policy")
|
|
160
|
+
projected = project_application(_get(b, "problem", "binding"), _get(b, "dataset", "binding"))
|
|
161
|
+
if projected["binding"] != b:
|
|
162
|
+
raise _error("wrong_specification_binding", "Stored application projection differs from fresh mapping.", "binding")
|
|
163
|
+
return projected
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _candidate_vector(value: object, path: str) -> dict:
|
|
167
|
+
vector = _object(value, path)
|
|
168
|
+
if set(vector) != {"A", "ke", "ka"}:
|
|
169
|
+
raise _error("candidate_mismatch", "A complete fixed vector is required.", path)
|
|
170
|
+
return {name: _exact(vector[name], path + "/" + name, positive=True) for name in ("A", "ke", "ka")}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _design_policy(request: dict, scientific_problem, times: list[str], budget: dict, expected: str) -> tuple:
|
|
174
|
+
"""Keep legacy replay stable while binding every explicit reviewed choice."""
|
|
175
|
+
sources = request.get("source_artifact_ids", [])
|
|
176
|
+
if type(sources) is not list or len(sources) > 2:
|
|
177
|
+
raise _error("invalid_input", "Supply at most two source artifact identifiers.", "request/source_artifact_ids")
|
|
178
|
+
for index, source in enumerate(sources):
|
|
179
|
+
_identifier(source, f"request/source_artifact_ids/{index}")
|
|
180
|
+
if len(set(sources)) != len(sources):
|
|
181
|
+
raise _error("invalid_input", "Source artifact identifiers must be unique.", "request/source_artifact_ids")
|
|
182
|
+
profile = request.get("scientific_profile")
|
|
183
|
+
explicit_fields = ("requested_tier", "allowance_origin", "maximum_horizon")
|
|
184
|
+
if profile is None:
|
|
185
|
+
if sources or any(request.get(field) is not None for field in explicit_fields):
|
|
186
|
+
raise _error("invalid_input", "Explicit scientific choices require the counterdex.v1 profile.", "request/scientific_profile")
|
|
187
|
+
horizon = max(scientific_problem.horizon, *(parse_rational(time) for time in times))
|
|
188
|
+
return (MAPPING_POLICY, "checked_pair_separation",
|
|
189
|
+
{"kind": "reviewed_hard_bound", "description": f"Approved DB-SC-1 design request {expected}; future_hard_allowance"},
|
|
190
|
+
rational_text(horizon))
|
|
191
|
+
if profile != "counterdex.v1":
|
|
192
|
+
raise _error("unsupported_model", "Unsupported application scientific profile.", "request/scientific_profile")
|
|
193
|
+
for field in explicit_fields:
|
|
194
|
+
if request.get(field) is None:
|
|
195
|
+
raise _error("invalid_input", "Review this scientific design choice explicitly.", "request/" + field)
|
|
196
|
+
tier = request["requested_tier"]
|
|
197
|
+
if tier not in ("numerical_guidance", "checked_pair_separation"):
|
|
198
|
+
raise _error("invalid_input", "Select an admitted scientific design tier.", "request/requested_tier")
|
|
199
|
+
origin = _object(request["allowance_origin"], "request/allowance_origin")
|
|
200
|
+
if set(origin) != {"kind", "description"} or origin.get("kind") not in ("hypothetical", "reviewed_hard_bound"):
|
|
201
|
+
raise _error("invalid_input", "Declare the reviewed allowance kind and description.", "request/allowance_origin")
|
|
202
|
+
description = origin["description"]
|
|
203
|
+
if type(description) is not str or not 1 <= len(description) <= 2000:
|
|
204
|
+
raise _error("invalid_input", "Supply the reviewed allowance description.", "request/allowance_origin/description")
|
|
205
|
+
horizon = _exact(request["maximum_horizon"], "request/maximum_horizon", positive=True)
|
|
206
|
+
if parse_rational(horizon) < scientific_problem.horizon or any(parse_rational(time) > parse_rational(horizon) for time in times):
|
|
207
|
+
raise _error("unavailable_horizon", "The reviewed horizon must cover included history and every approved time.", "request/maximum_horizon")
|
|
208
|
+
if tier == "checked_pair_separation" and budget["pair_verifications"] < 2:
|
|
209
|
+
raise _error("invalid_input", "Checked design requires initial checking and fresh pair replay.", "request/budget/pair_verifications")
|
|
210
|
+
if sources:
|
|
211
|
+
raise _error("unsupported_artifact_reuse", "Prospective certificate reuse is not supported by this application bridge.", "request/source_artifact_ids")
|
|
212
|
+
return DESIGN_MAPPING_POLICY, tier, origin, horizon
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def project_design(request: dict, *, expected_request_digest: str, projection: dict,
|
|
216
|
+
historical_evidence: dict, native_candidate_results: list[dict]) -> dict:
|
|
217
|
+
"""Project the approved design after the bridge freshly replays its history.
|
|
218
|
+
|
|
219
|
+
``historical_evidence`` is the actual evidence body stored by Workflow.
|
|
220
|
+
``native_candidate_results`` must come from fresh native certificate replay,
|
|
221
|
+
never directly from a stored valid flag. The wrapper verifies raw artifacts
|
|
222
|
+
and their source/scenario bindings before calling this projection function.
|
|
223
|
+
"""
|
|
224
|
+
current = verify_application_binding(_get(_object(projection, "projection"), "binding", "projection"))
|
|
225
|
+
if projection != current:
|
|
226
|
+
raise _error("wrong_specification_binding", "The supplied scientific projection was changed.", "projection")
|
|
227
|
+
request = deepcopy(_object(request, "request"))
|
|
228
|
+
if len(canonical_bytes(request)) > APPLICATION_BODY_CAP:
|
|
229
|
+
raise _error("resource_exhaustion", "Application request exceeds its byte cap.", "request")
|
|
230
|
+
expected = digest_value(expected_request_digest, "expected_request_digest")
|
|
231
|
+
if request.get("schema_version") != "DB-SC-1" or semantic_digest("design-request", request) != expected:
|
|
232
|
+
raise _error("wrong_specification_binding", "Design request differs from the independently supplied digest.", "request")
|
|
233
|
+
binding = current["binding"]
|
|
234
|
+
app_problem = binding["problem"]
|
|
235
|
+
if request.get("problem_id") != app_problem["id"] or request.get("problem_digest") != app_problem["digest"]:
|
|
236
|
+
raise _error("wrong_specification_binding", "Design must bind the supplied application problem.", "request/problem_digest")
|
|
237
|
+
if request.get("observable") != "concentration":
|
|
238
|
+
raise _error("unsupported_model", "The design observable must be concentration.", "request/observable")
|
|
239
|
+
evidence = deepcopy(_object(historical_evidence, "historical_evidence"))
|
|
240
|
+
for field, expected_value in (("run_id", request.get("historical_run_id")), ("scenario_id", request.get("scenario_id")),
|
|
241
|
+
("problem_id", app_problem["id"]), ("expected_problem_digest", app_problem["digest"])):
|
|
242
|
+
if field in {"run_id", "scenario_id", "problem_id"}:
|
|
243
|
+
_identifier(expected_value, "request/" + field)
|
|
244
|
+
if evidence.get(field) != expected_value:
|
|
245
|
+
raise _error("wrong_specification_binding", "Historical evidence belongs to a different approved scope.", "historical_evidence/" + field)
|
|
246
|
+
result = _object(_get(evidence, "result", "historical_evidence"), "historical_evidence/result")
|
|
247
|
+
if result.get("problem_id") != app_problem["id"] or result.get("problem_digest") != app_problem["digest"] or result.get("expected_binding") != "matches":
|
|
248
|
+
raise _error("wrong_specification_binding", "Historical result must match the reviewed application problem.", "historical_evidence/result")
|
|
249
|
+
ids, vectors = request.get("candidate_ids"), request.get("candidate_vectors")
|
|
250
|
+
if type(ids) is not list or type(vectors) is not list or len(ids) != 2 or len(vectors) != 2:
|
|
251
|
+
raise _error("missing_second_witness", "Pair design requires exactly two selected candidates.", "request/candidate_ids")
|
|
252
|
+
if type(native_candidate_results) is not list:
|
|
253
|
+
raise _error("incomplete_export", "Fresh native candidate results are required.", "native_candidate_results")
|
|
254
|
+
app_candidates = result.get("candidates")
|
|
255
|
+
if type(app_candidates) is not list:
|
|
256
|
+
raise _error("incomplete_export", "Historical application candidate references are missing.", "historical_evidence/result/candidates")
|
|
257
|
+
selected = []
|
|
258
|
+
for index, (cid, vector) in enumerate(zip(ids, vectors)):
|
|
259
|
+
_identifier(cid, f"request/candidate_ids/{index}")
|
|
260
|
+
vector = _candidate_vector(vector, f"request/candidate_vectors/{index}")
|
|
261
|
+
refs = [item for item in app_candidates if type(item) is dict and item.get("id") == cid]
|
|
262
|
+
checked = [item for item in native_candidate_results if type(item) is dict and item.get("candidate_id") == cid]
|
|
263
|
+
if len(refs) != 1 or len(checked) != 1:
|
|
264
|
+
raise _error("candidate_mismatch", "Each selected candidate must occur once in application and native history.", f"request/candidate_ids/{index}")
|
|
265
|
+
ref, native = refs[0], checked[0]
|
|
266
|
+
if (ref.get("parameter_vector") != vector or ref.get("problem_id") != app_problem["id"]
|
|
267
|
+
or ref.get("problem_digest") != app_problem["digest"] or ref.get("observable") != "concentration"
|
|
268
|
+
or native.get("parameters") != vector):
|
|
269
|
+
raise _error("candidate_mismatch", "The selected fixed vector differs from its historical evidence.", f"request/candidate_vectors/{index}")
|
|
270
|
+
# Native baseline certificates are historical evidence, not reusable
|
|
271
|
+
# prospective analytic-pair certificates. Construction stays explicit.
|
|
272
|
+
selected.append({"id": cid, "problem_digest": current["projection_digest"],
|
|
273
|
+
"parameters": vector, "source_artifact_digest": None})
|
|
274
|
+
if ids[0] == ids[1] or vectors[0] == vectors[1]:
|
|
275
|
+
raise _error("candidate_mismatch", "The selected pair requires distinct IDs and exact vectors.", "request/candidate_ids")
|
|
276
|
+
times = request.get("feasible_times")
|
|
277
|
+
if type(times) is not list or not 1 <= len(times) <= 64:
|
|
278
|
+
raise _error("invalid_input", "Review between one and 64 prospective times.", "request/feasible_times")
|
|
279
|
+
times = [_exact(time, f"request/feasible_times/{i}", positive=True) for i, time in enumerate(times)]
|
|
280
|
+
if len(set(times)) != len(times):
|
|
281
|
+
raise _error("invalid_input", "Approved prospective times must be distinct.", "request/feasible_times")
|
|
282
|
+
allowance = _exact(request.get("future_hard_allowance"), "request/future_hard_allowance", positive=True)
|
|
283
|
+
construction, extension = request.get("allow_construction"), request.get("allow_continuation")
|
|
284
|
+
if type(construction) is not bool or type(extension) is not bool:
|
|
285
|
+
raise _error("invalid_input", "Construction and continuation choices must be explicit booleans.", "request/allow_construction")
|
|
286
|
+
if extension and not construction:
|
|
287
|
+
raise _error("unsupported_model", "Continuation requires separately authorized construction.", "request/allow_continuation")
|
|
288
|
+
budget = _object(request.get("budget"), "request/budget")
|
|
289
|
+
caps = {"wall_seconds": (1, 120), "fixed_vector_constructions": (0, 2),
|
|
290
|
+
"pair_verifications": (0, 2), "bundle_bytes": (1, 4 * 1024 * 1024)}
|
|
291
|
+
for key, (lo, hi) in caps.items():
|
|
292
|
+
value = budget.get(key)
|
|
293
|
+
if type(value) is not int or not lo <= value <= hi:
|
|
294
|
+
raise _error("invalid_input", "Design resource budget exceeds the scientific profile.", "request/budget/" + key)
|
|
295
|
+
scientific_problem = normalize_problem(current["problem"])
|
|
296
|
+
mapping_policy, tier, allowance_origin, horizon = _design_policy(request, scientific_problem, times, budget, expected)
|
|
297
|
+
design = normalize_design({
|
|
298
|
+
"schema_version": DESIGN_PROFILE, "problem_digest": current["projection_digest"],
|
|
299
|
+
"scenario_id": request["scenario_id"], "candidates": selected,
|
|
300
|
+
"grid": [{"time": time, "feasible": True, "reason": "Reviewed application feasible time"} for time in times],
|
|
301
|
+
"time_origin": scientific_problem.time_origin, "observable": "c", "future_allowance": allowance,
|
|
302
|
+
"allowance_origin": allowance_origin,
|
|
303
|
+
"requested_tier": tier,
|
|
304
|
+
"horizon_policy": {"allow_construction": construction, "allow_extension": extension, "maximum_horizon": horizon},
|
|
305
|
+
"numerical_policy": NUMERICAL_POLICY, "checked_policy": CHECKED_POLICY,
|
|
306
|
+
"limits": {"wall_seconds": budget["wall_seconds"], "max_times": len(times),
|
|
307
|
+
"max_constructions": budget["fixed_vector_constructions"], "max_pair_verifications": budget["pair_verifications"],
|
|
308
|
+
"max_bundle_bytes": budget["bundle_bytes"], "max_certificate_bytes": min(2 * 1024 * 1024, budget["bundle_bytes"])},
|
|
309
|
+
}, scientific_problem)
|
|
310
|
+
design_binding = {"schema_version": DESIGN_BINDING, "mapping_policy": mapping_policy,
|
|
311
|
+
"application": binding, "request": request, "request_digest": expected,
|
|
312
|
+
"historical_evidence": evidence, "design_digest": design.digest,
|
|
313
|
+
"approved_grid_order": times}
|
|
314
|
+
return {"binding": design_binding, "design": design.to_payload(), "design_digest": design.digest,
|
|
315
|
+
"approved_grid_order": times}
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def verify_design_binding(binding: dict, *, native_candidate_results: list[dict]) -> dict:
|
|
319
|
+
b = _object(binding, "binding")
|
|
320
|
+
if b.get("schema_version") != DESIGN_BINDING or b.get("mapping_policy") not in (MAPPING_POLICY, DESIGN_MAPPING_POLICY):
|
|
321
|
+
raise _error("unsupported_model", "Unsupported application design mapping policy.", "binding/mapping_policy")
|
|
322
|
+
projection = verify_application_binding(_get(b, "application", "binding"))
|
|
323
|
+
result = project_design(_get(b, "request", "binding"), expected_request_digest=_get(b, "request_digest", "binding"),
|
|
324
|
+
projection=projection, historical_evidence=_get(b, "historical_evidence", "binding"),
|
|
325
|
+
native_candidate_results=native_candidate_results)
|
|
326
|
+
if result["binding"] != b:
|
|
327
|
+
raise _error("wrong_specification_binding", "Stored design projection differs from fresh mapping.", "binding")
|
|
328
|
+
return result
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def restore_approved_grid(options: list[dict], approved_grid_order: list[str]) -> list[dict]:
|
|
332
|
+
"""Retain every option/reason while undoing the scientific grid sort."""
|
|
333
|
+
if type(options) is not list or type(approved_grid_order) is not list:
|
|
334
|
+
raise _error("invalid_input", "Expected approved grid and option arrays.", "options")
|
|
335
|
+
approved_grid_order = [_exact(time, "approved_grid_order", positive=True) for time in approved_grid_order]
|
|
336
|
+
indexed = {}
|
|
337
|
+
for option in options:
|
|
338
|
+
item = _object(option, "options")
|
|
339
|
+
time = item.get("time")
|
|
340
|
+
if type(time) is not str or time in indexed:
|
|
341
|
+
raise _error("wrong_specification_binding", "Scientific options contain duplicate or absent times.", "options")
|
|
342
|
+
indexed[time] = item
|
|
343
|
+
if len(set(approved_grid_order)) != len(approved_grid_order) or set(indexed) != set(approved_grid_order):
|
|
344
|
+
raise _error("wrong_specification_binding", "Scientific options must retain every approved time exactly once.", "options")
|
|
345
|
+
return [deepcopy(indexed[time]) for time in approved_grid_order]
|