@antprofuse/saddle-skill 0.2.0 → 0.3.0-alpha.2

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.
@@ -1,254 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Generate or validate Saddle's final parameterized generated-capacity facts."""
3
-
4
- from __future__ import annotations
5
-
6
- import hashlib
7
- import json
8
- import re
9
- import sys
10
- from pathlib import Path
11
-
12
- U64_MAX = (1 << 64) - 1
13
- APPROVED_PROFILE_COUNT = 6_505_728
14
- APPROVED_DOMAIN_FINGERPRINT = (
15
- "b83afcae5ee83ae410b207fe93b4609bf1c12549e2eb52a139cb5728c2f121f9"
16
- )
17
- DOMAIN = {
18
- "worker_threads_min": 1,
19
- "worker_threads_max": 8,
20
- "active_requests_min": 1,
21
- "active_requests_max": 128,
22
- "wait_slots_min": 0,
23
- "wait_slots_max": 128,
24
- "db_max": 64,
25
- }
26
- COST = {
27
- "route_count": 6,
28
- "managed_commitment_per_active": 232,
29
- "managed_objects_per_active": 2,
30
- "task_storage_per_active": 2072,
31
- "framework_per_active": 7200,
32
- "response_carrier_per_active": 64,
33
- "entry_reserve_per_active": 64,
34
- }
35
- IDENTITY_KEYS = (
36
- "source_commit",
37
- "contract_sha256",
38
- "calibration_sha256",
39
- "physical_measurement_sha256",
40
- "physical_binary_sha256",
41
- "physical_cargo_lock_sha256",
42
- "query_artifact_sha256",
43
- "c1_artifact_sha256",
44
- "managed_objects_peak_fingerprint",
45
- )
46
- BASE_KEYS = {
47
- "schema",
48
- "source_commit",
49
- "contract_sha256",
50
- "calibration_sha256",
51
- "physical_measurement_sha256",
52
- "physical_binary_sha256",
53
- "physical_cargo_lock_sha256",
54
- "query_artifact_sha256",
55
- "c1_artifact_sha256",
56
- "managed_objects_peak_fingerprint",
57
- "source_build_identity",
58
- "worker_threads_domain",
59
- "active_requests_domain",
60
- "wait_slots_domain",
61
- "db_domain",
62
- "transport_registration_relation",
63
- "io_events_relation",
64
- "task_slot_capacity_relation",
65
- "route_count",
66
- "managed_commitment_per_active",
67
- "managed_objects_per_active",
68
- "task_storage_per_active",
69
- "framework_per_active",
70
- "response_carrier_per_active",
71
- "entry_reserve_per_active",
72
- "profile_count",
73
- "domain_fingerprint",
74
- "arithmetic",
75
- }
76
-
77
-
78
- def fail(message: str) -> None:
79
- raise ValueError(message)
80
-
81
-
82
- def checked(value: int, label: str) -> int:
83
- if value < 0 or value > U64_MAX:
84
- fail(f"{label} exceeds approved 64-bit usize")
85
- return value
86
-
87
-
88
- def sha256_text(text: str) -> str:
89
- return hashlib.sha256(text.encode("utf-8")).hexdigest()
90
-
91
-
92
- def validate_sha(value: object, key: str) -> str:
93
- length = 40 if key == "source_commit" else 64
94
- label = "full Git commit" if key == "source_commit" else "SHA-256"
95
- if not isinstance(value, str) or not re.fullmatch(rf"[0-9a-f]{{{length}}}", value):
96
- fail(f"{key} is not {label}")
97
- return value
98
-
99
-
100
- def canonical_identity(identity: dict[str, object]) -> tuple[dict[str, str], str]:
101
- if set(identity) != set(IDENTITY_KEYS):
102
- fail("source/build identity has unknown, duplicate, or missing fields")
103
- values = {key: validate_sha(identity[key], key) for key in IDENTITY_KEYS}
104
- text = "".join(f"{key}={values[key]}\n" for key in IDENTITY_KEYS)
105
- return values, sha256_text(text)
106
-
107
-
108
- def profile_record(
109
- workers: int,
110
- active: int,
111
- waiters: int,
112
- db: int,
113
- *,
114
- task_storage_per_active: int = COST["task_storage_per_active"],
115
- ) -> str:
116
- if not 1 <= workers <= 8:
117
- fail("T is outside 1..8")
118
- if not 1 <= active <= 128:
119
- fail("N is outside 1..128")
120
- if not 0 <= waiters <= 128:
121
- fail("W is outside 0..128")
122
- if not 0 <= db <= min(active, 64):
123
- fail("DB is outside 0..min(N,64)")
124
- registration = checked(active + waiters, "R=N+W")
125
- events = checked(registration + 3, "E=R+3")
126
- task_slots = active
127
- managed = checked(active * COST["managed_commitment_per_active"], "managed")
128
- objects = checked(active * COST["managed_objects_per_active"], "objects")
129
- task = checked(active * task_storage_per_active, "task")
130
- framework = checked(active * COST["framework_per_active"], "framework")
131
- response = checked(active * COST["response_carrier_per_active"], "response")
132
- entry = checked(active * COST["entry_reserve_per_active"], "entry")
133
- return (
134
- f"T={workers};N={active};W={waiters};DB={db};"
135
- f"R={registration};E={events};task_slots={task_slots};"
136
- f"managed={managed};objects={objects};task={task};"
137
- f"framework={framework};response={response};entry={entry}\n"
138
- )
139
-
140
-
141
- def enumerate_domain() -> tuple[int, str]:
142
- digest = hashlib.sha256()
143
- count = 0
144
- for workers in range(1, 9):
145
- for active in range(1, 129):
146
- for waiters in range(0, 129):
147
- for db in range(0, min(active, 64) + 1):
148
- record = profile_record(workers, active, waiters, db)
149
- digest.update(record.encode("ascii"))
150
- count += 1
151
- return count, digest.hexdigest()
152
-
153
-
154
- def expected(identity: dict[str, object], *, derive_domain: bool) -> dict[str, str]:
155
- identity_values, source_build_identity = canonical_identity(identity)
156
- if derive_domain:
157
- count, domain_fingerprint = enumerate_domain()
158
- if (
159
- count != APPROVED_PROFILE_COUNT
160
- or domain_fingerprint != APPROVED_DOMAIN_FINGERPRINT
161
- ):
162
- fail("enumerated support domain drifted from schema 1")
163
- else:
164
- count = APPROVED_PROFILE_COUNT
165
- domain_fingerprint = APPROVED_DOMAIN_FINGERPRINT
166
- return {
167
- "schema": "saddle-generated-parameterized-capacity/1",
168
- **identity_values,
169
- "source_build_identity": source_build_identity,
170
- "worker_threads_domain": "1..8",
171
- "active_requests_domain": "1..128",
172
- "wait_slots_domain": "0..128",
173
- "db_domain": "0..min(N,64)",
174
- "transport_registration_relation": "R=N+W",
175
- "io_events_relation": "E=R+3",
176
- "task_slot_capacity_relation": "task_slot_capacity=N",
177
- **{key: str(value) for key, value in COST.items()},
178
- "profile_count": str(count),
179
- "domain_fingerprint": domain_fingerprint,
180
- "arithmetic": "checked-u64",
181
- }
182
-
183
-
184
- def read_facts(path: Path) -> dict[str, str]:
185
- values: dict[str, str] = {}
186
- for line_number, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
187
- if not line or "=" not in line:
188
- fail(f"line {line_number} is not canonical key=value")
189
- key, value = line.split("=", 1)
190
- if key in values:
191
- fail(f"duplicate field: {key}")
192
- if key not in BASE_KEYS:
193
- fail(f"unknown field: {key}")
194
- values[key] = value
195
- if set(values) != BASE_KEYS:
196
- fail("machine facts have missing fields")
197
- return values
198
-
199
-
200
- def generate(identity_path: Path, output_path: Path) -> None:
201
- identity = json.loads(identity_path.read_text(encoding="utf-8"))
202
- values = expected(identity, derive_domain=True)
203
- output_path.parent.mkdir(parents=True, exist_ok=True)
204
- output_path.write_text(
205
- "".join(f"{key}={values[key]}\n" for key in values),
206
- encoding="utf-8",
207
- )
208
-
209
-
210
- def validate(facts_path: Path) -> None:
211
- values = read_facts(facts_path)
212
- identity = {key: values[key] for key in IDENTITY_KEYS}
213
- wanted = expected(identity, derive_domain=False)
214
- if values != wanted:
215
- drift = sorted(key for key in BASE_KEYS if values.get(key) != wanted.get(key))
216
- fail(f"generated capacity facts drifted: {','.join(drift)}")
217
-
218
-
219
- def main() -> int:
220
- try:
221
- if len(sys.argv) == 4 and sys.argv[1] == "generate":
222
- generate(Path(sys.argv[2]), Path(sys.argv[3]))
223
- return 0
224
- if len(sys.argv) == 3 and sys.argv[1] == "validate":
225
- validate(Path(sys.argv[2]))
226
- print("saddle-generated-parameterized-capacity/1: valid")
227
- return 0
228
- if len(sys.argv) == 7 and sys.argv[1] == "probe":
229
- workers, active, waiters, db, task_cost = map(int, sys.argv[2:])
230
- print(
231
- profile_record(
232
- workers,
233
- active,
234
- waiters,
235
- db,
236
- task_storage_per_active=task_cost,
237
- ),
238
- end="",
239
- )
240
- return 0
241
- print(
242
- "usage: parameterized-capacity-facts.py "
243
- "generate <identity.json> <facts> | validate <facts> | "
244
- "probe <T> <N> <W> <DB> <task-cost>",
245
- file=sys.stderr,
246
- )
247
- return 64
248
- except (OSError, ValueError, json.JSONDecodeError) as error:
249
- print(f"parameterized capacity facts invalid: {error}", file=sys.stderr)
250
- return 1
251
-
252
-
253
- if __name__ == "__main__":
254
- raise SystemExit(main())
@@ -1,124 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Synchronize the packaged Skill closure from one approved Rust candidate."""
3
-
4
- from __future__ import annotations
5
-
6
- import argparse
7
- import hashlib
8
- import json
9
- import re
10
- from pathlib import Path
11
-
12
-
13
- def digest(path: Path) -> str:
14
- return hashlib.sha256(path.read_bytes()).hexdigest()
15
-
16
-
17
- def main() -> None:
18
- parser = argparse.ArgumentParser()
19
- parser.add_argument("--root", type=Path, required=True)
20
- parser.add_argument("--rust-candidate-manifest", type=Path, required=True)
21
- parser.add_argument("--skill-release", default="0.2.0")
22
- args = parser.parse_args()
23
-
24
- root = args.root.resolve()
25
- candidate_path = args.rust_candidate_manifest.resolve()
26
- candidate = json.loads(candidate_path.read_text(encoding="utf-8"))
27
- if candidate.get("schema") != "saddle-rs-01-r12-rust-recovery-candidate/1":
28
- raise SystemExit("unsupported Rust candidate manifest")
29
- if candidate.get("release") != "0.2.0" or candidate.get("status") != "candidate-ready-for-transport-review":
30
- raise SystemExit("unexpected or incomplete Rust candidate")
31
- if candidate.get("publish_performed") is not False or candidate.get("tag_performed") is not False:
32
- raise SystemExit("Rust candidate crossed the release boundary")
33
- source = candidate.get("artifact_source_commit", "")
34
- if not re.fullmatch(r"[0-9a-f]{40}", source):
35
- raise SystemExit("Rust artifact source is not a full commit")
36
- expected_packages = {
37
- "saddle-core", "saddle-macros", "saddle-admission", "saddle-observability",
38
- "saddle-runtime", "saddle-db", "saddle-service", "saddle-framework",
39
- }
40
- packages = {item["name"]: item for item in candidate.get("crates", [])}
41
- if set(packages) != expected_packages:
42
- raise SystemExit("Rust candidate does not contain exactly eight Saddle crates")
43
- if any(not re.fullmatch(r"[0-9a-f]{64}", item.get("sha256", "")) for item in packages.values()):
44
- raise SystemExit("Rust candidate crate digest is invalid")
45
-
46
- skill = root / "skills/saddle-service-0-2"
47
- manifest_path = skill / "package-manifest.json"
48
- manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
49
- snapshot = skill / "references/public-api.snapshot"
50
- machine_doc = skill / "references/machine-schema.md"
51
- template_root = skill / "assets/registry-consumer"
52
- template_inputs = {
53
- "cargo_lock": template_root / "Cargo.lock",
54
- "cargo_manifest": template_root / "Cargo.toml",
55
- "library": template_root / "src/lib.rs",
56
- "generated_owner": template_root / "src/generated_artifact.rs",
57
- "external_consumer_test": template_root / "tests/provider_consumer.rs",
58
- "output_validator": skill / "scripts/validate-generated-project.sh",
59
- "preflight_validator": skill / "scripts/validate-generated-preflight.sh",
60
- "cache_key_builder": skill / "scripts/validation-cache-key.py",
61
- }
62
- observed_template = {name: digest(path) for name, path in template_inputs.items()}
63
- template_identity = hashlib.sha256(
64
- json.dumps(observed_template, separators=(",", ":")).encode()
65
- ).hexdigest()
66
- gate_identity = manifest.get("gate_identity", {})
67
- if not re.fullmatch(r"[0-9a-f]{40}", gate_identity.get("d1_source_candidate", "")):
68
- raise SystemExit("approved Gate identity is missing")
69
-
70
- closure = {
71
- "schema": "saddle-skill-identity-closure/2",
72
- "skill_release": args.skill_release,
73
- "rust_release": candidate["release"],
74
- "artifact_source_commit": source,
75
- "registry_artifact_source_commit": source,
76
- "rust_candidate_manifest_sha256": digest(candidate_path),
77
- "registry_packages_sha256": {name: packages[name]["sha256"] for name in sorted(packages)},
78
- "framework_crate_sha256": packages["saddle-framework"]["sha256"],
79
- "fresh_registry_cargo_lock_sha256": candidate["consumer_lock_sha256"],
80
- "registry_consumer_cargo_lock_sha256": observed_template["cargo_lock"],
81
- "declaration_schema": "saddle-application/1",
82
- "machine_schema": "saddle-approved-build/2",
83
- "generated_static_schema": "saddle-generated-static-facts/2",
84
- "gate_identity": gate_identity,
85
- "public_api_snapshot_sha256": digest(snapshot),
86
- "machine_schema_document_sha256": digest(machine_doc),
87
- "approved_locks": {"registry_consumer": observed_template["cargo_lock"]},
88
- "unified_application_sha256": observed_template["library"],
89
- "unified_owner_sha256": observed_template["generated_owner"],
90
- "template_identity_sha256": template_identity,
91
- "registry_consumer_template": observed_template,
92
- }
93
- closure_path = skill / "references/identity-closure.json"
94
- closure_path.write_text(json.dumps(closure, indent=2) + "\n", encoding="utf-8")
95
-
96
- manifest["npm"]["version"] = args.skill_release
97
- manifest["rust"]["requirement"] = f'={candidate["release"]}'
98
- manifest["rust"]["source_commit"] = source
99
- manifest["rust"]["public_api_snapshot_sha256"] = closure["public_api_snapshot_sha256"]
100
- manifest["consumer_evidence"]["approved_locks"] = closure["approved_locks"]
101
- manifest["consumer_evidence"]["unified_application_sha256"] = closure["unified_application_sha256"]
102
- manifest["consumer_evidence"]["unified_owner_sha256"] = closure["unified_owner_sha256"]
103
- manifest["consumer_evidence"]["registry_consumer_template"] = observed_template
104
- manifest["generated_static_facts"]["application_machine_fingerprint"] = "NOT_GENERATED_SK_02"
105
- manifest["generated_static_facts"]["template_identity_sha256"] = template_identity
106
- manifest["identity_closure"] = {
107
- "path": "references/identity-closure.json",
108
- "sha256": digest(closure_path),
109
- "registry_artifact_source_commit": source,
110
- "rust_candidate_manifest_sha256": closure["rust_candidate_manifest_sha256"],
111
- "registry_packages_sha256": closure["registry_packages_sha256"],
112
- "framework_crate_sha256": closure["framework_crate_sha256"],
113
- "fresh_registry_cargo_lock_sha256": closure["fresh_registry_cargo_lock_sha256"],
114
- "registry_consumer_cargo_lock_sha256": closure["registry_consumer_cargo_lock_sha256"],
115
- }
116
- manifest_path.write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
117
- package_path = skill / "package.json"
118
- package = json.loads(package_path.read_text(encoding="utf-8"))
119
- package["version"] = args.skill_release
120
- package_path.write_text(json.dumps(package, indent=2) + "\n", encoding="utf-8")
121
-
122
-
123
- if __name__ == "__main__":
124
- main()
@@ -1,62 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- if [[ $# -ne 1 ]]; then
5
- echo "usage: validate-contract.sh <application.rs>" >&2
6
- exit 64
7
- fi
8
-
9
- source_file=$1
10
- if [[ ! -f "$source_file" ]]; then
11
- echo "contract source not found: $source_file" >&2
12
- exit 66
13
- fi
14
-
15
- source_text="$(<"$source_file")"
16
-
17
- required=(
18
- 'saddle::application!'
19
- 'schema "saddle-application/1";'
20
- 'application '
21
- 'service '
22
- )
23
- for token in "${required[@]}"; do
24
- if ! grep -Fq "$token" <<<"$source_text"; then
25
- echo "missing required declaration token: $token" >&2
26
- exit 1
27
- fi
28
- done
29
-
30
- if [[ "$(grep -Fc 'saddle::application!' <<<"$source_text")" -ne 1 ]]; then
31
- echo "exactly one saddle::application! declaration is required" >&2
32
- exit 1
33
- fi
34
-
35
- if grep -Eq \
36
- 'ServiceHandler|ServiceFuture|ServiceRegistry|Statement|DbValue|TransactionFuture|serde|sqlx|String|Vec<|Box<|dyn Future|tokio::|std::thread|spawn\(|channel\(|capacity[[:space:]]|deadline[[:space:]]|timeout[[:space:]]' \
37
- <<<"$source_text"
38
- then
39
- echo "declaration contains a V1, unmanaged, execution, or numeric-profile bypass" >&2
40
- exit 1
41
- fi
42
-
43
- if grep -Eq 'transaction[[:space:]].*\{([^}]|$)*steps[[:space:]]+([02-9]|[1-9][0-9]+);' \
44
- <<<"$(tr '\n' ' ' <"$source_file")"
45
- then
46
- echo "schema 1 transaction must contain exactly one step" >&2
47
- exit 1
48
- fi
49
-
50
- if grep -Eq 'decision[[:space:]]+([^;]+);' <<<"$source_text"; then
51
- while IFS= read -r decision; do
52
- case "$decision" in
53
- "decision commit;"|"decision business_rollback;") ;;
54
- *)
55
- echo "unsupported transaction decision: $decision" >&2
56
- exit 1
57
- ;;
58
- esac
59
- done < <(grep -Eo 'decision[[:space:]]+[^;]+;' <<<"$source_text")
60
- fi
61
-
62
- echo "saddle-application/1 declaration: candidate-valid"
@@ -1,120 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- if [[ $# -ne 1 ]]; then
5
- echo "usage: validate-generated-preflight.sh <project-root>" >&2
6
- exit 64
7
- fi
8
-
9
- project=$(cd "$1" && pwd)
10
- python3 - "$project" <<'PY'
11
- from pathlib import Path
12
- import re, sys
13
-
14
- root = Path(sys.argv[1])
15
- sources = sorted((root / "src").glob("**/*.rs"))
16
- if not sources:
17
- raise SystemExit("generated source is missing")
18
- source = "\n".join(path.read_text() for path in sources)
19
- without_blocks = re.sub(r"/\*.*?\*/", "", source, flags=re.S)
20
- active = "\n".join(line.split("//", 1)[0] for line in without_blocks.splitlines())
21
- required = [
22
- r"let\s+bundle\s*=\s*builder\s*\.\s*freeze_with_capacity_leaf\s*\(",
23
- r"generated_bootstrap\s*\(\s*seal\.preflight_token\(\)\s*,\s*bundle\s*,",
24
- r"seal\s*\.\s*bind\s*\(\s*bootstrap\s*\)",
25
- ]
26
- for pattern in required:
27
- if not re.search(pattern, active, flags=re.S):
28
- raise SystemExit(f"missing active generated runtime preflight shape: {pattern}")
29
-
30
- marker = re.search(r"seal\s*\.\s*bind\s*\(", active)
31
- if marker is None:
32
- raise SystemExit("missing active Facade opaque bind call")
33
- start = marker.end()
34
- round_depth, curly_depth, square_depth = 1, 0, 0
35
- commas = []
36
- end = None
37
- for index in range(start, len(active)):
38
- char = active[index]
39
- if char == "(":
40
- round_depth += 1
41
- elif char == ")":
42
- round_depth -= 1
43
- if round_depth == 0:
44
- end = index
45
- break
46
- elif char == "{":
47
- curly_depth += 1
48
- elif char == "}":
49
- curly_depth -= 1
50
- elif char == "[":
51
- square_depth += 1
52
- elif char == "]":
53
- square_depth -= 1
54
- elif char == "," and round_depth == 1 and curly_depth == 0 and square_depth == 0:
55
- commas.append(index)
56
- if end is None:
57
- raise SystemExit("unterminated Facade opaque bind call")
58
- arguments = active[start:end]
59
- parts = []
60
- previous = 0
61
- for comma in commas:
62
- parts.append(arguments[previous:comma - start].strip())
63
- previous = comma - start + 1
64
- parts.append(arguments[previous:].strip())
65
- parts = [part for part in parts if part]
66
- if parts != ["bootstrap"]:
67
- raise SystemExit("Facade bind must receive only the Service whole-bundle bootstrap")
68
- for forbidden in [
69
- r"type\s+ServiceCapacity\s*=", r"type\s+Termination\s*=", r"type\s+Continuation\s*=",
70
- r"\.into_parts\s*\(\s*\)", r"GeneratedBootstrapBinder", r"GeneratedTerminationTopologyWorkOwner",
71
- r"PreflightGeneratedStaticContinuationOwner", r"runtime_layout_preflight\s*\(",
72
- r"impl\s+(?:GeneratedBootstrapBinder|PreflightGeneratedStaticContinuationOwner|GeneratedTerminationTopologyWorkOwner)\s+for\s+",
73
- ]:
74
- if re.search(forbidden, active):
75
- raise SystemExit(f"generated production proof injection remains: {forbidden}")
76
-
77
- def function_body(name: str) -> str:
78
- marker = re.search(rf"fn\s+{name}\s*\([^)]*\)\s*->\s*ExecutionError\s*\{{", active)
79
- if marker is None:
80
- raise SystemExit(f"missing generated error mapper: {name}")
81
- start = marker.end() - 1
82
- depth = 0
83
- for index in range(start, len(active)):
84
- if active[index] == "{":
85
- depth += 1
86
- elif active[index] == "}":
87
- depth -= 1
88
- if depth == 0:
89
- return active[start + 1:index]
90
- raise SystemExit(f"unterminated generated error mapper: {name}")
91
-
92
- expected = {
93
- "map_query_error": {
94
- "ConnectionUnavailable", "QueryFailed", "InvalidRow", "FinalizerFailed",
95
- "Cancelled", "Shutdown", "DependencyExecutionFailed", "DependencyUnavailable",
96
- },
97
- "map_write_error": {
98
- "ConnectionUnavailable", "WriteFailed", "FinalizerFailed", "Cancelled", "Shutdown",
99
- "DependencyExecutionFailed", "DependencyUnavailable",
100
- },
101
- "map_transaction_error": {
102
- "BusinessRollback", "ConnectionUnavailable", "BeginFailed", "WriteFailed",
103
- "CommitFailed", "RollbackFailed", "FinalizerFailed", "Cancelled", "Shutdown",
104
- "Business", "DependencyExecutionFailed", "DependencyUnavailable",
105
- },
106
- }
107
- for name, tokens in expected.items():
108
- body = function_body(name)
109
- if re.search(r"(?:^|[,{|])\s*_\s*=>", body):
110
- raise SystemExit(f"generated error mapper contains a catch-all: {name}")
111
- for token in tokens:
112
- if len(re.findall(rf"\b{re.escape(token)}\b", body)) != 1:
113
- raise SystemExit(f"generated error mapper token drift: {name}/{token}")
114
- if name != "map_transaction_error" and re.search(r"\bExecutionError::Business\b", body):
115
- raise SystemExit(f"dependency failure was downgraded to Business: {name}")
116
- if len(re.findall(r"\bExecutionError::Business\b", function_body("map_transaction_error"))) != 1:
117
- raise SystemExit("only BusinessRollback may map to ExecutionError::Business")
118
- PY
119
-
120
- echo 'generated whole-bundle opaque proof authority: PASS'
@@ -1,123 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- if [[ $# -ne 1 ]]; then
5
- echo "usage: validate-generated-project.sh <project-root>" >&2
6
- exit 64
7
- fi
8
-
9
- project=$(cd "$1" && pwd)
10
- test -f "$project/Cargo.toml"
11
- test -f "$project/Cargo.lock"
12
- script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)
13
- cache_key_builder="$script_dir/validation-cache-key.py"
14
- test -x "$cache_key_builder"
15
-
16
- if [[ ${CARGO_NET_OFFLINE:-} != true ]]; then
17
- echo "Skill validation requires CARGO_NET_OFFLINE=true" >&2
18
- exit 1
19
- fi
20
- if [[ ${SADDLE_SKILL_FEATURE_SET:-default} != default ]]; then
21
- echo "Skill validation supports only the declared default feature set" >&2
22
- exit 1
23
- fi
24
- if [[ -z ${SADDLE_ENTRY_LOCAL_ROOT:-} || -z ${CARGO_HOME:-} || -z ${CARGO_TARGET_DIR:-} ]]; then
25
- echo "Skill validation requires the approved entry-local cache runner" >&2
26
- exit 1
27
- fi
28
- entry_root=$(cd "$SADDLE_ENTRY_LOCAL_ROOT" && pwd -P)
29
- trusted_tmp=$(cd /tmp && pwd -P)
30
- if [[ $(dirname "$entry_root") != "$trusted_tmp" || -L $SADDLE_ENTRY_LOCAL_ROOT ]]; then
31
- echo "Skill validation entry root must be a canonical direct child of /tmp" >&2
32
- exit 1
33
- fi
34
- if [[ $(cd "$CARGO_HOME" && pwd -P) != "$entry_root/cargo-home" || \
35
- $(cd "$CARGO_TARGET_DIR" && pwd -P) != "$entry_root/target" || \
36
- $(pwd -P) != "$entry_root/work" ]]; then
37
- echo "Skill validation requires entry-local cargo-home, target, and workdir" >&2
38
- exit 1
39
- fi
40
- "$script_dir/validate-generated-preflight.sh" "$project"
41
- if find "$project" -type d -name target -print -quit | grep -q .; then
42
- echo "tracked or unignored build target is forbidden" >&2
43
- exit 1
44
- fi
45
-
46
- python3 - "$project" <<'PY'
47
- from pathlib import Path
48
- import re, sys, tomllib
49
-
50
- root = Path(sys.argv[1])
51
- cargo_text = (root / "Cargo.toml").read_text()
52
- cargo = tomllib.loads(cargo_text)
53
- package = cargo.get("package", {})
54
- if package.get("rust-version") != "1.85":
55
- raise SystemExit("generated project must declare rust-version 1.85")
56
- if re.search(r"(?:path|git|workspace)\s*=|\[patch", cargo_text):
57
- raise SystemExit("path/git/workspace/patch dependency is forbidden")
58
-
59
- deps = cargo.get("dependencies", {})
60
- framework = deps.get("saddle")
61
- if not isinstance(framework, dict) or framework.get("package") != "saddle-framework" or framework.get("version") != "=0.2.0":
62
- raise SystemExit("exact registry saddle-framework =0.2.0 is required")
63
- for name, value in deps.items():
64
- if name.startswith("saddle-"):
65
- version = value if isinstance(value, str) else value.get("version")
66
- if version != "=0.2.0":
67
- raise SystemExit(f"{name} must use exact registry 0.2.0")
68
-
69
- sources = sorted((root / "src").glob("**/*.rs"))
70
- tests = sorted((root / "tests").glob("**/*.rs"))
71
- if not sources or not tests:
72
- raise SystemExit("generated source and at least one executable integration test are required")
73
- source = "\n".join(p.read_text() for p in sources)
74
- without_blocks = re.sub(r"/\*.*?\*/", "", source, flags=re.S)
75
- active = "\n".join(line.split("//", 1)[0] for line in without_blocks.splitlines())
76
- required = [
77
- r"pub\s+fn\s+run\s*<\s*B\s*>",
78
- r"B\s*:\s*ApprovedExternalBundle",
79
- r"ProductionLauncher::verify\s*\(\s*bundle\s*\)\?\s*\.run\s*\(\s*config\s*,\s*GeneratedOwner\s*\)",
80
- r"mod\s+__saddle_generated\s*;",
81
- ]
82
- for pattern in required:
83
- if not re.search(pattern, active, re.S):
84
- raise SystemExit(f"missing active generated consumer shape: {pattern}")
85
- if re.search(r"pub\s+struct\s+GeneratedOwner", active):
86
- raise SystemExit("GeneratedOwner must remain private")
87
- if "TODO" in source or re.search(r"fn\s+main[^{}]*\{\s*(?:return\s+)?Ok\s*\(\s*\(\s*\)\s*\)\s*;?\s*\}", active, re.S):
88
- raise SystemExit("placeholder or no-op main is forbidden")
89
- test_text = "\n".join(p.read_text() for p in tests)
90
- if "#[test]" not in test_text:
91
- raise SystemExit("zero executable tests are forbidden")
92
- PY
93
-
94
- case "$(cd "$CARGO_TARGET_DIR" && pwd -P)" in
95
- "$project"|"$project"/*)
96
- echo "Cargo target must be outside the generated project" >&2
97
- exit 1
98
- ;;
99
- esac
100
- cargo +1.85.0 test --manifest-path "$project/Cargo.toml" --locked --offline
101
- if find "$project" -type d -name target -print -quit | grep -q .; then
102
- echo "validation left a build target in the generated project" >&2
103
- exit 1
104
- fi
105
- rustc_verbose=$(rustc +1.85.0 -vV)
106
- rustc_version=$(sed -n '1s/^rustc //p' <<<"$rustc_verbose")
107
- toolchain_identity=$(sed -n 's/^commit-hash: //p' <<<"$rustc_verbose")
108
- target_triple=$(sed -n 's/^host: //p' <<<"$rustc_verbose")
109
- if [[ -z $rustc_version || -z $toolchain_identity || -z $target_triple ]]; then
110
- echo "Rust toolchain identity is incomplete" >&2
111
- exit 1
112
- fi
113
- cache_identity=$(python3 "$cache_key_builder" cache-key \
114
- --project "$project" \
115
- --rustc-version "$rustc_version" \
116
- --toolchain-identity "$toolchain_identity" \
117
- --target-triple "$target_triple" \
118
- --feature-set default \
119
- --build-contract "validate-generated-project=$script_dir/validate-generated-project.sh" \
120
- --build-contract "validate-generated-preflight=$script_dir/validate-generated-preflight.sh" \
121
- --build-contract "validation-cache-key=$cache_key_builder")
122
- printf 'saddle-skill-validation-cache=%s\n' "$cache_identity"
123
- echo "generated provider-generic consumer: PASS"