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
1 change: 1 addition & 0 deletions .deepwork.policy.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# yaml-language-server: $schema=src/deepwork/schemas/policy.schema.json
- name: "README Accuracy"
trigger: "src/**/*"
safety: "README.md"
Expand Down
1 change: 1 addition & 0 deletions .deepwork/jobs/add_platform/job.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# yaml-language-server: $schema=../../../src/deepwork/schemas/job.schema.json
name: add_platform
version: "0.1.0"
summary: "Add a new AI platform to DeepWork with adapter, templates, and tests"
Expand Down
1 change: 1 addition & 0 deletions .deepwork/jobs/deepwork_jobs/job.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# yaml-language-server: $schema=../../../src/deepwork/schemas/job.schema.json
name: deepwork_jobs
version: "0.2.0"
summary: "DeepWork job management commands"
Expand Down
1 change: 1 addition & 0 deletions .deepwork/jobs/deepwork_policy/job.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# yaml-language-server: $schema=../../../src/deepwork/schemas/job.schema.json
name: deepwork_policy
version: "0.1.0"
summary: "Policy enforcement for AI agent sessions"
Expand Down
6 changes: 3 additions & 3 deletions src/deepwork/core/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from typing import Any

from deepwork.schemas.job_schema import JOB_SCHEMA, LIFECYCLE_HOOK_EVENTS
from deepwork.utils.validation import ValidationError, validate_against_schema
from deepwork.utils.validation import ValidationError, validate_and_set_defaults
from deepwork.utils.yaml_utils import YAMLError, load_yaml


Expand Down Expand Up @@ -294,9 +294,9 @@ def parse_job_definition(job_dir: Path | str) -> JobDefinition:
if job_data is None:
raise ParseError("job.yml is empty")

# Validate against schema
# Validate against schema and apply defaults
try:
validate_against_schema(job_data, JOB_SCHEMA)
validate_and_set_defaults(job_data, JOB_SCHEMA)
except ValidationError as e:
raise ParseError(f"Job definition validation failed: {e}") from e

Expand Down
6 changes: 3 additions & 3 deletions src/deepwork/core/policy_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import yaml

from deepwork.schemas.policy_schema import POLICY_SCHEMA
from deepwork.utils.validation import ValidationError, validate_against_schema
from deepwork.utils.validation import ValidationError, validate_and_set_defaults


class PolicyParseError(Exception):
Expand Down Expand Up @@ -280,9 +280,9 @@ def parse_policy_file(policy_path: Path | str, base_dir: Path | None = None) ->
f"Policy file must contain a list of policies, got {type(policy_data).__name__}"
)

# Validate against schema
# Validate against schema and apply defaults
try:
validate_against_schema(policy_data, POLICY_SCHEMA)
validate_and_set_defaults(policy_data, POLICY_SCHEMA)
except ValidationError as e:
raise PolicyParseError(f"Policy definition validation failed: {e}") from e

Expand Down
221 changes: 221 additions & 0 deletions src/deepwork/schemas/job.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://deepwork.dev/schemas/job.schema.json",
"title": "DeepWork Job Definition",
"description": "Schema for DeepWork job.yml files that define multi-step workflows",
"type": "object",
"required": ["name", "version", "summary", "steps"],
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]*$",
"description": "Job name (lowercase letters, numbers, underscores, must start with letter)"
},
"version": {
"type": "string",
"pattern": "^\\d+\\.\\d+\\.\\d+$",
"description": "Semantic version (e.g., 1.0.0)"
},
"summary": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Brief one-line summary of what this job accomplishes"
},
"description": {
"type": "string",
"minLength": 1,
"description": "Detailed multi-line description of the job's purpose, process, and goals"
},
"changelog": {
"type": "array",
"default": [],
"description": "Version history and changes to the job",
"items": {
"type": "object",
"required": ["version", "changes"],
"additionalProperties": false,
"properties": {
"version": {
"type": "string",
"pattern": "^\\d+\\.\\d+\\.\\d+$",
"description": "Version number for this change"
},
"changes": {
"type": "string",
"minLength": 1,
"description": "Description of changes made in this version"
}
}
}
},
"steps": {
"type": "array",
"minItems": 1,
"description": "List of steps in the job",
"items": {
"$ref": "#/$defs/step"
}
}
},
"$defs": {
"hookAction": {
"type": "object",
"description": "A hook action - one of: inline prompt, prompt file reference, or shell script",
"oneOf": [
{
"required": ["prompt"],
"additionalProperties": false,
"properties": {
"prompt": {
"type": "string",
"minLength": 1,
"description": "Inline prompt for validation/action"
}
}
},
{
"required": ["prompt_file"],
"additionalProperties": false,
"properties": {
"prompt_file": {
"type": "string",
"minLength": 1,
"description": "Path to prompt file (relative to job directory)"
}
}
},
{
"required": ["script"],
"additionalProperties": false,
"properties": {
"script": {
"type": "string",
"minLength": 1,
"description": "Path to shell script (relative to job directory)"
}
}
}
]
},
"userInput": {
"type": "object",
"description": "User parameter input",
"required": ["name", "description"],
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"description": "Input parameter name"
},
"description": {
"type": "string",
"description": "Input parameter description"
}
}
},
"fileInput": {
"type": "object",
"description": "File input from a previous step",
"required": ["file", "from_step"],
"additionalProperties": false,
"properties": {
"file": {
"type": "string",
"description": "File name from previous step"
},
"from_step": {
"type": "string",
"description": "Step ID that produces this file"
}
}
},
"step": {
"type": "object",
"description": "A single step in the job workflow",
"required": ["id", "name", "description", "instructions_file", "outputs"],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]*$",
"description": "Step ID (unique within job)"
},
"name": {
"type": "string",
"minLength": 1,
"description": "Human-readable step name"
},
"description": {
"type": "string",
"minLength": 1,
"description": "Step description"
},
"instructions_file": {
"type": "string",
"minLength": 1,
"description": "Path to instructions file (relative to job directory)"
},
"inputs": {
"type": "array",
"default": [],
"description": "List of inputs (user parameters or files from previous steps)",
"items": {
"oneOf": [
{ "$ref": "#/$defs/userInput" },
{ "$ref": "#/$defs/fileInput" }
]
}
},
"outputs": {
"type": "array",
"description": "List of output files/directories",
"items": {
"type": "string",
"minLength": 1
}
},
"dependencies": {
"type": "array",
"default": [],
"description": "List of step IDs this step depends on",
"items": {
"type": "string"
}
},
"hooks": {
"type": "object",
"default": {},
"description": "Lifecycle hooks for this step, keyed by event type",
"additionalProperties": false,
"properties": {
"after_agent": {
"type": "array",
"default": [],
"description": "Hooks triggered after the agent finishes (quality validation)",
"items": { "$ref": "#/$defs/hookAction" }
},
"before_tool": {
"type": "array",
"default": [],
"description": "Hooks triggered before a tool is used",
"items": { "$ref": "#/$defs/hookAction" }
},
"before_prompt": {
"type": "array",
"default": [],
"description": "Hooks triggered when user submits a prompt",
"items": { "$ref": "#/$defs/hookAction" }
}
}
},
"stop_hooks": {
"type": "array",
"description": "DEPRECATED: Use hooks.after_agent instead. Stop hooks for quality validation loops.",
"items": { "$ref": "#/$defs/hookAction" }
}
}
}
}
}
Loading