Skip to content

Commit 9747234

Browse files
committed
test(contracts): resolve F-05 pin v0.1.0 conformance
1 parent f76a710 commit 9747234

15 files changed

Lines changed: 569 additions & 10 deletions

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ Dockerfile text eol=lf
1010
*.md text eol=lf
1111
*.toml text eol=lf
1212
*.ps1 text eol=crlf
13+
tests/contracts/cas-contracts/v0.1.0/*.json -text

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ dependencies = [
2222
[project.optional-dependencies]
2323
dev = [
2424
"httpx>=0.28.0",
25+
"jsonschema>=4.23.0",
2526
"mypy>=1.14.0",
2627
"pytest>=8.3.0",
2728
"pytest-cov>=6.0.0",

src/cas_reference_product/models.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,42 @@
11
from datetime import datetime
2-
from typing import Annotated, Literal
2+
from typing import Annotated, Any, Literal
33

4-
from pydantic import BaseModel, ConfigDict, Field, field_validator
4+
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
5+
6+
7+
def reject_explicit_null(data: Any, fields: tuple[str, ...]) -> Any:
8+
if isinstance(data, dict):
9+
null_fields = [field for field in fields if field in data and data[field] is None]
10+
if null_fields:
11+
raise ValueError(f"{', '.join(null_fields)} must be omitted instead of null")
12+
return data
513

614

715
class Actor(BaseModel):
816
model_config = ConfigDict(extra="forbid")
917
id: str = Field(min_length=1, max_length=256)
1018
type: Literal["human", "agent", "service", "workflow"]
11-
displayName: str | None = Field(default=None, min_length=1, max_length=256)
19+
displayName: str | None = Field(
20+
default=None, min_length=1, max_length=256, exclude_if=lambda value: value is None
21+
)
22+
23+
@model_validator(mode="before")
24+
@classmethod
25+
def reject_null_display_name(cls, data: Any) -> Any:
26+
return reject_explicit_null(data, ("displayName",))
1227

1328

1429
class TraceContext(BaseModel):
1530
model_config = ConfigDict(extra="forbid")
1631
traceparent: str = Field(pattern=r"^[\da-f]{2}-[\da-f]{32}-[\da-f]{16}-[\da-f]{2}$")
17-
tracestate: str | None = Field(default=None, max_length=512)
32+
tracestate: str | None = Field(
33+
default=None, max_length=512, exclude_if=lambda value: value is None
34+
)
35+
36+
@model_validator(mode="before")
37+
@classmethod
38+
def reject_null_tracestate(cls, data: Any) -> Any:
39+
return reject_explicit_null(data, ("tracestate",))
1840

1941

2042
class LifecycleMetadata(BaseModel):
@@ -51,7 +73,14 @@ class RunEvent(LifecycleMetadata):
5173
eventType: str = Field(min_length=1, max_length=128)
5274
sequence: int = Field(ge=0)
5375
status: Literal["queued", "running", "succeeded", "failed", "cancelled"]
54-
message: str | None = Field(default=None, max_length=5_000)
76+
message: str | None = Field(
77+
default=None, max_length=5_000, exclude_if=lambda value: value is None
78+
)
79+
80+
@model_validator(mode="before")
81+
@classmethod
82+
def reject_null_message(cls, data: Any) -> Any:
83+
return reject_explicit_null(data, ("message",))
5584

5685

5786
class WorkflowResult(BaseModel):

src/cas_reference_product/workflow.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,17 +104,17 @@ def _event(
104104
status: RunStatus,
105105
message: str,
106106
) -> RunEvent:
107+
trace_context = {"traceparent": current_traceparent(envelope.traceContext.traceparent)}
108+
if envelope.traceContext.tracestate is not None:
109+
trace_context["tracestate"] = envelope.traceContext.tracestate
107110
return RunEvent(
108111
correlationId=envelope.correlationId,
109112
promptId=envelope.promptId,
110113
runId=envelope.runId,
111114
repo=self._repository,
112115
actor=Actor(id="cas-reference-workflow", type="workflow"),
113116
timestamp=self._clock(),
114-
traceContext=TraceContext(
115-
traceparent=current_traceparent(envelope.traceContext.traceparent),
116-
tracestate=envelope.traceContext.tracestate,
117-
),
117+
traceContext=TraceContext.model_validate(trace_context),
118118
eventType=event_type,
119119
sequence=sequence,
120120
status=status,
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://schemas.coding-autopilot.dev/v0.1/artifact-manifest.schema.json",
4+
"title": "ArtifactManifest",
5+
"type": "object",
6+
"allOf": [
7+
{
8+
"$ref": "common.schema.json#/$defs/lifecycleMetadata"
9+
},
10+
{
11+
"type": "object",
12+
"required": [
13+
"kind",
14+
"artifacts"
15+
],
16+
"properties": {
17+
"kind": {
18+
"const": "ArtifactManifest"
19+
},
20+
"artifacts": {
21+
"type": "array",
22+
"minItems": 1,
23+
"items": {
24+
"$ref": "common.schema.json#/$defs/evidence"
25+
}
26+
}
27+
}
28+
}
29+
],
30+
"unevaluatedProperties": false
31+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://schemas.coding-autopilot.dev/v0.1/common.schema.json",
4+
"title": "CAS Common Definitions",
5+
"$defs": {
6+
"actor": {
7+
"type": "object",
8+
"additionalProperties": false,
9+
"required": ["id", "type"],
10+
"properties": {
11+
"id": { "type": "string", "minLength": 1, "maxLength": 256 },
12+
"type": {
13+
"type": "string",
14+
"enum": ["human", "agent", "service", "workflow"]
15+
},
16+
"displayName": { "type": "string", "minLength": 1, "maxLength": 256 }
17+
}
18+
},
19+
"traceContext": {
20+
"type": "object",
21+
"additionalProperties": false,
22+
"required": ["traceparent"],
23+
"properties": {
24+
"traceparent": {
25+
"type": "string",
26+
"pattern": "^[\\da-f]{2}-[\\da-f]{32}-[\\da-f]{16}-[\\da-f]{2}$"
27+
},
28+
"tracestate": { "type": "string", "maxLength": 512 }
29+
}
30+
},
31+
"lifecycleMetadata": {
32+
"type": "object",
33+
"required": [
34+
"correlationId",
35+
"promptId",
36+
"runId",
37+
"repo",
38+
"actor",
39+
"timestamp",
40+
"schemaVersion",
41+
"traceContext"
42+
],
43+
"properties": {
44+
"correlationId": { "type": "string", "minLength": 1, "maxLength": 128 },
45+
"promptId": { "type": "string", "minLength": 1, "maxLength": 128 },
46+
"runId": { "type": "string", "minLength": 1, "maxLength": 128 },
47+
"repo": {
48+
"type": "string",
49+
"pattern": "^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$"
50+
},
51+
"actor": { "$ref": "#/$defs/actor" },
52+
"timestamp": { "type": "string", "format": "date-time" },
53+
"schemaVersion": { "const": "0.1.0" },
54+
"traceContext": { "$ref": "#/$defs/traceContext" }
55+
}
56+
},
57+
"evidence": {
58+
"type": "object",
59+
"additionalProperties": false,
60+
"required": ["kind", "uri"],
61+
"properties": {
62+
"kind": { "type": "string", "minLength": 1, "maxLength": 64 },
63+
"uri": { "type": "string", "format": "uri" },
64+
"sha256": { "type": "string", "pattern": "^[\\da-f]{64}$" }
65+
}
66+
}
67+
}
68+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://schemas.coding-autopilot.dev/v0.1/evaluation-result.schema.json",
4+
"title": "EvaluationResult",
5+
"type": "object",
6+
"allOf": [
7+
{
8+
"$ref": "common.schema.json#/$defs/lifecycleMetadata"
9+
},
10+
{
11+
"type": "object",
12+
"required": [
13+
"kind",
14+
"evaluator",
15+
"outcome",
16+
"metrics"
17+
],
18+
"properties": {
19+
"kind": {
20+
"const": "EvaluationResult"
21+
},
22+
"evaluator": {
23+
"type": "string",
24+
"minLength": 1,
25+
"maxLength": 256
26+
},
27+
"outcome": {
28+
"enum": [
29+
"passed",
30+
"failed",
31+
"inconclusive"
32+
]
33+
},
34+
"metrics": {
35+
"type": "object",
36+
"minProperties": 1,
37+
"additionalProperties": {
38+
"type": "number"
39+
}
40+
}
41+
}
42+
}
43+
],
44+
"unevaluatedProperties": false
45+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"version": "0.1.0",
3+
"schemas": [
4+
{
5+
"id": "https://schemas.coding-autopilot.dev/v0.1/artifact-manifest.schema.json",
6+
"path": "artifact-manifest.schema.json",
7+
"sha256": "6c2192fb6ca79843361695f3dccd5ebf1dda8ce320c974db2630b0a2b78705bd"
8+
},
9+
{
10+
"id": "https://schemas.coding-autopilot.dev/v0.1/common.schema.json",
11+
"path": "common.schema.json",
12+
"sha256": "c7ce72a6f5da8394e48f2421820588a8142546962e05152997bd1e6ced994928"
13+
},
14+
{
15+
"id": "https://schemas.coding-autopilot.dev/v0.1/evaluation-result.schema.json",
16+
"path": "evaluation-result.schema.json",
17+
"sha256": "12e8019f858dc0cda80ac8994ca1251a9a229a8642b05706227bd9c995c5799a"
18+
},
19+
{
20+
"id": "https://schemas.coding-autopilot.dev/v0.1/policy-decision.schema.json",
21+
"path": "policy-decision.schema.json",
22+
"sha256": "9cf259d405664560b30b7afd25d08d888337fd9a81a6a388ceeb36cbf7edcc33"
23+
},
24+
{
25+
"id": "https://schemas.coding-autopilot.dev/v0.1/prompt-envelope.schema.json",
26+
"path": "prompt-envelope.schema.json",
27+
"sha256": "58a991862031f40c2ffcc073743776d05206684534fac2c20c67c274fbf05c84"
28+
},
29+
{
30+
"id": "https://schemas.coding-autopilot.dev/v0.1/run-event.schema.json",
31+
"path": "run-event.schema.json",
32+
"sha256": "1bcaee2ff546439ea81d64d57dcb51cd9f57dd790fe300fd90e251823e27a36f"
33+
},
34+
{
35+
"id": "https://schemas.coding-autopilot.dev/v0.1/verification-result.schema.json",
36+
"path": "verification-result.schema.json",
37+
"sha256": "aeff3d41eeb99b3017b460c2a2a8d07b4e1c828830b72853d5f41d93d6abe012"
38+
},
39+
{
40+
"id": "https://schemas.coding-autopilot.dev/v0.1/work-request.schema.json",
41+
"path": "work-request.schema.json",
42+
"sha256": "543e1dd2313cff2a1ebeb1470db3085b89c3933694231eb5b4798096f147e4a7"
43+
}
44+
]
45+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://schemas.coding-autopilot.dev/v0.1/policy-decision.schema.json",
4+
"title": "PolicyDecision",
5+
"type": "object",
6+
"allOf": [
7+
{
8+
"$ref": "common.schema.json#/$defs/lifecycleMetadata"
9+
},
10+
{
11+
"type": "object",
12+
"required": [
13+
"kind",
14+
"decision",
15+
"policyVersion",
16+
"reasons"
17+
],
18+
"properties": {
19+
"kind": {
20+
"const": "PolicyDecision"
21+
},
22+
"decision": {
23+
"enum": [
24+
"allow",
25+
"deny",
26+
"require-approval"
27+
]
28+
},
29+
"policyVersion": {
30+
"type": "string",
31+
"minLength": 1,
32+
"maxLength": 64
33+
},
34+
"reasons": {
35+
"type": "array",
36+
"minItems": 1,
37+
"items": {
38+
"type": "string",
39+
"minLength": 1,
40+
"maxLength": 1000
41+
}
42+
}
43+
}
44+
}
45+
],
46+
"unevaluatedProperties": false
47+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://schemas.coding-autopilot.dev/v0.1/prompt-envelope.schema.json",
4+
"title": "PromptEnvelope",
5+
"type": "object",
6+
"allOf": [
7+
{
8+
"$ref": "common.schema.json#/$defs/lifecycleMetadata"
9+
},
10+
{
11+
"type": "object",
12+
"required": [
13+
"kind",
14+
"intent",
15+
"prompt"
16+
],
17+
"properties": {
18+
"kind": {
19+
"const": "PromptEnvelope"
20+
},
21+
"intent": {
22+
"type": "string",
23+
"minLength": 1,
24+
"maxLength": 256
25+
},
26+
"prompt": {
27+
"type": "string",
28+
"minLength": 1,
29+
"maxLength": 50000
30+
},
31+
"constraints": {
32+
"type": "array",
33+
"items": {
34+
"type": "string",
35+
"minLength": 1,
36+
"maxLength": 1000
37+
},
38+
"uniqueItems": true
39+
}
40+
}
41+
}
42+
],
43+
"unevaluatedProperties": false
44+
}

0 commit comments

Comments
 (0)