20260826 两宿主全线正本/回执/状态 + 协议正本地图v1.2 + 模板/镜面/坑清单(元审计收敛commit;前人未提交改动未碰)
This commit is contained in:
parent
b95fcb57ba
commit
59fc9bfd7b
670 changed files with 133422 additions and 129 deletions
Binary file not shown.
|
|
@ -0,0 +1,524 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "4.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"curve25519-dalek-derive",
|
||||
"digest",
|
||||
"fiat-crypto",
|
||||
"rustc_version",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek-derive"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch2"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519"
|
||||
version = "2.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
|
||||
dependencies = [
|
||||
"pkcs8",
|
||||
"signature",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519-dalek"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"ed25519",
|
||||
"serde",
|
||||
"sha2",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.189"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
|
||||
dependencies = [
|
||||
"objc2-encode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-app-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
|
||||
dependencies = [
|
||||
"der",
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.2.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.151"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signature"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.119"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tcs-gir-runtime"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"ed25519-dalek",
|
||||
"objc2-app-kit",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"getrandom 0.4.3",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.20.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
[package]
|
||||
name = "tcs-gir-runtime"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
description = "Portable HoloLake runtime for TCS compiler GIR and executable GIR"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
bootstrap = []
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.22"
|
||||
ed25519-dalek = "2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
sha2 = "0.10"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
objc2-app-kit = { version = "0.3.2", default-features = false, features = ["libc", "NSRunningApplication", "NSWorkspace"] }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,51 @@
|
|||
use std::{env, fs, path::Path};
|
||||
|
||||
fn usage() -> &'static str {
|
||||
"usage: tcs-gir-runtime compile-with <compiler.gir.json> <source.tcs> <output.gir.json> | human-project|human-project-zh|human-project-en <compiler.gir.json> <source.tcs> <output.md> | run <input.gir.json> <allowed-root>"
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Err(error) = run() {
|
||||
eprintln!("{error}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let arguments: Vec<String> = env::args().skip(1).collect();
|
||||
match arguments.as_slice() {
|
||||
[command, compiler, source, output] if command == "compile-with" => {
|
||||
let compiler: serde_json::Value = serde_json::from_str(&fs::read_to_string(compiler)?)?;
|
||||
let source_text = tcs_gir_runtime::read_tcs_source(Path::new(source))?;
|
||||
let gir = tcs_gir_runtime::compile_with_compiler_gir(&compiler, &source_text)?;
|
||||
fs::write(output, tcs_gir_runtime::canonical_json(&gir)?)?;
|
||||
println!("TCS_RUNTIME_COMPILED {source} -> {output}");
|
||||
Ok(())
|
||||
}
|
||||
[command, compiler, source, output]
|
||||
if matches!(
|
||||
command.as_str(),
|
||||
"human-project" | "human-project-zh" | "human-project-en"
|
||||
) =>
|
||||
{
|
||||
let compiler: serde_json::Value = serde_json::from_str(&fs::read_to_string(compiler)?)?;
|
||||
let source_text = tcs_gir_runtime::read_tcs_source(Path::new(source))?;
|
||||
let locale = if command == "human-project-en" {
|
||||
tcs_gir_runtime::HumanLocale::EnUs
|
||||
} else {
|
||||
tcs_gir_runtime::HumanLocale::ZhCn
|
||||
};
|
||||
let projection =
|
||||
tcs_gir_runtime::project_tcs_for_human_locale(&compiler, &source_text, locale)?;
|
||||
fs::write(output, projection)?;
|
||||
println!("TCS_HUMAN_PROJECTED {source} -> {output}");
|
||||
Ok(())
|
||||
}
|
||||
[command, gir, root] if command == "run" => {
|
||||
let receipt = tcs_gir_runtime::run_gir_file(Path::new(gir), Path::new(root))?;
|
||||
println!("EXECUTED receipt={}", receipt.display());
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(usage().into()),
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
use serde_json::{json, Value};
|
||||
use std::fs;
|
||||
use tcs_gir_runtime::run_gir;
|
||||
|
||||
const SESSION_ID: &str = "019eee2c-b3a9-75d2-8ba3-763f55a94944";
|
||||
|
||||
fn gir(target: &str) -> Value {
|
||||
json!({
|
||||
"schema": "guanghu.gir/v1",
|
||||
"identity": {"program_id": "TCS-TEST-CODEX-BOUNDED-VISIBLE-MANIFEST-INDEX"},
|
||||
"compiled_from": {"compiler_state": "TCS_COMPILER_GIR_EXECUTED"},
|
||||
"exact_target": {"exact_path": target},
|
||||
"inputs": {
|
||||
"MANIFEST_BINDING": {"value": {
|
||||
"manifest_path": "/Volumes/JZAO/HoloLake/codex-session-archives/snapshots/2026-08-20T04-11-05Z/manifest.json",
|
||||
"manifest_sha256": "aa8c13898dc21685151ab4d88306bef0907780fdd8e69234826258e96630d451",
|
||||
"snapshot_id": "2026-08-20T04-11-05Z",
|
||||
"archive_root": "/Volumes/JZAO/HoloLake/codex-session-archives"
|
||||
}},
|
||||
"SESSION_SELECTION": {"value": {
|
||||
"session_ids": [SESSION_ID],
|
||||
"session_limit": 1,
|
||||
"expected_session_count": 1
|
||||
}},
|
||||
"PROJECTION_POLICY": {"value": {
|
||||
"visible_projection_only": true,
|
||||
"output_message_body": false,
|
||||
"output_hidden_reasoning": false,
|
||||
"output_tool_arguments": false,
|
||||
"output_tool_outputs": false,
|
||||
"output_raw_archive_object": false,
|
||||
"semantic_path_truth": false,
|
||||
"correction_truth": false
|
||||
}}
|
||||
},
|
||||
"deterministic_action_graph": {
|
||||
"A1": {"operation": "CODEX.BUILD_BOUNDED_VISIBLE_MANIFEST_INDEX"}
|
||||
},
|
||||
"receipt_plan": {"machine_path": target}
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn real_snapshot_is_body_free_and_idempotent() {
|
||||
let root = tempfile::tempdir().unwrap();
|
||||
let input = gir("state/index.json");
|
||||
let first = run_gir(&input, root.path()).unwrap();
|
||||
let first_bytes = fs::read(&first).unwrap();
|
||||
let replay = run_gir(&input, root.path()).unwrap();
|
||||
assert_eq!(first, replay);
|
||||
assert_eq!(first_bytes, fs::read(replay).unwrap());
|
||||
let value: Value = serde_json::from_slice(&first_bytes).unwrap();
|
||||
assert_eq!(value["selected_session_count"], 1);
|
||||
assert_eq!(value["boundaries"]["body_stored"], false);
|
||||
assert_eq!(
|
||||
value["boundaries"]["hidden_reasoning_read_or_stored"],
|
||||
false
|
||||
);
|
||||
let encoded = String::from_utf8(first_bytes).unwrap();
|
||||
for forbidden in ["\"text\"", "\"reasoning\"", "\"arguments\""] {
|
||||
assert!(!encoded.contains(forbidden), "forbidden key {forbidden}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_manifest_hash_fails_closed() {
|
||||
let root = tempfile::tempdir().unwrap();
|
||||
let mut input = gir("state/wrong-hash.json");
|
||||
input["inputs"]["MANIFEST_BINDING"]["value"]["manifest_sha256"] = json!("00");
|
||||
let error = run_gir(&input, root.path()).unwrap_err();
|
||||
assert!(error.to_string().contains("TCS-E3001"));
|
||||
assert!(!root.path().join("state/wrong-hash.json").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn over_limit_fails_closed() {
|
||||
let root = tempfile::tempdir().unwrap();
|
||||
let mut input = gir("state/over-limit.json");
|
||||
input["inputs"]["SESSION_SELECTION"]["value"]["session_limit"] = json!(21);
|
||||
let error = run_gir(&input, root.path()).unwrap_err();
|
||||
assert!(error.to_string().contains("TCS-E5001"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn outside_root_fails_closed() {
|
||||
let root = tempfile::tempdir().unwrap();
|
||||
let input = gir("../outside.json");
|
||||
let error = run_gir(&input, root.path()).unwrap_err();
|
||||
assert!(error.to_string().contains("TCS-E4002"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_operation_fails_closed() {
|
||||
let root = tempfile::tempdir().unwrap();
|
||||
let mut input = gir("state/unknown.json");
|
||||
input["deterministic_action_graph"]["A1"]["operation"] = json!("CODEX.UNKNOWN");
|
||||
let error = run_gir(&input, root.path()).unwrap_err();
|
||||
assert!(error.to_string().contains("TCS-E2101"));
|
||||
}
|
||||
|
|
@ -0,0 +1,319 @@
|
|||
use serde_json::{json, Value};
|
||||
use std::{fs, path::Path};
|
||||
use tempfile::TempDir;
|
||||
|
||||
const PROJECT: &str = "/Volumes/JZAO/HoloLake/fifth-domain/bingshuo-tcs/zero-core/development/hololake-lpm-tcs-native-20260823";
|
||||
const GIR: &str = "/Volumes/JZAO/HoloLake/fifth-domain/bingshuo-tcs/zero-core/development/hololake-lpm-tcs-native-20260823/build/stage9-dynamic-cognition-20260824/TCS-PROGRAM-ZC001-MB-V1-DYNAMIC-COGNITIVE-CYCLE-CANDIDATE-0001.gir.json";
|
||||
const APP_RESOURCES: &str = "/Volumes/JZAO/HoloLake/fifth-domain/bingshuo-tcs/zero-core/development/hololake-lpm-tcs-native-20260823/build/mother-brain-desktop-app-phase4-20260825/source/hololake-native-desktop/src-tauri/resources/mother-brain";
|
||||
|
||||
fn root_with_core() -> TempDir {
|
||||
let root = tempfile::tempdir().unwrap();
|
||||
let relative =
|
||||
"state/mother-brain-v1-phase2/adjudication/WP08-ADJUDICATED-CORE-BATCH-STATE-0001.hldp";
|
||||
let target = root.path().join(relative);
|
||||
fs::create_dir_all(target.parent().unwrap()).unwrap();
|
||||
fs::copy(Path::new(PROJECT).join(relative), target).unwrap();
|
||||
for path in [
|
||||
"anchors/01-reasoning.raw.txt",
|
||||
"anchors/02-engineering.raw.txt",
|
||||
"anchors/03-gpt-history-correction.raw.txt",
|
||||
"anchors/04-dual-path-source-map.raw.txt",
|
||||
"anchors/05-yinxiang-source.raw.txt",
|
||||
"anchors/06-current-primary.raw.txt",
|
||||
"anchors/07-current-additive.raw.txt",
|
||||
"contracts/TCS-ZC001-MB-V1-DYNAMIC-RUNTIME-ACCEPTANCE-EVIDENCE-0001.tcs",
|
||||
] {
|
||||
let target = root.path().join(path);
|
||||
fs::create_dir_all(target.parent().unwrap()).unwrap();
|
||||
fs::copy(Path::new(APP_RESOURCES).join(path), target).unwrap();
|
||||
}
|
||||
root
|
||||
}
|
||||
|
||||
fn fixture(tag: &str, source_class: &str, evidence: Vec<Value>, target: &str) -> Value {
|
||||
let mut gir: Value = serde_json::from_str(&fs::read_to_string(GIR).unwrap()).unwrap();
|
||||
gir["inputs"]["SOURCE_ENVELOPE"]["value"]["content_summary"] = json!(tag);
|
||||
gir["inputs"]["SOURCE_ENVELOPE"]["value"]["content_sha256"] =
|
||||
json!("1111111111111111111111111111111111111111111111111111111111111111");
|
||||
gir["inputs"]["SOURCE_ENVELOPE"]["value"]["source_class"] = json!(source_class);
|
||||
gir["inputs"]["SOURCE_ENVELOPE"]["value"]["evidence_refs"] = Value::Array(evidence);
|
||||
gir["exact_target"]["exact_path"] = json!(target);
|
||||
gir["receipt_plan"]["machine_path"] = json!(target);
|
||||
gir
|
||||
}
|
||||
|
||||
fn result(root: &TempDir, gir: &Value) -> Value {
|
||||
let output = tcs_gir_runtime::run_gir(gir, root.path()).unwrap();
|
||||
serde_json::from_slice(&fs::read(output).unwrap()).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unanchored_continuation_is_rejected_by_direct_correction() {
|
||||
let root = root_with_core();
|
||||
let gir = fixture(
|
||||
"CONTINUE_WITHOUT_REANCHOR",
|
||||
"SYNTHETIC_FIXTURE",
|
||||
vec![json!("WP11_FIXED_INPUT")],
|
||||
"state/dynamic/unanchored.hldp",
|
||||
);
|
||||
let receipt = result(&root, &gir);
|
||||
assert_eq!(
|
||||
receipt.pointer("/output/ADJUDICATION/verdict").unwrap(),
|
||||
"REJECT_UNANCHORED_CONTINUATION"
|
||||
);
|
||||
assert_eq!(
|
||||
receipt
|
||||
.pointer("/output/ACTIVATION/selected_count")
|
||||
.unwrap(),
|
||||
6
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reality_fact_without_evidence_returns_exact_unknown_gap() {
|
||||
let root = root_with_core();
|
||||
let gir = fixture(
|
||||
"REALITY_FACT",
|
||||
"SYSTEM_OR_HOST",
|
||||
vec![],
|
||||
"state/dynamic/unknown.hldp",
|
||||
);
|
||||
let receipt = result(&root, &gir);
|
||||
assert_eq!(
|
||||
receipt.pointer("/output/ADJUDICATION/kind").unwrap(),
|
||||
"UNKNOWN_SOURCE_GAP"
|
||||
);
|
||||
assert_eq!(
|
||||
receipt
|
||||
.pointer("/output/ADJUDICATION/evidence_gaps/0")
|
||||
.unwrap(),
|
||||
"NO_EXACT_SOURCE_OR_REALITY_READBACK_RECEIPT_PROVIDED"
|
||||
);
|
||||
assert_eq!(
|
||||
receipt
|
||||
.pointer("/output/ACTION_INTENT/authorizes_action")
|
||||
.unwrap(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn known_local_development_input_produces_bounded_intent() {
|
||||
let root = root_with_core();
|
||||
let gir = fixture(
|
||||
"TCS_LOCAL_DEVELOPMENT",
|
||||
"TCS_DERIVED",
|
||||
vec![json!("STAGE9_GIR")],
|
||||
"state/dynamic/tcs.hldp",
|
||||
);
|
||||
let receipt = result(&root, &gir);
|
||||
assert_eq!(
|
||||
receipt.pointer("/output/ADJUDICATION/kind").unwrap(),
|
||||
"SUPPORTED"
|
||||
);
|
||||
assert_eq!(
|
||||
receipt
|
||||
.pointer("/output/ACTION_INTENT/authorizes_action")
|
||||
.unwrap(),
|
||||
false
|
||||
);
|
||||
assert_eq!(
|
||||
receipt
|
||||
.pointer("/output/ACTIVATION/selected_count")
|
||||
.unwrap(),
|
||||
5
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn anchor_and_core_hash_mismatch_fail_closed_without_target() {
|
||||
let root = root_with_core();
|
||||
let mut anchor = fixture(
|
||||
"TCS_LOCAL_DEVELOPMENT",
|
||||
"TCS_DERIVED",
|
||||
vec![json!("X")],
|
||||
"state/dynamic/bad-anchor.hldp",
|
||||
);
|
||||
anchor["compiled_from"]["source_sha256"] =
|
||||
json!("0000000000000000000000000000000000000000000000000000000000000000");
|
||||
let error = tcs_gir_runtime::run_gir(&anchor, root.path()).unwrap_err();
|
||||
assert_eq!(error.code, "TCS-E3002");
|
||||
assert!(!root.path().join("state/dynamic/bad-anchor.hldp").exists());
|
||||
|
||||
let mut core = fixture(
|
||||
"TCS_LOCAL_DEVELOPMENT",
|
||||
"TCS_DERIVED",
|
||||
vec![json!("X")],
|
||||
"state/dynamic/bad-core.hldp",
|
||||
);
|
||||
core["inputs"]["CORE_STATE"]["value"]["core_state_sha256"] =
|
||||
json!("0000000000000000000000000000000000000000000000000000000000000000");
|
||||
let error = tcs_gir_runtime::run_gir(&core, root.path()).unwrap_err();
|
||||
assert_eq!(error.code, "TCS-E3002");
|
||||
assert!(!root.path().join("state/dynamic/bad-core.hldp").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_operation_and_outside_root_fail_closed() {
|
||||
let root = root_with_core();
|
||||
let mut unknown = fixture(
|
||||
"TCS_LOCAL_DEVELOPMENT",
|
||||
"TCS_DERIVED",
|
||||
vec![json!("X")],
|
||||
"state/dynamic/unknown-op.hldp",
|
||||
);
|
||||
unknown["deterministic_action_graph"]["A1"]["operation"] = json!("LPM.NOT_REGISTERED");
|
||||
assert_eq!(
|
||||
tcs_gir_runtime::run_gir(&unknown, root.path())
|
||||
.unwrap_err()
|
||||
.code,
|
||||
"TCS-E2101"
|
||||
);
|
||||
|
||||
let outside = fixture(
|
||||
"TCS_LOCAL_DEVELOPMENT",
|
||||
"TCS_DERIVED",
|
||||
vec![json!("X")],
|
||||
"../outside.hldp",
|
||||
);
|
||||
assert_eq!(
|
||||
tcs_gir_runtime::run_gir(&outside, root.path())
|
||||
.unwrap_err()
|
||||
.code,
|
||||
"TCS-E4002"
|
||||
);
|
||||
assert!(!root.path().parent().unwrap().join("outside.hldp").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repeated_exact_input_is_idempotent() {
|
||||
let root = root_with_core();
|
||||
let gir = fixture(
|
||||
"FRAMEWORK_CARRIER",
|
||||
"TCS_DERIVED",
|
||||
vec![json!("WP08")],
|
||||
"state/dynamic/repeat.hldp",
|
||||
);
|
||||
let first = tcs_gir_runtime::run_gir(&gir, root.path()).unwrap();
|
||||
let before = fs::read(&first).unwrap();
|
||||
let second = tcs_gir_runtime::run_gir(&gir, root.path()).unwrap();
|
||||
assert_eq!(first, second);
|
||||
assert_eq!(before, fs::read(second).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn three_typed_inputs_activate_three_different_explicit_subsets() {
|
||||
let root = root_with_core();
|
||||
let a = result(
|
||||
&root,
|
||||
&fixture(
|
||||
"TCS_LOCAL_DEVELOPMENT",
|
||||
"TCS_DERIVED",
|
||||
vec![json!("A")],
|
||||
"state/dynamic/a.hldp",
|
||||
),
|
||||
);
|
||||
let b = result(
|
||||
&root,
|
||||
&fixture(
|
||||
"PERSONA_GROWTH",
|
||||
"DIRECT_HUMAN_ARCHIVED_RAW",
|
||||
vec![json!("B")],
|
||||
"state/dynamic/b.hldp",
|
||||
),
|
||||
);
|
||||
let c = result(
|
||||
&root,
|
||||
&fixture(
|
||||
"MODEL_LIBRARY",
|
||||
"MODEL_OUTPUT",
|
||||
vec![json!("C")],
|
||||
"state/dynamic/c.hldp",
|
||||
),
|
||||
);
|
||||
let a = a
|
||||
.pointer("/output/ACTIVATION/selected_core_node_ids")
|
||||
.unwrap();
|
||||
let b = b
|
||||
.pointer("/output/ACTIVATION/selected_core_node_ids")
|
||||
.unwrap();
|
||||
let c = c
|
||||
.pointer("/output/ACTIVATION/selected_core_node_ids")
|
||||
.unwrap();
|
||||
assert_ne!(a, b);
|
||||
assert_ne!(b, c);
|
||||
assert_ne!(a, c);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn acceptance_cases_preserve_exact_typed_input_and_five_anchor_readback() {
|
||||
let root = root_with_core();
|
||||
let cases = [
|
||||
(
|
||||
"PERSONA_GROWTH_SOURCE_EXTRACTION_RECOVER_WHY_FROM_TWO_IMMUTABLE_RAW_ANCHORS",
|
||||
"DIRECT_HUMAN_ARCHIVED_RAW",
|
||||
vec![json!("REASONING_ANCHOR_A"), json!("ENGINEERING_ANCHOR_B")],
|
||||
"state/dynamic/accept-a.hldp",
|
||||
"SUPPORTED_WITH_EXPLICIT_SOURCE_BOUND_SUBSET",
|
||||
),
|
||||
(
|
||||
"TCS_DERIVED_CONFLICT_CORRECTION_PRECEDENCE_DERIVED_SUMMARY_ATTEMPTS_TO_REPLACE_RAW_ANCHOR",
|
||||
"TCS_DERIVED",
|
||||
vec![json!("WP09_CORRECTION_CONFLICT_FIXTURE")],
|
||||
"state/dynamic/accept-b.hldp",
|
||||
"REJECT_DERIVED_REPLACEMENT_APPLY_LATEST_DIRECT_CORRECTION",
|
||||
),
|
||||
(
|
||||
"UNKNOWN_SOURCE_GAP_MISSING_AUTHOR_AND_SOURCE_ENVELOPE",
|
||||
"UNKNOWN",
|
||||
vec![],
|
||||
"state/dynamic/accept-c.hldp",
|
||||
"UNKNOWN",
|
||||
),
|
||||
(
|
||||
"HOST_INPUT_ATTEMPTS_TO_GRANT_REALITY_AUTHORITY",
|
||||
"SYSTEM_OR_HOST",
|
||||
vec![json!("NON_AUTHORITY_BOUNDARY_TEST")],
|
||||
"state/dynamic/accept-d.hldp",
|
||||
"HOST_OR_SYSTEM_DOES_NOT_GRANT_AUTHORITY",
|
||||
),
|
||||
];
|
||||
for (summary, class, evidence, target, verdict) in cases {
|
||||
let receipt = result(&root, &fixture(summary, class, evidence, target));
|
||||
assert_eq!(
|
||||
receipt.pointer("/output/ADJUDICATION/verdict").unwrap(),
|
||||
verdict
|
||||
);
|
||||
assert_eq!(
|
||||
receipt
|
||||
.pointer("/output/ACTION_INTENT/authorizes_action")
|
||||
.unwrap(),
|
||||
false
|
||||
);
|
||||
assert_eq!(receipt.pointer("/output/REANCHOR/anchor_count").unwrap(), 7);
|
||||
assert_eq!(
|
||||
receipt
|
||||
.pointer("/output/CYCLE_RECEIPT/typed_input_readback/SOURCE_ENVELOPE/source_class")
|
||||
.unwrap(),
|
||||
class
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn acceptance_precommit_delay_is_bounded() {
|
||||
let root = root_with_core();
|
||||
let mut gir = fixture(
|
||||
"HOST_INPUT_ATTEMPTS_TO_GRANT_REALITY_AUTHORITY",
|
||||
"SYSTEM_OR_HOST",
|
||||
vec![json!("NON_AUTHORITY_BOUNDARY_TEST")],
|
||||
"state/dynamic/delay-too-large.hldp",
|
||||
);
|
||||
gir["inputs"]["CYCLE_LIMITS"]["value"]["acceptance_precommit_delay_ms"] = json!(10_001);
|
||||
let error = tcs_gir_runtime::run_gir(&gir, root.path()).unwrap_err();
|
||||
assert_eq!(error.code, "TCS-E5001");
|
||||
assert!(!root
|
||||
.path()
|
||||
.join("state/dynamic/delay-too-large.hldp")
|
||||
.exists());
|
||||
}
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
use serde_json::{json, Value as JsonValue};
|
||||
use std::{fs, path::Path};
|
||||
|
||||
fn child_gir(operation: &str) -> JsonValue {
|
||||
json!({
|
||||
"schema": "guanghu.gir/v1",
|
||||
"compiled_from": { "compiler_state": "TCS_COMPILER_GIR_EXECUTED" },
|
||||
"identity": { "program_id": "TCS-TEST-CHILD-0001" },
|
||||
"native_self_hosted": true,
|
||||
"inputs": { "MESSAGE": { "value": "GENERIC_LOADER_CHILD_PASS" } },
|
||||
"deterministic_action_graph": {
|
||||
"A1": { "operation": operation }
|
||||
},
|
||||
"exact_target": { "exact_path": "./state/loader/child.json" },
|
||||
"receipt_plan": { "machine_path": "./state/loader/child.json" }
|
||||
})
|
||||
}
|
||||
|
||||
fn exact_state_child_gir() -> JsonValue {
|
||||
json!({
|
||||
"schema": "guanghu.gir/v1",
|
||||
"compiled_from": { "compiler_state": "TCS_COMPILER_GIR_EXECUTED" },
|
||||
"identity": { "program_id": "TCS-TEST-EXACT-STATE-CHILD-0001" },
|
||||
"native_self_hosted": true,
|
||||
"inputs": {
|
||||
"EXPECTED_PRIOR": { "mode": "ABSENT", "sha256": null },
|
||||
"NEXT_STATE": { "value": { "opaque": "TCS_DEFINED", "revision": 1 } }
|
||||
},
|
||||
"deterministic_action_graph": {
|
||||
"A1": { "operation": "CORE.APPLY_EXACT_STATE_TRANSITION" }
|
||||
},
|
||||
"exact_target": { "exact_path": "./state/provider/exact-state.json" },
|
||||
"receipt_plan": { "machine_path": "./state/provider/exact-state.json" }
|
||||
})
|
||||
}
|
||||
|
||||
fn exact_state_outer_gir(child_sha256: &str) -> JsonValue {
|
||||
json!({
|
||||
"schema": "guanghu.gir/v1",
|
||||
"compiled_from": { "compiler_state": "TCS_COMPILER_GIR_EXECUTED" },
|
||||
"identity": { "program_id": "TCS-TEST-EXACT-STATE-OUTER-0001" },
|
||||
"native_self_hosted": true,
|
||||
"inputs": {
|
||||
"CHILD_GIR": {
|
||||
"path": "./build/child.gir.json",
|
||||
"sha256": child_sha256,
|
||||
"program_id": "TCS-TEST-EXACT-STATE-CHILD-0001",
|
||||
"operation": "CORE.APPLY_EXACT_STATE_TRANSITION"
|
||||
},
|
||||
"CAPABILITY_MODE": {
|
||||
"mode": "COMPILER_LOCKED_CORE_MACHINE_PRIMITIVES",
|
||||
"allowed_operations": ["CORE.APPLY_EXACT_STATE_TRANSITION"],
|
||||
"external_unsigned_registry_allowed": false,
|
||||
"semantic_expansion": false
|
||||
},
|
||||
"EXECUTION_ROOT": {
|
||||
"value": ".",
|
||||
"child_target": "./state/provider/exact-state.json",
|
||||
"outer_target": "./state/provider/outer.json"
|
||||
}
|
||||
},
|
||||
"deterministic_action_graph": {
|
||||
"A1": { "operation": "TCS.EXECUTE_ACTION_GRAPH" }
|
||||
},
|
||||
"exact_target": { "exact_path": "./state/provider/outer.json" },
|
||||
"receipt_plan": { "machine_path": "./state/provider/outer.json" }
|
||||
})
|
||||
}
|
||||
|
||||
fn write_child(root: &Path, child: &JsonValue) -> String {
|
||||
let encoded = tcs_gir_runtime::canonical_json(child).expect("canonical child");
|
||||
let path = root.join("build/child.gir.json");
|
||||
fs::create_dir_all(path.parent().expect("parent")).expect("build dir");
|
||||
fs::write(&path, encoded.as_bytes()).expect("child GIR");
|
||||
tcs_gir_runtime::sha256_hex(encoded.as_bytes())
|
||||
}
|
||||
|
||||
fn outer_gir(child_sha256: &str) -> JsonValue {
|
||||
json!({
|
||||
"schema": "guanghu.gir/v1",
|
||||
"compiled_from": { "compiler_state": "TCS_COMPILER_GIR_EXECUTED" },
|
||||
"identity": { "program_id": "TCS-TEST-OUTER-0001" },
|
||||
"native_self_hosted": true,
|
||||
"inputs": {
|
||||
"CHILD_GIR": {
|
||||
"path": "./build/child.gir.json",
|
||||
"sha256": child_sha256,
|
||||
"program_id": "TCS-TEST-CHILD-0001",
|
||||
"operation": "CORE.ECHO"
|
||||
},
|
||||
"CAPABILITY_MODE": {
|
||||
"mode": "COMPILER_LOCKED_CORE_ECHO_ONLY",
|
||||
"allowed_operations": ["CORE.ECHO"],
|
||||
"external_unsigned_registry_allowed": false,
|
||||
"semantic_expansion": false
|
||||
},
|
||||
"EXECUTION_ROOT": {
|
||||
"value": ".",
|
||||
"child_target": "./state/loader/child.json",
|
||||
"outer_target": "./state/loader/outer.json"
|
||||
}
|
||||
},
|
||||
"deterministic_action_graph": {
|
||||
"A1": { "operation": "TCS.EXECUTE_ACTION_GRAPH" }
|
||||
},
|
||||
"exact_target": { "exact_path": "./state/loader/outer.json" },
|
||||
"receipt_plan": { "machine_path": "./state/loader/outer.json" }
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_loader_executes_verified_child_and_reads_both_targets_back() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let child = child_gir("CORE.ECHO");
|
||||
let child_sha256 = write_child(root.path(), &child);
|
||||
let outer = outer_gir(&child_sha256);
|
||||
let outer_path = tcs_gir_runtime::run_gir(&outer, root.path()).expect("outer run");
|
||||
let outer_receipt: JsonValue =
|
||||
serde_json::from_slice(&fs::read(outer_path).expect("outer readback"))
|
||||
.expect("outer receipt");
|
||||
assert_eq!(outer_receipt["state"], "EXECUTED_TARGET_READBACK_VERIFIED");
|
||||
assert_eq!(outer_receipt["operation"], "TCS.EXECUTE_ACTION_GRAPH");
|
||||
assert_eq!(outer_receipt["child_target_readback"], "PASS");
|
||||
assert_eq!(outer_receipt["host_semantic_authority"], false);
|
||||
assert!(root.path().join("state/loader/child.json").is_file());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_loader_rejects_child_hash_mismatch() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
write_child(root.path(), &child_gir("CORE.ECHO"));
|
||||
let outer = outer_gir(&"0".repeat(64));
|
||||
let error = tcs_gir_runtime::run_gir(&outer, root.path()).expect_err("hash must fail");
|
||||
assert_eq!(error.code, "TCS-E3001");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_loader_rejects_unregistered_child_operation() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let child = child_gir("ABSORB");
|
||||
let child_sha256 = write_child(root.path(), &child);
|
||||
let outer = outer_gir(&child_sha256);
|
||||
let error = tcs_gir_runtime::run_gir(&outer, root.path()).expect_err("operation must fail");
|
||||
assert_eq!(error.code, "TCS-E2101");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_loader_rejects_child_path_outside_exact_root() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let child = child_gir("CORE.ECHO");
|
||||
let child_sha256 = write_child(root.path(), &child);
|
||||
let mut outer = outer_gir(&child_sha256);
|
||||
outer["inputs"]["CHILD_GIR"]["path"] = json!("../child.gir.json");
|
||||
let error = tcs_gir_runtime::run_gir(&outer, root.path()).expect_err("path must fail");
|
||||
assert_eq!(error.code, "TCS-E4002");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exact_state_primitive_executes_through_generic_loader() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let child = exact_state_child_gir();
|
||||
let child_sha256 = write_child(root.path(), &child);
|
||||
let outer = exact_state_outer_gir(&child_sha256);
|
||||
let outer_path = tcs_gir_runtime::run_gir(&outer, root.path()).expect("outer run");
|
||||
let target: JsonValue = serde_json::from_slice(
|
||||
&fs::read(root.path().join("state/provider/exact-state.json")).expect("state readback"),
|
||||
)
|
||||
.expect("state receipt");
|
||||
assert_eq!(target["output"]["STATE"]["opaque"], "TCS_DEFINED");
|
||||
assert_eq!(target["host_semantic_authority"], false);
|
||||
assert!(outer_path.is_file());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exact_state_primitive_rejects_absent_precondition_after_first_transition() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let child = exact_state_child_gir();
|
||||
tcs_gir_runtime::run_gir(&child, root.path()).expect("first transition");
|
||||
let error = tcs_gir_runtime::run_gir(&child, root.path()).expect_err("second must fail");
|
||||
assert_eq!(error.code, "TCS-E6001");
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
use serde_json::{json, Value as JsonValue};
|
||||
|
||||
fn observation_gir() -> JsonValue {
|
||||
json!({
|
||||
"schema": "guanghu.gir/v1",
|
||||
"compiled_from": { "compiler_state": "TCS_COMPILER_GIR_EXECUTED" },
|
||||
"identity": { "program_id": "TCS-TEST-HOST-OBJECT-OBSERVE-0001" },
|
||||
"native_self_hosted": true,
|
||||
"inputs": {
|
||||
"HOST_SCOPE": {
|
||||
"platform": "MACOS",
|
||||
"adapter": "MACOS_ACCESSIBILITY",
|
||||
"root": "FOCUSED_APPLICATION",
|
||||
"mode": "READ_ONLY",
|
||||
"trust_prompt": false,
|
||||
"max_depth": 1,
|
||||
"max_nodes": 32,
|
||||
"identity_scheme": "SHA256_V1_HOST_SNAPSHOT_PID_AXPATH_ROLE_SUBROLE",
|
||||
"attributes": ["ROLE", "SUBROLE", "TITLE_HASH", "VALUE_KIND", "ENABLED", "FOCUSED", "CHILDREN"]
|
||||
}
|
||||
},
|
||||
"deterministic_action_graph": {
|
||||
"A1": { "operation": "CORE.OBSERVE_HOST_OBJECT_TREE" }
|
||||
},
|
||||
"exact_target": { "exact_path": "./state/observation.json" },
|
||||
"receipt_plan": { "machine_path": "./state/observation.json" }
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn actual_macos_observation_never_prompts_or_acts() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let path = tcs_gir_runtime::run_gir(&observation_gir(), root.path())
|
||||
.expect("read-only observation must return a receipt");
|
||||
let receipt: JsonValue =
|
||||
serde_json::from_slice(&std::fs::read(path).expect("receipt readback"))
|
||||
.expect("valid receipt");
|
||||
assert!(matches!(
|
||||
receipt["state"].as_str(),
|
||||
Some("OBSERVED_TARGET_READBACK_VERIFIED")
|
||||
| Some("HALTED_ACCESSIBILITY_PERMISSION_NOT_GRANTED")
|
||||
| Some("HALTED_NO_FOCUSED_APPLICATION")
|
||||
));
|
||||
assert_eq!(receipt["permission_prompted"], false);
|
||||
assert_eq!(receipt["system_settings_opened"], false);
|
||||
assert_eq!(receipt["desktop_action_attempted"], false);
|
||||
assert_eq!(receipt["network_action"], false);
|
||||
assert_eq!(receipt["host_semantic_authority"], false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trust_prompt_request_is_rejected_without_receipt() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let mut gir = observation_gir();
|
||||
gir["inputs"]["HOST_SCOPE"]["trust_prompt"] = json!(true);
|
||||
let error = tcs_gir_runtime::run_gir(&gir, root.path()).expect_err("prompt must fail");
|
||||
assert_eq!(error.code, "TCS-E4001");
|
||||
assert!(!root.path().join("state/observation.json").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_mode_is_rejected_without_receipt() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let mut gir = observation_gir();
|
||||
gir["inputs"]["HOST_SCOPE"]["mode"] = json!("WRITE");
|
||||
let error = tcs_gir_runtime::run_gir(&gir, root.path()).expect_err("write must fail");
|
||||
assert_eq!(error.code, "TCS-E4001");
|
||||
assert!(!root.path().join("state/observation.json").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsupported_platform_is_rejected_without_receipt() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let mut gir = observation_gir();
|
||||
gir["inputs"]["HOST_SCOPE"]["platform"] = json!("LINUX");
|
||||
let error = tcs_gir_runtime::run_gir(&gir, root.path()).expect_err("platform must fail");
|
||||
assert_eq!(error.code, "TCS-E2101");
|
||||
assert!(!root.path().join("state/observation.json").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn outside_target_is_rejected_without_residue() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let mut gir = observation_gir();
|
||||
gir["exact_target"]["exact_path"] = json!("/tmp/TCS-STAGE12-SHOULD-NOT-WRITE.json");
|
||||
gir["receipt_plan"]["machine_path"] = json!("/tmp/TCS-STAGE12-SHOULD-NOT-WRITE.json");
|
||||
let error = tcs_gir_runtime::run_gir(&gir, root.path()).expect_err("outside must fail");
|
||||
assert_eq!(error.code, "TCS-E4002");
|
||||
assert!(!std::path::Path::new("/tmp/TCS-STAGE12-SHOULD-NOT-WRITE.json").exists());
|
||||
}
|
||||
|
|
@ -0,0 +1,259 @@
|
|||
use serde_json::{json, Value as JsonValue};
|
||||
use std::fs;
|
||||
|
||||
const SOURCE_SHA: &str = "d2bd9da062345bde9bfe8ca3b04719a81cba1f7432ca7866c59fe6fc62550672";
|
||||
const JOB_ID: &str = "SYNTHETIC-NATIVE-OPS-JOB-0001";
|
||||
const WORKER_ID: &str = "ZC001-MB-V1-LOCAL-OFFLINE-CANDIDATE-WORKER-NATIVE-OPS-001";
|
||||
|
||||
fn envelope(program_id: &str, operation: &str, target: &str, inputs: JsonValue) -> JsonValue {
|
||||
json!({
|
||||
"schema": "guanghu.gir/v1",
|
||||
"compiled_from": { "compiler_state": "TCS_COMPILER_GIR_EXECUTED" },
|
||||
"identity": { "program_id": program_id },
|
||||
"native_self_hosted": true,
|
||||
"inputs": inputs,
|
||||
"deterministic_action_graph": { "A1": { "operation": operation } },
|
||||
"exact_target": { "exact_path": target },
|
||||
"receipt_plan": { "machine_path": target }
|
||||
})
|
||||
}
|
||||
|
||||
fn write_canonical(root: &std::path::Path, relative: &str, value: &JsonValue) -> String {
|
||||
let path = root.join(relative);
|
||||
fs::create_dir_all(path.parent().expect("fixture parent")).expect("create fixture parent");
|
||||
let encoded = tcs_gir_runtime::canonical_json(value).expect("canonical fixture");
|
||||
fs::write(&path, encoded.as_bytes()).expect("write fixture");
|
||||
tcs_gir_runtime::sha256_hex(encoded.as_bytes())
|
||||
}
|
||||
|
||||
fn queue_fixture() -> JsonValue {
|
||||
json!({ "jobs": [{ "job_id": JOB_ID, "source_sha256": SOURCE_SHA, "state": "READY" }] })
|
||||
}
|
||||
|
||||
fn heartbeat_fixture() -> JsonValue {
|
||||
json!({ "safe_checkpoint": "REVISION_0", "sequence": 0, "state": "CLAIMED" })
|
||||
}
|
||||
|
||||
fn receipt_index_fixture() -> JsonValue {
|
||||
json!({ "receipts": [] })
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn atomic_claim_uses_exact_hash_atomic_rename_fsync_and_readback() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let path = "state/worker/queue.json";
|
||||
let hash = write_canonical(root.path(), path, &queue_fixture());
|
||||
let gir = envelope(
|
||||
"TCS-TEST-WORKER-ATOMIC-CLAIM",
|
||||
"WORKER.ATOMIC_QUEUE_CLAIM_WITH_FSYNC",
|
||||
path,
|
||||
json!({ "REQUEST": { "value": { "queue_state_sha256": hash, "job_id": JOB_ID, "worker_id": WORKER_ID, "claim_sequence": 1 } } }),
|
||||
);
|
||||
tcs_gir_runtime::run_gir(&gir, root.path()).expect("claim");
|
||||
let state: JsonValue =
|
||||
serde_json::from_slice(&fs::read(root.path().join(path)).expect("read queue"))
|
||||
.expect("queue json");
|
||||
assert_eq!(state["jobs"][0]["state"], "CLAIMED");
|
||||
assert_eq!(state["jobs"][0]["claim_sequence"], 1);
|
||||
assert!(!root
|
||||
.path()
|
||||
.join("state/worker/.queue.json.worker-txn.tmp")
|
||||
.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prior_receipt_readback_is_read_only_and_detects_source_mismatch() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let path = "state/worker/receipts.json";
|
||||
let index = json!({ "receipts": [{ "idempotency_key": "KEY-1", "source_sha256": SOURCE_SHA, "result": "CANDIDATE" }] });
|
||||
let hash = write_canonical(root.path(), path, &index);
|
||||
let original = fs::read(root.path().join(path)).expect("index bytes");
|
||||
let gir = envelope(
|
||||
"TCS-TEST-WORKER-PRIOR-READBACK",
|
||||
"WORKER.IDEMPOTENT_PRIOR_RECEIPT_READBACK",
|
||||
path,
|
||||
json!({ "REQUEST": { "value": { "receipt_index_sha256": hash, "idempotency_key": "KEY-1", "expected_source_sha256": SOURCE_SHA } } }),
|
||||
);
|
||||
tcs_gir_runtime::run_gir(&gir, root.path()).expect("readback");
|
||||
assert_eq!(
|
||||
fs::read(root.path().join(path)).expect("unchanged"),
|
||||
original
|
||||
);
|
||||
let mut mismatch = gir.clone();
|
||||
mismatch["inputs"]["REQUEST"]["value"]["expected_source_sha256"] = json!("0".repeat(64));
|
||||
let error = tcs_gir_runtime::run_gir(&mismatch, root.path()).expect_err("source mismatch");
|
||||
assert_eq!(error.code, "TCS-E3001");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn heartbeat_advances_exactly_one_and_rejects_rewind() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let path = "state/worker/heartbeat.json";
|
||||
let hash = write_canonical(root.path(), path, &heartbeat_fixture());
|
||||
let gir = envelope(
|
||||
"TCS-TEST-WORKER-HEARTBEAT",
|
||||
"WORKER.MONOTONIC_HEARTBEAT_TICK",
|
||||
path,
|
||||
json!({ "REQUEST": { "value": { "heartbeat_state_sha256": hash, "expected_sequence": 0, "worker_state": "CLAIMED", "safe_checkpoint_ref": "REVISION_0" } } }),
|
||||
);
|
||||
tcs_gir_runtime::run_gir(&gir, root.path()).expect("heartbeat");
|
||||
let bytes = fs::read(root.path().join(path)).expect("heartbeat read");
|
||||
let state: JsonValue = serde_json::from_slice(&bytes).expect("heartbeat json");
|
||||
assert_eq!(state["sequence"], 1);
|
||||
let mut rewind = gir.clone();
|
||||
rewind["inputs"]["REQUEST"]["value"]["heartbeat_state_sha256"] =
|
||||
json!(tcs_gir_runtime::sha256_hex(&bytes));
|
||||
let error = tcs_gir_runtime::run_gir(&rewind, root.path()).expect_err("rewind");
|
||||
assert_eq!(error.code, "TCS-E6001");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bounded_poll_stops_at_explicit_iteration_bound() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let gir = envelope(
|
||||
"TCS-TEST-WORKER-POLL",
|
||||
"WORKER.BOUNDED_RESIDENT_POLL_LOOP",
|
||||
"state/worker/poll-receipt.json",
|
||||
json!({ "REQUEST": { "value": { "exact_queue_root": "state/worker", "max_iterations": 3, "max_elapsed_ms": 100, "poll_interval_ms": 1, "stop_signal_path": "state/worker/STOP.tcs-signal", "capability_ceiling": "CANDIDATE_ONLY_NO_CORE_NO_NETWORK" } } }),
|
||||
);
|
||||
let output = tcs_gir_runtime::run_gir(&gir, root.path()).expect("poll");
|
||||
let receipt: JsonValue =
|
||||
serde_json::from_slice(&fs::read(output).expect("poll receipt")).expect("receipt json");
|
||||
assert_eq!(receipt["iterations"], 3);
|
||||
assert_eq!(receipt["stop_reason"], "MAX_ITERATIONS");
|
||||
assert_eq!(receipt["recursive_self_spawn"], false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn path_traversal_and_unknown_operation_fail_closed() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let outside = envelope(
|
||||
"TCS-TEST-WORKER-OUTSIDE",
|
||||
"WORKER.ATOMIC_QUEUE_CLAIM_WITH_FSYNC",
|
||||
"../outside.json",
|
||||
json!({ "REQUEST": { "value": { "queue_state_sha256": "0".repeat(64), "job_id": JOB_ID, "worker_id": WORKER_ID, "claim_sequence": 1 } } }),
|
||||
);
|
||||
assert_eq!(
|
||||
tcs_gir_runtime::run_gir(&outside, root.path())
|
||||
.expect_err("outside")
|
||||
.code,
|
||||
"TCS-E4002"
|
||||
);
|
||||
let unknown = envelope(
|
||||
"TCS-TEST-WORKER-UNKNOWN",
|
||||
"WORKER.UNKNOWN",
|
||||
"state/worker/unknown.json",
|
||||
json!({}),
|
||||
);
|
||||
assert_eq!(
|
||||
tcs_gir_runtime::run_gir(&unknown, root.path())
|
||||
.expect_err("unknown")
|
||||
.code,
|
||||
"TCS-E2101"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn crash_residual_stops_without_mutating_queue() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let path = "state/worker/queue.json";
|
||||
let hash = write_canonical(root.path(), path, &queue_fixture());
|
||||
let before = fs::read(root.path().join(path)).expect("queue before");
|
||||
fs::write(
|
||||
root.path().join("state/worker/.queue.json.worker-txn.tmp"),
|
||||
b"INTERRUPTED",
|
||||
)
|
||||
.expect("residual");
|
||||
let gir = envelope(
|
||||
"TCS-TEST-WORKER-CRASH-RESIDUAL",
|
||||
"WORKER.ATOMIC_QUEUE_CLAIM_WITH_FSYNC",
|
||||
path,
|
||||
json!({ "REQUEST": { "value": { "queue_state_sha256": hash, "job_id": JOB_ID, "worker_id": WORKER_ID, "claim_sequence": 1 } } }),
|
||||
);
|
||||
assert_eq!(
|
||||
tcs_gir_runtime::run_gir(&gir, root.path())
|
||||
.expect_err("residual must stop")
|
||||
.code,
|
||||
"TCS-E6001"
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read(root.path().join(path)).expect("queue after"),
|
||||
before
|
||||
);
|
||||
}
|
||||
|
||||
fn provider_gir(receipt_hash: &str, queue_hash: &str, heartbeat_hash: &str) -> JsonValue {
|
||||
json!({
|
||||
"schema": "guanghu.gir/v1",
|
||||
"compiled_from": { "compiler_state": "TCS_COMPILER_GIR_EXECUTED" },
|
||||
"identity": { "program_id": "TCS-PROVIDER-ZC001-MB-V1-RESIDENT-WORKER-NATIVE-OPS-EXACT-PATHS-0002" },
|
||||
"native_self_hosted": true,
|
||||
"inputs": {
|
||||
"RECEIPT_LOOKUP": { "value": { "receipt_index_path": "fixtures/receipts.json", "receipt_index_sha256": receipt_hash, "idempotency_key": JOB_ID, "expected_source_sha256": SOURCE_SHA } },
|
||||
"CLAIM_REQUEST": { "value": { "queue_path": "fixtures/queue.json", "queue_state_sha256": queue_hash, "job_id": JOB_ID, "worker_id": WORKER_ID, "claim_sequence": 1 } },
|
||||
"HEARTBEAT_REQUEST": { "value": { "heartbeat_path": "fixtures/heartbeat.json", "heartbeat_state_sha256": heartbeat_hash, "expected_sequence": 0, "worker_state": "CLAIMED", "safe_checkpoint_ref": "REVISION_0" } },
|
||||
"POLL_BOUND": { "value": { "exact_queue_root": "fixtures", "max_iterations": 2, "max_elapsed_ms": 100, "poll_interval_ms": 1, "stop_signal_path": "fixtures/STOP.tcs-signal", "capability_ceiling": "CANDIDATE_ONLY_NO_CORE_NO_NETWORK" } }
|
||||
},
|
||||
"deterministic_action_graph": {
|
||||
"A1": { "operation": "WORKER.IDEMPOTENT_PRIOR_RECEIPT_READBACK" },
|
||||
"A2": { "operation": "WORKER.ATOMIC_QUEUE_CLAIM_WITH_FSYNC" },
|
||||
"A3": { "operation": "WORKER.MONOTONIC_HEARTBEAT_TICK" },
|
||||
"A4": { "operation": "WORKER.BOUNDED_RESIDENT_POLL_LOOP" }
|
||||
},
|
||||
"exact_target": { "exact_path": "state/worker/provider-receipt.json" },
|
||||
"receipt_plan": { "machine_path": "state/worker/provider-receipt.json" }
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn full_provider_executes_once_then_returns_same_idempotent_receipt() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let receipt_hash = write_canonical(
|
||||
root.path(),
|
||||
"fixtures/receipts.json",
|
||||
&receipt_index_fixture(),
|
||||
);
|
||||
let queue_hash = write_canonical(root.path(), "fixtures/queue.json", &queue_fixture());
|
||||
let heartbeat_hash =
|
||||
write_canonical(root.path(), "fixtures/heartbeat.json", &heartbeat_fixture());
|
||||
let gir = provider_gir(&receipt_hash, &queue_hash, &heartbeat_hash);
|
||||
let output = tcs_gir_runtime::run_gir(&gir, root.path()).expect("provider first run");
|
||||
let first = fs::read(&output).expect("provider receipt");
|
||||
let receipt: JsonValue = serde_json::from_slice(&first).expect("provider json");
|
||||
assert_eq!(
|
||||
receipt["operations"].as_array().expect("operations").len(),
|
||||
4
|
||||
);
|
||||
assert_eq!(receipt["core_write"], false);
|
||||
assert_eq!(receipt["network"], false);
|
||||
assert_eq!(receipt["host_semantic_authority"], false);
|
||||
let queue: JsonValue =
|
||||
serde_json::from_slice(&fs::read(root.path().join("fixtures/queue.json")).expect("queue"))
|
||||
.expect("queue json");
|
||||
assert_eq!(queue["jobs"][0]["state"], "CLAIMED");
|
||||
let heartbeat: JsonValue = serde_json::from_slice(
|
||||
&fs::read(root.path().join("fixtures/heartbeat.json")).expect("heartbeat"),
|
||||
)
|
||||
.expect("heartbeat json");
|
||||
assert_eq!(heartbeat["sequence"], 1);
|
||||
let second_output =
|
||||
tcs_gir_runtime::run_gir(&gir, root.path()).expect("provider idempotent run");
|
||||
assert_eq!(second_output, output);
|
||||
assert_eq!(fs::read(output).expect("same receipt"), first);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn provider_without_exact_object_paths_fails_before_writes() {
|
||||
let root = tempfile::tempdir().expect("root");
|
||||
let mut gir = provider_gir("0", "0", "0");
|
||||
gir["inputs"]["RECEIPT_LOOKUP"]["value"]
|
||||
.as_object_mut()
|
||||
.expect("lookup")
|
||||
.remove("receipt_index_path");
|
||||
let error = tcs_gir_runtime::run_gir(&gir, root.path()).expect_err("missing path must fail");
|
||||
assert_eq!(error.code, "TCS-E3002");
|
||||
assert!(!root
|
||||
.path()
|
||||
.join("state/worker/provider-receipt.json")
|
||||
.exists());
|
||||
}
|
||||
Loading…
Reference in a new issue