@antprofuse/saddle-skill 0.2.0-rc.19 → 0.2.0
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.
- package/SKILL.md +5 -1
- package/assets/registry-consumer/Cargo.lock +14 -14
- package/assets/registry-consumer/Cargo.toml +7 -7
- package/package-files.txt +1 -0
- package/package-manifest.json +25 -24
- package/package.json +1 -1
- package/references/api-boundary.md +2 -2
- package/references/identity-closure.json +24 -23
- package/references/public-api.snapshot +1 -1
- package/scripts/sync-identity-closure.py +3 -2
- package/scripts/validate-generated-project.sh +53 -16
- package/scripts/validate-identity-closure.py +3 -2
- package/scripts/validate-machine-input.sh +1 -1
- package/scripts/validation-cache-key.py +88 -0
package/SKILL.md
CHANGED
|
@@ -27,7 +27,11 @@ path、设计目标或相邻版本替代。
|
|
|
27
27
|
6. 运行 `scripts/validate-contract.sh <application.rs>` 与
|
|
28
28
|
`scripts/validate-generated-project.sh <project-root>`;核对 public API snapshot、
|
|
29
29
|
approved locks、package allowlist、同源 managed-object peak 与 machine
|
|
30
|
-
fingerprint,再运行正式 Rust package 提供的 Gate,不自行实现替代 Gate
|
|
30
|
+
fingerprint,再运行正式 Rust package 提供的 Gate,不自行实现替代 Gate。生成工程
|
|
31
|
+
验证必须设置 `CARGO_NET_OFFLINE=true`,并通过已批准的 entry-local runner 创建
|
|
32
|
+
canonical `/tmp` 直属临时根;入口只接受其中独立的 `cargo-home`、`target` 与 `work`,
|
|
33
|
+
覆盖继承的 `CARGO_HOME`,在成功、STOP 和其他失败退出后删除整个临时根,并输出由
|
|
34
|
+
toolchain、target、features、lock、source 与 build contract 共同派生的 cache key。
|
|
31
35
|
|
|
32
36
|
## 生成约束
|
|
33
37
|
|
|
@@ -921,9 +921,9 @@ dependencies = [
|
|
|
921
921
|
|
|
922
922
|
[[package]]
|
|
923
923
|
name = "saddle-admission"
|
|
924
|
-
version = "0.2.0
|
|
924
|
+
version = "0.2.0"
|
|
925
925
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
926
|
-
checksum = "
|
|
926
|
+
checksum = "86c6a3787d1612faa49558f5a104ba78415ff604344112c150b6b69446937065"
|
|
927
927
|
dependencies = [
|
|
928
928
|
"saddle-core",
|
|
929
929
|
"serde",
|
|
@@ -932,9 +932,9 @@ dependencies = [
|
|
|
932
932
|
|
|
933
933
|
[[package]]
|
|
934
934
|
name = "saddle-core"
|
|
935
|
-
version = "0.2.0
|
|
935
|
+
version = "0.2.0"
|
|
936
936
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
937
|
-
checksum = "
|
|
937
|
+
checksum = "bf4e1cd2343cc239a0bb8288fe0947e73775d9cb3438b85ee1c15026a6369aa0"
|
|
938
938
|
dependencies = [
|
|
939
939
|
"ring",
|
|
940
940
|
"rustix",
|
|
@@ -945,9 +945,9 @@ dependencies = [
|
|
|
945
945
|
|
|
946
946
|
[[package]]
|
|
947
947
|
name = "saddle-db"
|
|
948
|
-
version = "0.2.0
|
|
948
|
+
version = "0.2.0"
|
|
949
949
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
950
|
-
checksum = "
|
|
950
|
+
checksum = "e3cac62b288d0e7cf775138793e2d8afb8923b4bbb4d72afb2deb8c18d9b7030"
|
|
951
951
|
dependencies = [
|
|
952
952
|
"futures-util",
|
|
953
953
|
"saddle-admission",
|
|
@@ -963,9 +963,9 @@ dependencies = [
|
|
|
963
963
|
|
|
964
964
|
[[package]]
|
|
965
965
|
name = "saddle-framework"
|
|
966
|
-
version = "0.2.0
|
|
966
|
+
version = "0.2.0"
|
|
967
967
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
968
|
-
checksum = "
|
|
968
|
+
checksum = "6f819954a32f042aa43a55c1fddb8e1a8c6de389f5f3b6cd006bba532a1aca0b"
|
|
969
969
|
dependencies = [
|
|
970
970
|
"ring",
|
|
971
971
|
"saddle-admission",
|
|
@@ -981,9 +981,9 @@ dependencies = [
|
|
|
981
981
|
|
|
982
982
|
[[package]]
|
|
983
983
|
name = "saddle-observability"
|
|
984
|
-
version = "0.2.0
|
|
984
|
+
version = "0.2.0"
|
|
985
985
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
986
|
-
checksum = "
|
|
986
|
+
checksum = "5e6f5d2228e8a02dd6bf65cbbd2e982129696976a104c4caf773c12016e1ecd3"
|
|
987
987
|
dependencies = [
|
|
988
988
|
"getrandom 0.3.4",
|
|
989
989
|
"rustix",
|
|
@@ -996,9 +996,9 @@ dependencies = [
|
|
|
996
996
|
|
|
997
997
|
[[package]]
|
|
998
998
|
name = "saddle-runtime"
|
|
999
|
-
version = "0.2.0
|
|
999
|
+
version = "0.2.0"
|
|
1000
1000
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1001
|
-
checksum = "
|
|
1001
|
+
checksum = "0c8925b3871f95f58cde8cf7de6938116d4fbb35000ea31699c7603d658deee2"
|
|
1002
1002
|
dependencies = [
|
|
1003
1003
|
"saddle-admission",
|
|
1004
1004
|
"saddle-core",
|
|
@@ -1011,9 +1011,9 @@ dependencies = [
|
|
|
1011
1011
|
|
|
1012
1012
|
[[package]]
|
|
1013
1013
|
name = "saddle-service"
|
|
1014
|
-
version = "0.2.0
|
|
1014
|
+
version = "0.2.0"
|
|
1015
1015
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1016
|
-
checksum = "
|
|
1016
|
+
checksum = "6d148466da57be9be7b2e4df9dcd68f0a253a418db247438ad0be1e886c8ff1b"
|
|
1017
1017
|
dependencies = [
|
|
1018
1018
|
"pin-project-lite",
|
|
1019
1019
|
"saddle-admission",
|
|
@@ -6,13 +6,13 @@ rust-version = "1.85"
|
|
|
6
6
|
publish = false
|
|
7
7
|
|
|
8
8
|
[dependencies]
|
|
9
|
-
saddle = { package = "saddle-framework", version = "=0.2.0
|
|
10
|
-
saddle-admission = "=0.2.0
|
|
11
|
-
saddle-core = "=0.2.0
|
|
12
|
-
saddle-db = "=0.2.0
|
|
13
|
-
saddle-observability = "=0.2.0
|
|
14
|
-
saddle-runtime = "=0.2.0
|
|
15
|
-
saddle-service = "=0.2.0
|
|
9
|
+
saddle = { package = "saddle-framework", version = "=0.2.0" }
|
|
10
|
+
saddle-admission = "=0.2.0"
|
|
11
|
+
saddle-core = "=0.2.0"
|
|
12
|
+
saddle-db = "=0.2.0"
|
|
13
|
+
saddle-observability = "=0.2.0"
|
|
14
|
+
saddle-runtime = "=0.2.0"
|
|
15
|
+
saddle-service = "=0.2.0"
|
|
16
16
|
|
|
17
17
|
[lints.rust]
|
|
18
18
|
unsafe_code = "forbid"
|
package/package-files.txt
CHANGED
package/package-manifest.json
CHANGED
|
@@ -5,18 +5,18 @@
|
|
|
5
5
|
"publish": false,
|
|
6
6
|
"npm": {
|
|
7
7
|
"name": "@antprofuse/saddle-skill",
|
|
8
|
-
"version": "0.2.0
|
|
8
|
+
"version": "0.2.0"
|
|
9
9
|
},
|
|
10
10
|
"rust": {
|
|
11
11
|
"facade": "saddle-framework",
|
|
12
|
-
"requirement": "=0.2.0
|
|
13
|
-
"source_commit": "
|
|
12
|
+
"requirement": "=0.2.0",
|
|
13
|
+
"source_commit": "96cd4ec8da55b0770c5d3e8275c74e65241a4759",
|
|
14
14
|
"msrv": "1.85.0",
|
|
15
15
|
"abi_frozen": false,
|
|
16
16
|
"compatibility": "source-and-public-api",
|
|
17
17
|
"skill_mapping": "exact-manifest-identity-not-version-number-equality",
|
|
18
18
|
"public_api_snapshot": "references/public-api.snapshot",
|
|
19
|
-
"public_api_snapshot_sha256": "
|
|
19
|
+
"public_api_snapshot_sha256": "da87e0b63c3fdf511daac30581cbf415f49541df2034d1e7bc713a9833179a51"
|
|
20
20
|
},
|
|
21
21
|
"skill": {
|
|
22
22
|
"name": "saddle-service-0-2",
|
|
@@ -44,16 +44,17 @@
|
|
|
44
44
|
"unified_application_sha256": "a85bf6a5665f3516fafddbe2b3c9460dadb7e341ce0336a79c4ecca4a4fd55d9",
|
|
45
45
|
"unified_owner_sha256": "af15a8dab10c1ac35d1c7bcbf2174d80c056e8200bd8b7f6fe2ceb60c1f9e0ea",
|
|
46
46
|
"approved_locks": {
|
|
47
|
-
"registry_consumer": "
|
|
47
|
+
"registry_consumer": "8896ba07b7a868b6914fa4cf5e85358e0c201bd717083c1822d0456d547a87ed"
|
|
48
48
|
},
|
|
49
49
|
"registry_consumer_template": {
|
|
50
|
-
"cargo_lock": "
|
|
51
|
-
"cargo_manifest": "
|
|
50
|
+
"cargo_lock": "8896ba07b7a868b6914fa4cf5e85358e0c201bd717083c1822d0456d547a87ed",
|
|
51
|
+
"cargo_manifest": "561cef428037910a846ff06936b1c71a7d41d386fd8341abb0e5e979a2ea83d1",
|
|
52
52
|
"library": "a85bf6a5665f3516fafddbe2b3c9460dadb7e341ce0336a79c4ecca4a4fd55d9",
|
|
53
53
|
"generated_owner": "af15a8dab10c1ac35d1c7bcbf2174d80c056e8200bd8b7f6fe2ceb60c1f9e0ea",
|
|
54
54
|
"external_consumer_test": "18cb018e87a251255457861058537fc1b07b0226c002d170de4e2c5512f2ae45",
|
|
55
|
-
"output_validator": "
|
|
56
|
-
"preflight_validator": "925c0205387dd458cd60e029179f978aa72dcc1eb3bcde6b32ad4756363b81e4"
|
|
55
|
+
"output_validator": "d20d3ecf89e81c0797340bd6779e8e58265e4cfe4c38b7519e78a9064a817415",
|
|
56
|
+
"preflight_validator": "925c0205387dd458cd60e029179f978aa72dcc1eb3bcde6b32ad4756363b81e4",
|
|
57
|
+
"cache_key_builder": "7b464d2bfd6444f03c9ebc6bc58c49e03904223dc1a55bee8bfba8dabf56e90b"
|
|
57
58
|
}
|
|
58
59
|
},
|
|
59
60
|
"generated_static_facts": {
|
|
@@ -62,7 +63,7 @@
|
|
|
62
63
|
"c1_routes": 3,
|
|
63
64
|
"fingerprint_toolchain": "rustc-1.85.0",
|
|
64
65
|
"application_machine_fingerprint": "NOT_GENERATED_SK_02",
|
|
65
|
-
"template_identity_sha256": "
|
|
66
|
+
"template_identity_sha256": "04f64225450bd190706464f806d8ce6604a70774b112311908ece3f448eeb261",
|
|
66
67
|
"service_capacity": "whole-bundle-facade-owned",
|
|
67
68
|
"termination": "component-opaque",
|
|
68
69
|
"continuation": "component-opaque",
|
|
@@ -91,21 +92,21 @@
|
|
|
91
92
|
],
|
|
92
93
|
"identity_closure": {
|
|
93
94
|
"path": "references/identity-closure.json",
|
|
94
|
-
"sha256": "
|
|
95
|
-
"registry_artifact_source_commit": "
|
|
96
|
-
"rust_candidate_manifest_sha256": "
|
|
95
|
+
"sha256": "620df144ab00eee84a5826bf4f53ae2f1f04b564c97f499ec9dd9a0e78b0aaea",
|
|
96
|
+
"registry_artifact_source_commit": "96cd4ec8da55b0770c5d3e8275c74e65241a4759",
|
|
97
|
+
"rust_candidate_manifest_sha256": "2b0af0e6dd396b32fcbefb4236565136319c0d33c69effc1852913acb5290b17",
|
|
97
98
|
"registry_packages_sha256": {
|
|
98
|
-
"saddle-admission": "
|
|
99
|
-
"saddle-core": "
|
|
100
|
-
"saddle-db": "
|
|
101
|
-
"saddle-framework": "
|
|
102
|
-
"saddle-macros": "
|
|
103
|
-
"saddle-observability": "
|
|
104
|
-
"saddle-runtime": "
|
|
105
|
-
"saddle-service": "
|
|
99
|
+
"saddle-admission": "86c6a3787d1612faa49558f5a104ba78415ff604344112c150b6b69446937065",
|
|
100
|
+
"saddle-core": "bf4e1cd2343cc239a0bb8288fe0947e73775d9cb3438b85ee1c15026a6369aa0",
|
|
101
|
+
"saddle-db": "e3cac62b288d0e7cf775138793e2d8afb8923b4bbb4d72afb2deb8c18d9b7030",
|
|
102
|
+
"saddle-framework": "6f819954a32f042aa43a55c1fddb8e1a8c6de389f5f3b6cd006bba532a1aca0b",
|
|
103
|
+
"saddle-macros": "e46b63cda97e643f41a86ac817306081b88c1af186c635e9451946b51c59dbeb",
|
|
104
|
+
"saddle-observability": "5e6f5d2228e8a02dd6bf65cbbd2e982129696976a104c4caf773c12016e1ecd3",
|
|
105
|
+
"saddle-runtime": "0c8925b3871f95f58cde8cf7de6938116d4fbb35000ea31699c7603d658deee2",
|
|
106
|
+
"saddle-service": "6d148466da57be9be7b2e4df9dcd68f0a253a418db247438ad0be1e886c8ff1b"
|
|
106
107
|
},
|
|
107
|
-
"framework_crate_sha256": "
|
|
108
|
-
"fresh_registry_cargo_lock_sha256": "
|
|
109
|
-
"registry_consumer_cargo_lock_sha256": "
|
|
108
|
+
"framework_crate_sha256": "6f819954a32f042aa43a55c1fddb8e1a8c6de389f5f3b6cd006bba532a1aca0b",
|
|
109
|
+
"fresh_registry_cargo_lock_sha256": "542bb990a3e176f3cc987b34df23061c6fdaac321d3433aaa08cf5f47151631a",
|
|
110
|
+
"registry_consumer_cargo_lock_sha256": "8896ba07b7a868b6914fa4cf5e85358e0c201bd717083c1822d0456d547a87ed"
|
|
110
111
|
}
|
|
111
112
|
}
|
package/package.json
CHANGED
|
@@ -51,9 +51,9 @@ where
|
|
|
51
51
|
为 private、non-Clone 且仅移动一次。bundle 与 config 由 Test/部署控制面提供;Skill 不生成
|
|
52
52
|
provider、credential、calibration 或 raw owner constructor。
|
|
53
53
|
|
|
54
|
-
Facade source `
|
|
54
|
+
Facade source `96cd4ec8da55b0770c5d3e8275c74e65241a4759` 已真实导出本候选宏和
|
|
55
55
|
managed API,并物理收口 V1 路径。该 source checkpoint 仍不等于已发布的
|
|
56
|
-
`saddle-framework 0.2.0
|
|
56
|
+
`saddle-framework 0.2.0`;正式使用必须按 package manifest 精确匹配该候选制品。
|
|
57
57
|
旧 rc.3/rc.4 与外部 proof associated types 不兼容,禁止回退或混用。
|
|
58
58
|
|
|
59
59
|
## 稳定诊断 code 候选
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "saddle-skill-identity-closure/2",
|
|
3
|
-
"skill_release": "0.2.0
|
|
4
|
-
"rust_release": "0.2.0
|
|
5
|
-
"artifact_source_commit": "
|
|
6
|
-
"registry_artifact_source_commit": "
|
|
7
|
-
"rust_candidate_manifest_sha256": "
|
|
3
|
+
"skill_release": "0.2.0",
|
|
4
|
+
"rust_release": "0.2.0",
|
|
5
|
+
"artifact_source_commit": "96cd4ec8da55b0770c5d3e8275c74e65241a4759",
|
|
6
|
+
"registry_artifact_source_commit": "96cd4ec8da55b0770c5d3e8275c74e65241a4759",
|
|
7
|
+
"rust_candidate_manifest_sha256": "2b0af0e6dd396b32fcbefb4236565136319c0d33c69effc1852913acb5290b17",
|
|
8
8
|
"registry_packages_sha256": {
|
|
9
|
-
"saddle-admission": "
|
|
10
|
-
"saddle-core": "
|
|
11
|
-
"saddle-db": "
|
|
12
|
-
"saddle-framework": "
|
|
13
|
-
"saddle-macros": "
|
|
14
|
-
"saddle-observability": "
|
|
15
|
-
"saddle-runtime": "
|
|
16
|
-
"saddle-service": "
|
|
9
|
+
"saddle-admission": "86c6a3787d1612faa49558f5a104ba78415ff604344112c150b6b69446937065",
|
|
10
|
+
"saddle-core": "bf4e1cd2343cc239a0bb8288fe0947e73775d9cb3438b85ee1c15026a6369aa0",
|
|
11
|
+
"saddle-db": "e3cac62b288d0e7cf775138793e2d8afb8923b4bbb4d72afb2deb8c18d9b7030",
|
|
12
|
+
"saddle-framework": "6f819954a32f042aa43a55c1fddb8e1a8c6de389f5f3b6cd006bba532a1aca0b",
|
|
13
|
+
"saddle-macros": "e46b63cda97e643f41a86ac817306081b88c1af186c635e9451946b51c59dbeb",
|
|
14
|
+
"saddle-observability": "5e6f5d2228e8a02dd6bf65cbbd2e982129696976a104c4caf773c12016e1ecd3",
|
|
15
|
+
"saddle-runtime": "0c8925b3871f95f58cde8cf7de6938116d4fbb35000ea31699c7603d658deee2",
|
|
16
|
+
"saddle-service": "6d148466da57be9be7b2e4df9dcd68f0a253a418db247438ad0be1e886c8ff1b"
|
|
17
17
|
},
|
|
18
|
-
"framework_crate_sha256": "
|
|
19
|
-
"fresh_registry_cargo_lock_sha256": "
|
|
20
|
-
"registry_consumer_cargo_lock_sha256": "
|
|
18
|
+
"framework_crate_sha256": "6f819954a32f042aa43a55c1fddb8e1a8c6de389f5f3b6cd006bba532a1aca0b",
|
|
19
|
+
"fresh_registry_cargo_lock_sha256": "542bb990a3e176f3cc987b34df23061c6fdaac321d3433aaa08cf5f47151631a",
|
|
20
|
+
"registry_consumer_cargo_lock_sha256": "8896ba07b7a868b6914fa4cf5e85358e0c201bd717083c1822d0456d547a87ed",
|
|
21
21
|
"declaration_schema": "saddle-application/1",
|
|
22
22
|
"machine_schema": "saddle-approved-build/2",
|
|
23
23
|
"generated_static_schema": "saddle-generated-static-facts/2",
|
|
@@ -28,21 +28,22 @@
|
|
|
28
28
|
"canonical_machine_input_sha256": "f7e73baa824f607a83a275e20681da46e4eab6f250fba8129bf959a1b7f263e6",
|
|
29
29
|
"semantic_fact_whole_sha256": "a3ccc16cd94daec6c3bd4b93d7f8095b4eef68d3e9dbb686c8942c341acda5b2"
|
|
30
30
|
},
|
|
31
|
-
"public_api_snapshot_sha256": "
|
|
31
|
+
"public_api_snapshot_sha256": "da87e0b63c3fdf511daac30581cbf415f49541df2034d1e7bc713a9833179a51",
|
|
32
32
|
"machine_schema_document_sha256": "353ee7fbf4dc8219595c44a1871f699952d0f2b116ed5ec615242c3f5521285d",
|
|
33
33
|
"approved_locks": {
|
|
34
|
-
"registry_consumer": "
|
|
34
|
+
"registry_consumer": "8896ba07b7a868b6914fa4cf5e85358e0c201bd717083c1822d0456d547a87ed"
|
|
35
35
|
},
|
|
36
36
|
"unified_application_sha256": "a85bf6a5665f3516fafddbe2b3c9460dadb7e341ce0336a79c4ecca4a4fd55d9",
|
|
37
37
|
"unified_owner_sha256": "af15a8dab10c1ac35d1c7bcbf2174d80c056e8200bd8b7f6fe2ceb60c1f9e0ea",
|
|
38
|
-
"template_identity_sha256": "
|
|
38
|
+
"template_identity_sha256": "04f64225450bd190706464f806d8ce6604a70774b112311908ece3f448eeb261",
|
|
39
39
|
"registry_consumer_template": {
|
|
40
|
-
"cargo_lock": "
|
|
41
|
-
"cargo_manifest": "
|
|
40
|
+
"cargo_lock": "8896ba07b7a868b6914fa4cf5e85358e0c201bd717083c1822d0456d547a87ed",
|
|
41
|
+
"cargo_manifest": "561cef428037910a846ff06936b1c71a7d41d386fd8341abb0e5e979a2ea83d1",
|
|
42
42
|
"library": "a85bf6a5665f3516fafddbe2b3c9460dadb7e341ce0336a79c4ecca4a4fd55d9",
|
|
43
43
|
"generated_owner": "af15a8dab10c1ac35d1c7bcbf2174d80c056e8200bd8b7f6fe2ceb60c1f9e0ea",
|
|
44
44
|
"external_consumer_test": "18cb018e87a251255457861058537fc1b07b0226c002d170de4e2c5512f2ae45",
|
|
45
|
-
"output_validator": "
|
|
46
|
-
"preflight_validator": "925c0205387dd458cd60e029179f978aa72dcc1eb3bcde6b32ad4756363b81e4"
|
|
45
|
+
"output_validator": "d20d3ecf89e81c0797340bd6779e8e58265e4cfe4c38b7519e78a9064a817415",
|
|
46
|
+
"preflight_validator": "925c0205387dd458cd60e029179f978aa72dcc1eb3bcde6b32ad4756363b81e4",
|
|
47
|
+
"cache_key_builder": "7b464d2bfd6444f03c9ebc6bc58c49e03904223dc1a55bee8bfba8dabf56e90b"
|
|
47
48
|
}
|
|
48
49
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
format=saddle-public-api-snapshot/1
|
|
2
2
|
facade=saddle-framework
|
|
3
|
-
source_commit=
|
|
3
|
+
source_commit=96cd4ec8da55b0770c5d3e8275c74e65241a4759
|
|
4
4
|
declaration_schema=saddle-application/1
|
|
5
5
|
macro=saddle::application!
|
|
6
6
|
managed_type=saddle::managed::U64
|
|
@@ -18,7 +18,7 @@ def main() -> None:
|
|
|
18
18
|
parser = argparse.ArgumentParser()
|
|
19
19
|
parser.add_argument("--root", type=Path, required=True)
|
|
20
20
|
parser.add_argument("--rust-candidate-manifest", type=Path, required=True)
|
|
21
|
-
parser.add_argument("--skill-release", default="0.2.0
|
|
21
|
+
parser.add_argument("--skill-release", default="0.2.0")
|
|
22
22
|
args = parser.parse_args()
|
|
23
23
|
|
|
24
24
|
root = args.root.resolve()
|
|
@@ -26,7 +26,7 @@ def main() -> None:
|
|
|
26
26
|
candidate = json.loads(candidate_path.read_text(encoding="utf-8"))
|
|
27
27
|
if candidate.get("schema") != "saddle-rs-01-r12-rust-recovery-candidate/1":
|
|
28
28
|
raise SystemExit("unsupported Rust candidate manifest")
|
|
29
|
-
if candidate.get("release") != "0.2.0
|
|
29
|
+
if candidate.get("release") != "0.2.0" or candidate.get("status") != "candidate-ready-for-transport-review":
|
|
30
30
|
raise SystemExit("unexpected or incomplete Rust candidate")
|
|
31
31
|
if candidate.get("publish_performed") is not False or candidate.get("tag_performed") is not False:
|
|
32
32
|
raise SystemExit("Rust candidate crossed the release boundary")
|
|
@@ -57,6 +57,7 @@ def main() -> None:
|
|
|
57
57
|
"external_consumer_test": template_root / "tests/provider_consumer.rs",
|
|
58
58
|
"output_validator": skill / "scripts/validate-generated-project.sh",
|
|
59
59
|
"preflight_validator": skill / "scripts/validate-generated-preflight.sh",
|
|
60
|
+
"cache_key_builder": skill / "scripts/validation-cache-key.py",
|
|
60
61
|
}
|
|
61
62
|
observed_template = {name: digest(path) for name, path in template_inputs.items()}
|
|
62
63
|
template_identity = hashlib.sha256(
|
|
@@ -9,7 +9,35 @@ fi
|
|
|
9
9
|
project=$(cd "$1" && pwd)
|
|
10
10
|
test -f "$project/Cargo.toml"
|
|
11
11
|
test -f "$project/Cargo.lock"
|
|
12
|
-
|
|
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"
|
|
13
41
|
if find "$project" -type d -name target -print -quit | grep -q .; then
|
|
14
42
|
echo "tracked or unignored build target is forbidden" >&2
|
|
15
43
|
exit 1
|
|
@@ -30,13 +58,13 @@ if re.search(r"(?:path|git|workspace)\s*=|\[patch", cargo_text):
|
|
|
30
58
|
|
|
31
59
|
deps = cargo.get("dependencies", {})
|
|
32
60
|
framework = deps.get("saddle")
|
|
33
|
-
if not isinstance(framework, dict) or framework.get("package") != "saddle-framework" or framework.get("version") != "=0.2.0
|
|
34
|
-
raise SystemExit("exact registry saddle-framework =0.2.0
|
|
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")
|
|
35
63
|
for name, value in deps.items():
|
|
36
64
|
if name.startswith("saddle-"):
|
|
37
65
|
version = value if isinstance(value, str) else value.get("version")
|
|
38
|
-
if version != "=0.2.0
|
|
39
|
-
raise SystemExit(f"{name} must use exact registry 0.2.0
|
|
66
|
+
if version != "=0.2.0":
|
|
67
|
+
raise SystemExit(f"{name} must use exact registry 0.2.0")
|
|
40
68
|
|
|
41
69
|
sources = sorted((root / "src").glob("**/*.rs"))
|
|
42
70
|
tests = sorted((root / "tests").glob("**/*.rs"))
|
|
@@ -63,24 +91,33 @@ if "#[test]" not in test_text:
|
|
|
63
91
|
raise SystemExit("zero executable tests are forbidden")
|
|
64
92
|
PY
|
|
65
93
|
|
|
66
|
-
|
|
67
|
-
if [[ -z ${CARGO_TARGET_DIR:-} ]]; then
|
|
68
|
-
owned_target=$(mktemp -d)
|
|
69
|
-
export CARGO_TARGET_DIR=$owned_target
|
|
70
|
-
trap 'rm -rf -- "$owned_target"' EXIT
|
|
71
|
-
else
|
|
72
|
-
mkdir -p "$CARGO_TARGET_DIR"
|
|
73
|
-
fi
|
|
74
|
-
case "$(cd "$CARGO_TARGET_DIR" && pwd)" in
|
|
94
|
+
case "$(cd "$CARGO_TARGET_DIR" && pwd -P)" in
|
|
75
95
|
"$project"|"$project"/*)
|
|
76
96
|
echo "Cargo target must be outside the generated project" >&2
|
|
77
97
|
exit 1
|
|
78
98
|
;;
|
|
79
99
|
esac
|
|
80
|
-
|
|
81
|
-
cargo +1.85.0 test --manifest-path "$project/Cargo.toml" --locked
|
|
100
|
+
cargo +1.85.0 test --manifest-path "$project/Cargo.toml" --locked --offline
|
|
82
101
|
if find "$project" -type d -name target -print -quit | grep -q .; then
|
|
83
102
|
echo "validation left a build target in the generated project" >&2
|
|
84
103
|
exit 1
|
|
85
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"
|
|
86
123
|
echo "generated provider-generic consumer: PASS"
|
|
@@ -74,6 +74,7 @@ def main() -> None:
|
|
|
74
74
|
"external_consumer_test": template_root / "tests/provider_consumer.rs",
|
|
75
75
|
"output_validator": skill / "scripts/validate-generated-project.sh",
|
|
76
76
|
"preflight_validator": skill / "scripts/validate-generated-preflight.sh",
|
|
77
|
+
"cache_key_builder": skill / "scripts/validation-cache-key.py",
|
|
77
78
|
}
|
|
78
79
|
observed_template = {name: digest(path) for name, path in template_inputs.items()}
|
|
79
80
|
template_identity = hashlib.sha256(
|
|
@@ -117,9 +118,9 @@ def main() -> None:
|
|
|
117
118
|
raise SystemExit("identity closure invalid: registry package set")
|
|
118
119
|
if any(not re.fullmatch(r"[0-9a-f]{64}", value) for value in closure["registry_packages_sha256"].values()):
|
|
119
120
|
raise SystemExit("identity closure invalid: registry package digest")
|
|
120
|
-
if manifest["npm"]["version"] != "0.2.0
|
|
121
|
+
if manifest["npm"]["version"] != "0.2.0" or closure.get("skill_release") != "0.2.0":
|
|
121
122
|
raise SystemExit("identity closure invalid: Skill candidate version")
|
|
122
|
-
if manifest["rust"]["requirement"] != "=0.2.0
|
|
123
|
+
if manifest["rust"]["requirement"] != "=0.2.0" or closure.get("rust_release") != "0.2.0":
|
|
123
124
|
raise SystemExit("identity closure invalid: Rust RC version")
|
|
124
125
|
installation = manifest.get("installation", {})
|
|
125
126
|
if installation != {
|
|
@@ -36,7 +36,7 @@ fi
|
|
|
36
36
|
grep -Fxq 'schema=saddle-approved-build/2' "$input"
|
|
37
37
|
grep -Fxq 'status=rc-blackbox-candidate-unpublished' "$input"
|
|
38
38
|
grep -Fxq 'release_approval=false' "$input"
|
|
39
|
-
grep -Fxq 'rust_facade_source=
|
|
39
|
+
grep -Fxq 'rust_facade_source=96cd4ec8da55b0770c5d3e8275c74e65241a4759' "$input"
|
|
40
40
|
grep -Fxq 'generated_static_schema=saddle-generated-static-facts/2' "$input"
|
|
41
41
|
grep -Fxq 'runtime_profile=opaque-verified-startup-plan-layout' "$input"
|
|
42
42
|
grep -Fxq 'signed_production_bundle=deployment-required' "$input"
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Build the deterministic P2 validation identity for an entry-local run."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import hashlib
|
|
8
|
+
import json
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def hash_parts(parts: list[tuple[str, bytes]]) -> str:
|
|
13
|
+
digest = hashlib.sha256()
|
|
14
|
+
for name, payload in parts:
|
|
15
|
+
encoded = name.encode("utf-8")
|
|
16
|
+
digest.update(len(encoded).to_bytes(8, "big"))
|
|
17
|
+
digest.update(encoded)
|
|
18
|
+
digest.update(len(payload).to_bytes(8, "big"))
|
|
19
|
+
digest.update(payload)
|
|
20
|
+
return digest.hexdigest()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def source_digest(project: Path) -> str:
|
|
24
|
+
paths = [project / "Cargo.toml"]
|
|
25
|
+
for directory in (project / "src", project / "tests"):
|
|
26
|
+
if directory.is_dir():
|
|
27
|
+
paths.extend(path for path in directory.rglob("*.rs") if path.is_file())
|
|
28
|
+
unique = sorted(set(paths), key=lambda item: item.relative_to(project).as_posix())
|
|
29
|
+
return hash_parts(
|
|
30
|
+
[(path.relative_to(project).as_posix(), path.read_bytes()) for path in unique]
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def parse_contract(value: str) -> tuple[str, Path]:
|
|
35
|
+
if "=" not in value:
|
|
36
|
+
raise argparse.ArgumentTypeError("build contract must be label=path")
|
|
37
|
+
label, raw_path = value.split("=", 1)
|
|
38
|
+
if not label or not raw_path:
|
|
39
|
+
raise argparse.ArgumentTypeError("build contract must be label=path")
|
|
40
|
+
path = Path(raw_path).resolve()
|
|
41
|
+
if not path.is_file():
|
|
42
|
+
raise argparse.ArgumentTypeError(f"build contract is not a file: {path}")
|
|
43
|
+
return label, path
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def main() -> None:
|
|
47
|
+
parser = argparse.ArgumentParser()
|
|
48
|
+
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
49
|
+
key_parser = subparsers.add_parser("cache-key")
|
|
50
|
+
key_parser.add_argument("--project", type=Path, required=True)
|
|
51
|
+
key_parser.add_argument("--rustc-version", required=True)
|
|
52
|
+
key_parser.add_argument("--toolchain-identity", required=True)
|
|
53
|
+
key_parser.add_argument("--target-triple", required=True)
|
|
54
|
+
key_parser.add_argument("--feature-set", required=True)
|
|
55
|
+
key_parser.add_argument("--build-contract", action="append", type=parse_contract, required=True)
|
|
56
|
+
args = parser.parse_args()
|
|
57
|
+
|
|
58
|
+
project = args.project.resolve()
|
|
59
|
+
lock = project / "Cargo.lock"
|
|
60
|
+
if not lock.is_file():
|
|
61
|
+
raise SystemExit(f"Cargo.lock is missing: {lock}")
|
|
62
|
+
contracts = sorted(args.build_contract, key=lambda item: item[0])
|
|
63
|
+
build_contract_digest = hash_parts([(label, path.read_bytes()) for label, path in contracts])
|
|
64
|
+
inputs = {
|
|
65
|
+
"RUSTC_VERSION": args.rustc_version,
|
|
66
|
+
"TOOLCHAIN_IDENTITY": args.toolchain_identity,
|
|
67
|
+
"TARGET_TRIPLE": args.target_triple,
|
|
68
|
+
"FEATURE_SET": args.feature_set,
|
|
69
|
+
"LOCK_DIGEST": hashlib.sha256(lock.read_bytes()).hexdigest(),
|
|
70
|
+
"SOURCE_DIGEST": source_digest(project),
|
|
71
|
+
"BUILD_CONTRACT_DIGEST": build_contract_digest,
|
|
72
|
+
}
|
|
73
|
+
canonical = [inputs[name] for name in (
|
|
74
|
+
"RUSTC_VERSION", "TOOLCHAIN_IDENTITY", "TARGET_TRIPLE", "FEATURE_SET",
|
|
75
|
+
"LOCK_DIGEST", "SOURCE_DIGEST", "BUILD_CONTRACT_DIGEST",
|
|
76
|
+
)]
|
|
77
|
+
output = {
|
|
78
|
+
"schema": "saddle-skill-validation-cache-key/1",
|
|
79
|
+
"inputs": inputs,
|
|
80
|
+
"cache_key": hashlib.sha256(
|
|
81
|
+
json.dumps(canonical, separators=(",", ":")).encode("utf-8")
|
|
82
|
+
).hexdigest(),
|
|
83
|
+
}
|
|
84
|
+
print(json.dumps(output, separators=(",", ":"), sort_keys=True))
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
if __name__ == "__main__":
|
|
88
|
+
main()
|