Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 173 additions & 0 deletions docs/services/openapi-oracle.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
{
"components": {
"schemas": {
"HTTPValidationError": {
"properties": {
"detail": {
"items": {
"$ref": "#/components/schemas/ValidationError"
},
"title": "Detail",
"type": "array"
}
},
"title": "HTTPValidationError",
"type": "object"
},
"ValidationError": {
"properties": {
"ctx": {
"title": "Context",
"type": "object"
},
"input": {
"title": "Input"
},
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"title": "Location",
"type": "array"
},
"msg": {
"title": "Message",
"type": "string"
},
"type": {
"title": "Error Type",
"type": "string"
}
},
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError",
"type": "object"
},
"VerifyRequest": {
"description": "One model instance to check: Turtle text + whether to run cross-record checks.",
"properties": {
"check_conflicts": {
"default": true,
"title": "Check Conflicts",
"type": "boolean"
},
"turtle": {
"title": "Turtle",
"type": "string"
}
},
"required": [
"turtle"
],
"title": "VerifyRequest",
"type": "object"
}
}
},
"info": {
"description": "Model-instance conformance against the cds model family: verdict + granular tri-severity findings (rule/focus/message) for remediation. Verification only \u2014 validation (fitness for purpose) is human.",
"title": "cds conformance oracle",
"version": "0.1.0"
},
"openapi": "3.1.0",
"paths": {
"/healthz": {
"get": {
"operationId": "healthz_healthz_get",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": {
"type": "string"
},
"title": "Response Healthz Healthz Get",
"type": "object"
}
}
},
"description": "Successful Response"
}
},
"summary": "Healthz"
}
},
"/rules": {
"get": {
"operationId": "list_rules_rules_get",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": {
"items": {
"type": "string"
},
"type": "array"
},
"title": "Response List Rules Rules Get",
"type": "object"
}
}
},
"description": "Successful Response"
}
},
"summary": "List Rules"
}
},
"/verify": {
"post": {
"operationId": "verify_instance_verify_post",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/VerifyRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": true,
"title": "Response Verify Instance Verify Post",
"type": "object"
}
}
},
"description": "Successful Response"
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
"description": "Validation Error"
}
},
"summary": "Verify Instance"
}
}
}
}
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ interop = [
]

mcp = ["mcp>=1.0"]
facilitator = ["cds[mcp]", "anthropic>=0.40", "instructor>=1.0"]
oracle = ["fastapi>=0.110", "uvicorn>=0.29"]
facilitator = ["cds[mcp]", "fastapi>=0.110", "uvicorn>=0.29", "anthropic>=0.40", "instructor>=1.0"]
selfhosted-llm = ["vllm>=0.6", "xgrammar>=0.1"]
app = ["cds[facilitator]", "voila>=0.5", "ipywidgets>=8", "jupyterhub>=5", "dockerspawner>=13", "oauthenticator>=17"]
store = ["pyoxigraph>=0.4", "oxrdflib>=0.4"]
Expand All @@ -47,6 +48,7 @@ store = ["pyoxigraph>=0.4", "oxrdflib>=0.4"]
cds = "cds.core.cli:main"
cds-mcp = "cds.mcp.server:main"
cds-serve = "cds.facilitator.server:main"
cds-oracle = "cds.oracle.app:main"

[tool.hatch.metadata]
allow-direct-references = true
Expand Down
62 changes: 62 additions & 0 deletions src/cds/contracts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Cross-component interface contracts — the modularity keystone (spec §6.0/§8.3).

Six components, each a would-be distribution, joined only by the typed seams in this module
(which imports ONLY ``cds.core`` — enforced by ``tests/unit/test_factoring.py``):

1. the modeling-family package (``cds.core`` + ``cds.stages`` + CLI),
2. the conformance oracle service (``cds.oracle`` — verification, "build it right"),
3. the facilitator service (``cds.facilitator`` — correct-by-construction authoring),
4. the model datastore service (contract here; Flexo MMS target, ROADMAP T6),
5. the MCP tool server (``cds.mcp`` — composes 1 + 2 + 4 behind the K1 whitelist),
6. the web app (``cds.app`` — drives the facilitator).

The rule: any component can move out-of-process without changing its consumers — a consumer
holds a Protocol from here, never a sibling import.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Protocol, runtime_checkable

from rdflib import Graph

from cds.core.flexo import FlexoBackend
from cds.core.verify import VerifyResult, verify

__all__ = ["ConformanceOracle", "InProcessOracle", "ModelStore"]


@runtime_checkable
class ConformanceOracle(Protocol):
"""The verification seam ("build it right" — machine, never fitness-for-purpose).

A model *instance* graph goes in; a tri-severity :class:`~cds.core.verify.VerifyResult`
comes out, each finding carrying the named ``rule``, the ``focus`` node, and an authored
``message`` — the raw material of remediation. Stateless by contract.
"""

def check(self, data: Graph, *, check_conflicts: bool = True) -> VerifyResult: ...


@dataclass(frozen=True)
class InProcessOracle:
"""Reference oracle: ``cds.core.verify`` in-process.

DEFERRED (spec §11 D8): an HTTP client implementation consuming the ``cds-oracle``
service's ``POST /verify`` — trigger: an out-of-process consumer (the P5/P6 app tier).
It drops in behind this same Protocol without touching any consumer.
"""

def check(self, data: Graph, *, check_conflicts: bool = True) -> VerifyResult:
return verify(data, check_conflicts=check_conflicts)


# The datastore seam (spec §6.0 C4, §8.3): per-branch model-instance storage.
#
# ``cds.core.flexo.FlexoBackend`` — ``commit(*, branch, graph)`` / ``read_graph(*, branch)`` —
# already IS that contract; re-exported under the component name rather than duplicated.
# Implementations today: ``InMemoryFlexoBackend`` (tests) and the git-TTL project layout (the
# durable record, ADR-7a; P2's session staging binds it). DEFERRED (spec §11 D9): the
# Flexo-MMS-backed store service via ``FlexoHttpClient`` — trigger: ROADMAP T6 acceptance.
ModelStore = FlexoBackend
11 changes: 8 additions & 3 deletions src/cds/mcp/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from rdflib import Graph

from cds.contracts import ConformanceOracle, InProcessOracle
from cds.core import compile as compile_mod
from cds.core import explain as explain_mod
from cds.core.authoring import (
Expand Down Expand Up @@ -47,7 +48,6 @@
Severity,
VerifyResult,
Waiver,
verify,
waiver_to_graph,
)
from cds.core.workspace import Project
Expand Down Expand Up @@ -85,6 +85,11 @@ def _staging_graph(project: Project) -> Graph:
return project_graph(project)


# The verification seam (spec §8.3): tools consult the oracle via its contract, so the check
# can move out-of-process (cds-oracle service, D8) without touching this module.
_ORACLE: ConformanceOracle = InProcessOracle()


# ---------------------------------------------------------------------------- read / preview


Expand All @@ -105,7 +110,7 @@ def cds_show(project: Project, kind: str, slug: str) -> list[str] | None:

@_tool("cds_verify", "Verify the staging graph — tri-severity findings; preview only.")
def cds_verify(project: Project, check_conflicts: bool = True) -> VerifyResult:
return verify(_staging_graph(project), check_conflicts=check_conflicts)
return _ORACLE.check(_staging_graph(project), check_conflicts=check_conflicts)


@_tool("cds_compile", "Compile the staging graph to a Markdown brief; preview only.")
Expand Down Expand Up @@ -216,7 +221,7 @@ def _append_waiver(project: Project, addition: Graph) -> None:
writes=True)
def cds_waive(project: Project, waiver_id: str, rule: str, reason: str,
focus: str | None = None, by: str | None = None) -> str:
result = verify(_staging_graph(project), check_conflicts=True)
result = _ORACLE.check(_staging_graph(project), check_conflicts=True)
refuse_if_waives_t1(result.findings, rule=rule, focus=focus)
w = Waiver(id=waiver_id, rule=rule, reason=reason, focus=focus, by=by)
_append_waiver(project, waiver_to_graph(w))
Expand Down
7 changes: 7 additions & 0 deletions src/cds/oracle/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""cds.oracle — the model-conformance oracle service (spec §6.0 C2).

Stateless verification: a model *instance* (Turtle) in, a conformance verdict + granular
tri-severity findings out. "Build it right" is this service's whole job; "build the right
thing" (validation) belongs to the human commit gate. Surface: exactly ``POST /verify``,
``GET /rules``, ``GET /healthz``.
"""
Loading
Loading