docs: teach agents workflow schema discovery

This commit is contained in:
lda
2026-06-22 22:06:03 +07:00 Verified
parent bc89943554
commit 0185cb5227
5 changed files with 34 additions and 14 deletions
+5 -2
View File
@@ -69,5 +69,8 @@ wf run trace <run_id> --from 0 --limit 25
- Do not use planning-session specs or implementation plans as user-facing runtime guidance.
- Do not confuse draft shape with raw plan shape: drafts use `steps/routes/use`;
raw plans use `nodes/edges/node`.
- `wf schema` is currently only an empty command group; do not rely on it for
workflow plan shape until subcommands exist.
- Use `wf schema` to list workflow document/component shapes.
- Use `wf schema draft`, `wf schema raw`, or `wf schema <Component>` for compact
JSON guidance before authoring.
- Add `--verbose` only when a complete JSON Schema document is required; it may
be large.
@@ -3,6 +3,16 @@
Use direct plan import only when you already have a complete workflow plan. For
interactive authoring, prefer draft workspaces and focused edit commands.
Before writing a plan, inspect the current public shape:
wf schema raw
wf schema NodeUse
wf schema InputPathBinding
wf schema OutputBinding
Use `wf schema raw --verbose` only when the complete validation schema is
required.
## Command Path
```bash
@@ -3,6 +3,11 @@
Use draft workspaces for iterative workflow authoring. They are mutable and
revisioned; artifacts are immutable and versioned.
Before writing or patching a draft, inspect the current public shape:
wf schema draft
wf schema DraftUseStep
## Draft Shape
A draft has:
+9 -5
View File
@@ -13,7 +13,6 @@ from wf_api.models import RawWorkflowPlan
from wf_artifacts.drafts.models import WorkflowDraft
from wf_core.models.workflow import Workflow
JsonObject: TypeAlias = dict[str, Any]
SCHEMA_DIALECT = Draft202012Validator.META_SCHEMA["$id"]
ROOT_MODELS: dict[str, type[Any]] = {
@@ -63,7 +62,11 @@ class SchemaCatalog:
def entry(self, name: str) -> SchemaEntry:
canonical = self.resolve(name)
schema = self.schema(canonical)
aliases = tuple(sorted(alias for alias, target in self.aliases.items() if target == canonical))
aliases = tuple(
sorted(
alias for alias, target in self.aliases.items() if target == canonical
)
)
return SchemaEntry(
name=canonical,
aliases=aliases,
@@ -145,8 +148,7 @@ def _compact_node(schema: object, related: set[str]) -> object:
properties = schema.get("properties")
if isinstance(properties, dict):
result["properties"] = {
name: _compact_node(value, related)
for name, value in properties.items()
name: _compact_node(value, related) for name, value in properties.items()
}
if "items" in schema:
result["items"] = _compact_node(schema["items"], related)
@@ -157,7 +159,9 @@ def _compact_node(schema: object, related: set[str]) -> object:
result["one_of"] = [_compact_node(branch, related) for branch in branches]
break
discriminator = schema.get("discriminator")
if isinstance(discriminator, dict) and isinstance(discriminator.get("propertyName"), str):
if isinstance(discriminator, dict) and isinstance(
discriminator.get("propertyName"), str
):
result["discriminator"] = discriminator["propertyName"]
return result
+5 -7
View File
@@ -8,7 +8,11 @@ from jsonschema import Draft202012Validator
from typer.testing import CliRunner
from wf_cli.app import app
from wf_cli.schema_catalog import (
compact_schema_outline,
schema_catalog,
verbose_schema_document,
)
runner = CliRunner()
@@ -112,9 +116,6 @@ def test_schema_unknown_name_fails_with_suggestion() -> None:
assert "NodeUse" in result.output
from wf_cli.schema_catalog import schema_catalog
def test_schema_catalog_resolves_aliases_and_components() -> None:
catalog = schema_catalog()
@@ -125,9 +126,6 @@ def test_schema_catalog_resolves_aliases_and_components() -> None:
assert catalog.entry("NodeUse").kind == "definition"
from wf_cli.schema_catalog import compact_schema_outline, verbose_schema_document
def test_compact_outline_replaces_local_refs_with_names() -> None:
payload = compact_schema_outline("NodeUse")