simplest categorical addition

This commit is contained in:
lda
2026-05-16 17:53:42 +07:00 Verified
parent 1140a7ccdd
commit 7dcfad92c1
6 changed files with 42 additions and 3 deletions
+3 -2
View File
@@ -85,7 +85,8 @@ how did the original provider happen to expose this thing?
### Wrapper / Adapter Artifact
A wrapper artifact is a saved reusable bridge from a raw capability to a
workflow capability.
workflow capability. In storage it is not a second artifact family: it is a
`WorkflowArtifact` with `kind="wrapper"`.
Examples:
@@ -264,10 +265,10 @@ Today:
- `wf.std` owns local reusable workflow node specs
- `wf.mcp` owns workflow-facing MCP runtime helpers
- discovered upstream tools can already become workflow node specs
- saved artifacts can be tagged with `kind="workflow"` or `kind="wrapper"`
Not yet implemented:
- a saved wrapper artifact model
- a direct public tool for calling arbitrary workflow node specs for authoring
tests
- per-outcome output schemas
+2
View File
@@ -5,6 +5,7 @@ from .catalog import (
)
from .factory import create_workflow_artifact_from_plan
from .models import (
ArtifactKind,
AvailableCapability,
AvailableSource,
DependencyDiagnostic,
@@ -19,6 +20,7 @@ from .validation import validate_deployment_dependencies
__all__ = [
"AvailableCapability",
"ArtifactKind",
"AvailableSource",
"DependencyDiagnostic",
"DiagnosticSeverity",
+3 -1
View File
@@ -4,7 +4,7 @@ from collections.abc import Mapping
from wf_core import Workflow
from .models import JsonObject, RequiredCapability, WorkflowArtifact
from .models import ArtifactKind, JsonObject, RequiredCapability, WorkflowArtifact
def create_workflow_artifact_from_plan(
@@ -14,6 +14,7 @@ def create_workflow_artifact_from_plan(
title: str,
plan: JsonObject,
outcomes: tuple[str, ...],
kind: ArtifactKind = "workflow",
description: str | None = None,
required_capabilities: Mapping[str, RequiredCapability] | None = None,
created_from_catalog_version: str | None = None,
@@ -24,6 +25,7 @@ def create_workflow_artifact_from_plan(
id=artifact_id,
version=version,
title=title,
kind=kind,
description=description,
input_schema=_required_object_field(plan, "input_schema"),
output_schema=_required_object_field(plan, "output_schema"),
+2
View File
@@ -6,6 +6,7 @@ from typing import Any, Literal
from pydantic import BaseModel, Field
JsonObject = dict[str, Any]
ArtifactKind = Literal["workflow", "wrapper"]
class DriftPolicy(StrEnum):
@@ -71,6 +72,7 @@ class WorkflowArtifact(BaseModel):
id: str
version: int = Field(ge=1)
title: str
kind: ArtifactKind = "workflow"
description: str | None = None
input_schema: JsonObject
output_schema: JsonObject
+14
View File
@@ -22,6 +22,7 @@ def test_create_workflow_artifact_from_plan_derives_boundary_schemas() -> None:
)
assert artifact.id == "echo"
assert artifact.kind == "workflow"
assert artifact.version == 1
assert artifact.title == "Echo"
assert artifact.input_schema["properties"]["text"]["type"] == "string"
@@ -32,6 +33,19 @@ def test_create_workflow_artifact_from_plan_derives_boundary_schemas() -> None:
assert artifact.created_from_catalog_version == "catalog-1"
def test_create_workflow_artifact_from_plan_accepts_wrapper_kind() -> None:
artifact = create_workflow_artifact_from_plan(
artifact_id="normalize_status",
version=1,
title="Normalize Status",
plan=_plan(),
outcomes=("done",),
kind="wrapper",
)
assert artifact.kind == "wrapper"
def test_create_workflow_artifact_from_plan_rejects_missing_boundary_schema() -> None:
plan = _plan()
plan.pop("output_schema")
+18
View File
@@ -38,6 +38,7 @@ def test_workflow_artifact_serializes_required_capability_contract() -> None:
dumped = artifact.model_dump(mode="json")
assert dumped["id"] == "summarize_docs"
assert dumped["kind"] == "workflow"
assert dumped["version"] == 1
assert dumped["outcomes"] == ["done", "failed"]
required = dumped["required_capabilities"]["context7.query-docs"]
@@ -45,6 +46,23 @@ def test_workflow_artifact_serializes_required_capability_contract() -> None:
assert required["input_schema_hash"] == "sha256:input"
def test_workflow_artifact_can_be_marked_as_wrapper_intent() -> None:
artifact = WorkflowArtifact(
id="normalize_status",
version=1,
title="Normalize Status",
kind="wrapper",
input_schema={"type": "object", "properties": {}},
output_schema={"type": "object", "properties": {}},
outcomes=("done", "needs_input"),
plan={"name": "normalize_status", "nodes": [], "edges": []},
)
dumped = artifact.model_dump(mode="json")
assert dumped["kind"] == "wrapper"
def test_workflow_deployment_binds_logical_sources_to_concrete_sources() -> None:
deployment = WorkflowDeployment(
id="summarize_docs.personal",