CultNet: witness element types carry ids; peers and fixtures follow
CultWitnessContractPin, CultWitnessArtifactEntry and CultWitnessTimingEntry get an id slot. The JSON schema contract and the Python schema copy gain an optional id per element, and the Python and TypeScript fixtures carry and assert ids. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
ded5436569
commit
09dabd38c5
5 changed files with 27 additions and 6 deletions
|
|
@ -59,6 +59,7 @@
|
|||
],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": { "type": "string", "minLength": 1 },
|
||||
"role": { "type": "string", "minLength": 1 },
|
||||
"schemaId": { "type": "string", "minLength": 1 },
|
||||
"schemaVersion": { "type": "string", "minLength": 1 },
|
||||
|
|
@ -74,6 +75,7 @@
|
|||
],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": { "type": "string", "minLength": 1 },
|
||||
"role": { "type": "string", "minLength": 1 },
|
||||
"uri": { "type": "string", "minLength": 1 },
|
||||
"mediaType": { "type": "string", "minLength": 1 },
|
||||
|
|
@ -92,6 +94,7 @@
|
|||
],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": { "type": "string", "minLength": 1 },
|
||||
"stage": { "type": "string", "minLength": 1 },
|
||||
"startedAt": { "type": "string", "minLength": 1 },
|
||||
"completedAt": { "type": "string", "minLength": 1 },
|
||||
|
|
|
|||
|
|
@ -1316,6 +1316,7 @@ def witness_artifact_bundle_schema_json() -> str:
|
|||
"required": ["role", "schemaId"],
|
||||
"additionalProperties": False,
|
||||
"properties": {
|
||||
"id": {"type": "string", "minLength": 1},
|
||||
"role": {"type": "string", "minLength": 1},
|
||||
"schemaId": {"type": "string", "minLength": 1},
|
||||
"schemaVersion": {"type": "string", "minLength": 1},
|
||||
|
|
@ -1327,6 +1328,7 @@ def witness_artifact_bundle_schema_json() -> str:
|
|||
"required": ["role", "uri", "mediaType"],
|
||||
"additionalProperties": False,
|
||||
"properties": {
|
||||
"id": {"type": "string", "minLength": 1},
|
||||
"role": {"type": "string", "minLength": 1},
|
||||
"uri": {"type": "string", "minLength": 1},
|
||||
"mediaType": {"type": "string", "minLength": 1},
|
||||
|
|
@ -1340,6 +1342,7 @@ def witness_artifact_bundle_schema_json() -> str:
|
|||
"required": ["stage", "startedAt", "completedAt", "latencyMs"],
|
||||
"additionalProperties": False,
|
||||
"properties": {
|
||||
"id": {"type": "string", "minLength": 1},
|
||||
"stage": {"type": "string", "minLength": 1},
|
||||
"startedAt": {"type": "string", "minLength": 1},
|
||||
"completedAt": {"type": "string", "minLength": 1},
|
||||
|
|
|
|||
|
|
@ -1870,9 +1870,9 @@ class CultNetTests(unittest.TestCase):
|
|||
witness_kind="interop-proof",
|
||||
captured_at="2026-06-13T00:00:03Z",
|
||||
subject={"documentType": "cultnet.interop-note", "subjectId": "note:python"},
|
||||
contracts=[{"role": "payload", "schemaId": "schema-a"}],
|
||||
artifacts=[{"role": "log", "uri": "cultcache://bundle-1/log", "mediaType": "text/plain"}],
|
||||
timing_witnesses=[{"stage": "roundtrip", "startedAt": "2026-06-13T00:00:03Z", "completedAt": "2026-06-13T00:00:04Z", "latencyMs": 1.0}],
|
||||
contracts=[{"id": "c0e1a2b3c4d5", "role": "payload", "schemaId": "schema-a"}],
|
||||
artifacts=[{"id": "a0e1a2b3c4d5", "role": "log", "uri": "cultcache://bundle-1/log", "mediaType": "text/plain"}],
|
||||
timing_witnesses=[{"id": "e0e1a2b3c4d5", "stage": "roundtrip", "startedAt": "2026-06-13T00:00:03Z", "completedAt": "2026-06-13T00:00:04Z", "latencyMs": 1.0}],
|
||||
provenance={"pipelineId": "interop", "runId": "run-1", "runtimeId": "python-test"},
|
||||
)
|
||||
payload = encode_witness_artifact_bundle_payload(bundle)
|
||||
|
|
@ -1888,6 +1888,8 @@ class CultNetTests(unittest.TestCase):
|
|||
self.assertEqual(slots[2], "2026-06-13T00:00:03Z")
|
||||
self.assertEqual(slots[3]["subjectId"], "note:python")
|
||||
self.assertEqual(slots[4][0]["schemaId"], "schema-a")
|
||||
self.assertEqual([slots[4][0]["id"], slots[5][0]["id"], slots[6][0]["id"]], ["c0e1a2b3c4d5", "a0e1a2b3c4d5", "e0e1a2b3c4d5"])
|
||||
self.assertEqual(typed_decoded.contracts[0]["id"], "c0e1a2b3c4d5")
|
||||
self.assertEqual(slots[5][0]["uri"], "cultcache://bundle-1/log")
|
||||
self.assertEqual(slots[6][0]["latencyMs"], 1.0)
|
||||
self.assertEqual(slots[7]["runtimeId"], "python-test")
|
||||
|
|
|
|||
|
|
@ -1232,9 +1232,9 @@ test("CultNet TS/Rust/C#/Python peers discover each other and exchange raw state
|
|||
schemaVersion: INTEROP_SCHEMA_VERSION,
|
||||
schemaId: interopNoteSchemaId,
|
||||
},
|
||||
[{ role: "payload", schemaId: interopNoteSchemaId, schemaVersion: INTEROP_SCHEMA_VERSION }],
|
||||
[{ role: "log", uri: "cultcache://bundle:ts-python-witness/log", mediaType: "text/plain" }],
|
||||
[{ stage: "roundtrip", startedAt: "2026-06-13T00:00:03Z", completedAt: "2026-06-13T00:00:04Z", latencyMs: 1 }],
|
||||
[{ id: "c0e1a2b3c4d5", role: "payload", schemaId: interopNoteSchemaId, schemaVersion: INTEROP_SCHEMA_VERSION }],
|
||||
[{ id: "a0e1a2b3c4d5", role: "log", uri: "cultcache://bundle:ts-python-witness/log", mediaType: "text/plain" }],
|
||||
[{ id: "e0e1a2b3c4d5", stage: "roundtrip", startedAt: "2026-06-13T00:00:03Z", completedAt: "2026-06-13T00:00:04Z", latencyMs: 1 }],
|
||||
{ pipelineId: "interop", runId: "ts-python-witness", runtimeId: "ts-witness", agentId: "ts-agent" },
|
||||
]),
|
||||
sourceRuntimeId: "ts-witness",
|
||||
|
|
@ -1252,6 +1252,7 @@ test("CultNet TS/Rust/C#/Python peers discover each other and exchange raw state
|
|||
assert.equal(witnessSlots[1], "interop-proof");
|
||||
assert.equal(witnessSlots[3].subjectId, "note:python-peer");
|
||||
assert.equal(witnessSlots[7].runtimeId, "ts-witness");
|
||||
assert.deepEqual([witnessSlots[4][0].id, witnessSlots[5][0].id, witnessSlots[6][0].id], ["c0e1a2b3c4d5", "a0e1a2b3c4d5", "e0e1a2b3c4d5"], "element ids cross TS to Python and back");
|
||||
|
||||
const expectedPeers = ["csharp-peer", "python-peer", "rust-peer", "ts-peer"];
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,10 @@ namespace GameCult.Networking
|
|||
[MessagePackObject]
|
||||
public sealed class CultWitnessContractPin
|
||||
{
|
||||
[Key(4)]
|
||||
[CultElementId]
|
||||
public string Id { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the contract role inside the bundle.
|
||||
/// </summary>
|
||||
|
|
@ -135,6 +139,10 @@ namespace GameCult.Networking
|
|||
[MessagePackObject]
|
||||
public sealed class CultWitnessArtifactEntry
|
||||
{
|
||||
[Key(6)]
|
||||
[CultElementId]
|
||||
public string Id { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the artifact role inside the witness bundle.
|
||||
/// </summary>
|
||||
|
|
@ -178,6 +186,10 @@ namespace GameCult.Networking
|
|||
[MessagePackObject]
|
||||
public sealed class CultWitnessTimingEntry
|
||||
{
|
||||
[Key(5)]
|
||||
[CultElementId]
|
||||
public string Id { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pipeline stage name.
|
||||
/// </summary>
|
||||
|
|
|
|||
Loading…
Reference in a new issue