Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
fef54f7
feat: inject sorted git diff into broad review rule prompts
nhorton Apr 1, 2026
ef01c0a
Merge branch 'main' of https://github.com/Unsupervisedcom/deepwork
nhorton Apr 1, 2026
a3a5cbe
feat: teach learn workflow to create deepschemas and deepreview rules
nhorton Apr 1, 2026
d3d07e5
feat: add claude_settings deepschema and enforce JSON-schema-first re…
nhorton Apr 1, 2026
840fe0e
docs: update architecture.md to reflect learn workflow's preventive a…
nhorton Apr 1, 2026
fccb5a2
refactor: move knowledge-based deepschema requirements to instructions
nhorton Apr 1, 2026
9ebe600
style: fix ruff formatting in review/instructions.py
nhorton Apr 2, 2026
fc2f5fd
feat: add requirements_file standard schema, specs, and review improv…
nhorton Apr 2, 2026
07ea90e
revert: restore REVIEW-REQ-005.7 to original position (pre-existing o…
nhorton Apr 2, 2026
d5e5075
test: verify named and anonymous schemas both apply to same file
nhorton Apr 2, 2026
d331357
Apply suggestion from @nhorton
nhorton Apr 2, 2026
768e5e7
refactor: promote claude_settings deepschema to standard schema
nhorton Apr 2, 2026
40232c2
docs: add verification_bash_command guidance to deepschema SKILL.md
nhorton Apr 2, 2026
28e50bc
revert: drop ruff formatting change to instructions.py
nhorton Apr 2, 2026
b995a1c
revert: remove git_diff injection for broad review rules
nhorton Apr 2, 2026
cd4bd68
fix: add --plugin-dir to CI claude invocations for DeepSchema validation
nhorton Apr 2, 2026
5e181d1
Merge branch 'main' into feat/learn-prevention-automation
nhorton Apr 3, 2026
26ed434
fix: resolve dual MCP server conflict in e2e CI and bump max turns to 25
nhorton Apr 3, 2026
be9c2ba
fix: remove stale ls of skills dir in CI setup
nhorton Apr 3, 2026
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
47 changes: 26 additions & 21 deletions .deepreview
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,33 @@ requirements_traceability:
false confidence (a passing test that doesn't actually verify anything)
or wastes reviewer judgment on something a machine can check exactly.

**Use anonymous DeepSchemas** (`.deepschema.<filename>.yml`) when
requirements target a specific file — whether structural or semantic:
- "This config file MUST include a timeout field" — structural check
for one file (use `json_schema_path` or `verification_bash_command`
for exact verification)
- "The learn workflow MUST accept X and Y step arguments" — the
requirement governs a specific YAML file's content
- "Skill MUST instruct the agent to do X" — judgment-based check
of prose in one specific file
- "The error message MUST include a suggestion for how to fix the
problem" — governs a specific source file's behavior

Anonymous DeepSchemas provide both write-time validation and review-time
checks, and they keep the requirement co-located with the file it governs.
**Prefer them over both tests and `.deepreview` rules whenever the
requirement targets a specific file** rather than a class of files.
DeepSchemas can enforce structural requirements via `json_schema_path`
or `verification_bash_command` just as precisely as a test, while also
supporting judgment-based requirements in the same schema.

**Use automated tests** (`tests/`) when the requirement specifies a
concrete, machine-verifiable fact:
- File exists at a specific path
- JSON/YAML field has a specific value
- Config contains a specific identifier (e.g., `mcp__deepwork__get_review_instructions`)
concrete, machine-verifiable fact that spans multiple files or is not
tied to a single file's content:
- File A is byte-identical to file B
- A data structure has a required shape
- A Python function returns the correct value for given inputs
- A CLI command produces expected output
- A data structure assembled from multiple sources has a required shape

Tests reference requirement IDs via docstrings and traceability comments.

Expand All @@ -150,21 +170,6 @@ requirements_traceability:
- "Documentation MUST stay in sync with code" — are the descriptions
still accurate after changes?

**Use anonymous DeepSchemas** (`.deepschema.<filename>.yml`) when the
requirement is specific to a single file's behavior or content:
- "The error message in situation X MUST include a suggestion for how
to fix the problem" — place the requirement in a `.deepschema` for
the file that implements that functionality
- "This config file MUST include a timeout field" — a structural
requirement for one specific file
- "Skill MUST instruct the agent to do X" — does the prose in this
specific skill file convey X clearly enough?

Anonymous DeepSchemas provide both write-time validation and review-time
checks, and they keep the requirement co-located with the file it governs.
Prefer them over `.deepreview` rules whenever the requirement targets a
specific file rather than a class of files.

Both `.deepreview` rules and DeepSchemas reference requirement IDs in
their `description`, `instructions`, or `requirements` fields.

Expand Down Expand Up @@ -456,7 +461,7 @@ deepreview_config_quality:
and a specific recommendation.

job_schema_instruction_compatibility:
description: "Verify deepwork_jobs job.yml inline instructions are compatible with the job schema."
description: "Verify all standard and library job.yml definitions and templates are compatible with the job schema."
match:
include:
- "src/deepwork/jobs/job.schema.json"
Expand Down
23 changes: 11 additions & 12 deletions .github/workflows/claude-code-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ jobs:
if: steps.check-key.outputs.has_key == 'true'
run: |
# Create a fresh project with NO pre-existing job definitions
mkdir -p test_project/.claude/skills/deepwork
mkdir -p test_project/.claude

cd test_project
git init
Expand All @@ -216,16 +216,14 @@ jobs:
git add . && git commit -m "init"
cd ..

# Copy plugin skill into the test project (replaces old `deepwork install`)
cp plugins/claude/skills/deepwork/SKILL.md test_project/.claude/skills/deepwork/

# Write MCP config using bare `deepwork` command (CI has it on PATH
# via .venv/bin; the plugin's .mcp.json uses `uvx` which isn't available here)
# The plugin (--plugin-dir) provides skills, hooks, and MCP server config.
# Override the plugin's MCP config to use the bare `deepwork` command
# (the plugin uses `uvx` which may not resolve the local venv install).
python3 -c "
import json
mcp = {'mcpServers': {'deepwork': {
'command': 'deepwork',
'args': ['serve', '--path', '.', '--external-runner', 'claude']
'args': ['serve', '--path', '.', '--platform', 'claude']
}}}
with open('test_project/.mcp.json', 'w') as f:
json.dump(mcp, f, indent=2)
Expand All @@ -240,7 +238,8 @@ jobs:
'Bash(*)', 'Read(./**)', 'Edit(./**)', 'Write(./**)', 'Skill(*)',
'mcp__deepwork__get_workflows', 'mcp__deepwork__start_workflow',
'mcp__deepwork__finished_step', 'mcp__deepwork__abort_workflow',
'mcp__deepwork__go_to_step'
'mcp__deepwork__go_to_step',
'mcp__deepwork__mark_review_as_passed'
]
}
}
Expand All @@ -249,8 +248,8 @@ jobs:
"

echo "Fresh test project setup complete"
echo "Available skills:"
ls -la test_project/.claude/skills/
echo "MCP config:"
cat test_project/.mcp.json

# STEP 1: Use /deepwork to CREATE the fruits job via MCP workflow
#
Expand All @@ -269,7 +268,7 @@ jobs:
# Use --debug and --output-format stream-json for diagnosing failures.
# stream-json shows every tool call; output is captured to a file for the failure handler.
set -o pipefail
claude --print --verbose --output-format stream-json --max-turns 20 --debug --model claude-sonnet-4-6 --dangerously-skip-permissions <<'PROMPT_EOF' | tee ../claude-create-job.jsonl
claude --print --verbose --output-format stream-json --max-turns 25 --debug --model claude-sonnet-4-6 --dangerously-skip-permissions --plugin-dir "$GITHUB_WORKSPACE/plugins/claude" <<'PROMPT_EOF' | tee ../claude-create-job.jsonl
/deepwork I want to create a simple job called "fruits" for identifying and classifying fruits.

Here are the EXACT specifications.
Expand Down Expand Up @@ -380,7 +379,7 @@ jobs:
echo "=== Running fruits workflow with test input via /deepwork ==="

set -o pipefail
claude --print --verbose --output-format stream-json --max-turns 20 --debug --model claude-sonnet-4-6 --dangerously-skip-permissions <<'PROMPT_EOF' | tee ../claude-run-workflow.jsonl
claude --print --verbose --output-format stream-json --max-turns 25 --debug --model claude-sonnet-4-6 --dangerously-skip-permissions --plugin-dir "$GITHUB_WORKSPACE/plugins/claude" <<'PROMPT_EOF' | tee ../claude-run-workflow.jsonl
/deepwork Run the fruits full workflow. Process the list to the file and don't give any extra commentary or text output.
NEVER use AskUserQuestion — you already have all the information you need.
You MUST complete all tool calls needed. Do not stop early.
Expand Down
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ Each step:
7. **Succinctness**: Jobs, documentation, and code MUST be succinct. Avoid verbose preambles, redundant explanations, and duplicated content. Step instructions should contain only what the agent needs to act — not philosophy, not quality criteria already enforced by the workflow runtime, and not domain tables already in `common_job_info`. If it can be said in one sentence, do not use three.
8. **Documentation Sync**: When making implementation changes, update `doc/architecture.md` and `README.md` to reflect those changes.

## MCP Tool Naming in This Repo

This repo has **two** MCP server instances: one from the plugin (`plugin:deepwork:deepwork`, tools prefixed `mcp__plugin_deepwork_deepwork__`) and one from the project-level `.mcp.json` (`deepwork`, tools prefixed `mcp__deepwork__`). **Always use the non-plugin prefix** (`mcp__deepwork__*`) when calling MCP tools in this repo — including in the e2e CI test (`claude-code-test.yml`), workflow prompts, and any scripted Claude sessions. The non-plugin server is configured for development/testing (bare `deepwork` command, `--path .`), while the plugin server uses `uvx` and is meant for end-user installations. Note: `how_to_invoke` in `src/deepwork/jobs/mcp/tools.py` hardcodes the `mcp__plugin_deepwork_deepwork__` prefix — this is correct for end-user plugin installations but causes confusion when both servers are present in development.

## Appendix: Project Structure

```
Expand Down
11 changes: 8 additions & 3 deletions doc/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ DeepWork includes a built-in job called `deepwork_jobs` for managing jobs. It pr
- **`repair`** workflow: `fix_settings` → `fix_jobs` → `errata`
- Cleans up and migrates DeepWork configurations from prior versions
- **`learn`** workflow: `learn`
- Analyzes conversation history to improve job instructions and capture learnings
- Analyzes conversation history to improve job instructions, capture learnings, and create preventive automation (DeepSchemas and DeepReview rules)

These are auto-discovered at runtime by the MCP server from the Python package.

Expand Down Expand Up @@ -532,7 +532,7 @@ User: /deepwork new_job

### The `learn` Workflow

Analyzes conversation history to improve job instructions and capture learnings:
Analyzes conversation history to improve job instructions, capture learnings, and create preventive automation:

```
User: /deepwork_jobs.learn
Expand All @@ -551,10 +551,14 @@ Claude: I'll analyze this conversation for DeepWork job executions...
Bespoke learnings captured:
✓ Created AGENTS.md with project-specific notes about this competitive research instance

Prevention opportunities evaluated:
✓ Created DeepSchema for competitor_profiles/ output format
✓ Added DeepReview rule to enforce source prioritization in research steps

Job instructions updated in place. Changes take effect on next workflow run.
```

This standalone skill can be run anytime after executing a job to capture learnings and improve instructions.
This standalone skill can be run anytime after executing a job to capture learnings, improve instructions, and create preventive automation (DeepSchemas and DeepReview rules).

### Step Instructions at Runtime

Expand Down Expand Up @@ -742,6 +746,7 @@ The `/deepwork_jobs.define` command:
The `/deepwork_jobs.learn` command:
1. Identifies doc spec-related learnings (quality criteria issues, structure changes)
2. Updates doc spec files with improvements
3. Evaluates prevention opportunities and creates DeepSchemas and DeepReview rules

See `doc/doc-specs.md` for complete documentation.

Expand Down
62 changes: 59 additions & 3 deletions plugins/claude/skills/deepschema/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ matchers:
- "src/configs/**/*.json"

requirements:
has-version: "Every config file MUST include a version field."
# Semantic rules only — structural constraints go in config.schema.json
documented-fields: "All fields SHOULD have inline comments explaining their purpose."
no-secrets: "Config files MUST NOT contain secrets or credentials."

# Optional: structural validation
# Structural validation — enforce types, required fields, enums, etc. here
json_schema_path: "config.schema.json"

# Optional: custom validation commands (file path passed as $1)
Expand All @@ -72,13 +72,69 @@ Place a `.deepschema.<filename>.yml` file next to the target file:
```yaml
requirements:
api-key-rotated: "The API key MUST be rotated every 90 days."
format-valid: "The file MUST be valid YAML."
no-plaintext-secrets: "Credentials MUST use environment variable references, not literal values."

# Reference a named schema for shared requirements
parent_deep_schemas:
- api_endpoint
```

## JSON Schema First: Maximize Structural Validation

**The `json_schema_path` file is the primary enforcement mechanism.** Every constraint that _can_ be expressed structurally MUST go in the JSON Schema, not in requirements. Requirements exist only for semantic rules that JSON Schema cannot express.

Put in the JSON Schema (not requirements):
- File format validity (valid JSON, valid YAML)
- Field types (string, number, boolean, array, object)
- Required fields
- Allowed property names (`additionalProperties: false`)
- Enum values and allowed constants
- Array item types and constraints (`minItems`, `uniqueItems`)
- Numeric ranges (`minimum`, `maximum`)
- String patterns (`pattern`, `format`)
- Conditional field presence (`if`/`then` — e.g., "when type is 'http', url is required")
- Nested object shapes and their constraints

Put in requirements (not the JSON Schema):
- Semantic rules about _meaning_ ("secrets MUST NOT appear in shared settings")
- Cross-file concerns ("this field MUST reference an existing named schema")
- Behavioral gotchas ("sandbox paths use different prefix semantics than permission paths")
- Design guidance ("deny rules SHOULD be used for hard security boundaries, not soft preferences")
- Anything requiring judgment or context a machine validator cannot assess

**Build the JSON Schema to be as strict and comprehensive as possible.** Use `additionalProperties: false` to catch typos. Use enums for closed sets. Use `if/then` for conditional requirements. Use `pattern` for string formats. Use `$defs` and `$ref` for reusable types. Use `anyOf` for discriminated unions. Use `uniqueItems`, `minLength`, `minItems` where appropriate. A good JSON Schema catches errors at write time before a reviewer ever sees the file. Requirements that duplicate what the schema already enforces are noise — they dilute the reviewer's attention and risk contradicting the schema.

### Verification Commands for Non-JSON Files

For files that aren't JSON or YAML (markdown, shell scripts, plain text, custom formats), `verification_bash_command` serves the same role as `json_schema_path` — it's the primary structural enforcement mechanism. The same principle applies: anything a command can check exactly MUST go in a verification command, not in requirements.

```yaml
# Example: RFC 2119 requirements files (markdown)
verification_bash_command:
- "grep -nE '^[0-9]+\\.' \"$1\" | grep -vE 'MUST|SHALL|SHOULD|MAY|REQUIRED|RECOMMENDED|OPTIONAL' | { if read -r line; then echo \"FAIL: Requirement without RFC 2119 keyword: $line\"; exit 1; fi; }"

requirements:
# Only semantic rules the command can't check
testability: "Each requirement MUST be specific enough to be verifiable."
```

Commands receive the file path as `$1`, must exit 0 on success and non-zero on failure, and have a 30-second timeout.

### Check SchemaStore for Existing Schemas

Before writing a JSON Schema from scratch, check whether a published schema already exists at [SchemaStore](https://www.schemastore.org/) (`https://json.schemastore.org/<name>.json`). SchemaStore hosts community-maintained schemas for hundreds of config file formats.

If a good schema exists:
1. **Vendor a local copy** into your schema directory (e.g., `claude_settings.schema.json`)
2. **Add a `_source` field** at the top of the file with the original URL and sync date:
```json
{
"_source": "Vendored from https://json.schemastore.org/example.json. To update: fetch the latest version from that URL and replace this file. Last synced: 2026-04-01."
}
```
3. **Point `json_schema_path`** at the local copy — this avoids network dependencies during validation
4. **Periodically re-fetch** the upstream schema to pick up improvements — the `_source` field tells future maintainers where to look

## Schema Fields Reference

| Field | Description |
Expand Down
15 changes: 12 additions & 3 deletions specs/deepwork/DW-REQ-011-deepschema.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# DW-REQ-011: DeepSchema System

## Overview

The DeepSchema system provides rich, file-level schemas with automatic validation on writes and synthetic review rule generation.

## DW-REQ-011.1: Schema Types
Expand Down Expand Up @@ -42,13 +44,13 @@ The DeepSchema system provides rich, file-level schemas with automatic validatio

1. A file MUST match a named schema if any of the schema's `matchers` glob patterns match the file's project-relative path.
2. A file MUST match an anonymous schema if a `.deepschema.<filename>.yml` file exists alongside it.
3. The `get_schemas_for_file_fast()` function MUST avoid full tree walks — it MUST only scan named schema folders and check for the anonymous schema file at O(1).
3. The `get_schemas_for_file_fast()` function MUST avoid full tree walks by only scanning named schema folders and checking for the anonymous schema file at O(1).

## DW-REQ-011.7: Write Hook (PostToolUse)

1. The write hook MUST fire on PostToolUse events for Write and Edit tools.
2. For each applicable schema, the hook MUST inject a conformance note: "Note: this file must conform to the DeepSchema at `<path>`".
3. If `json_schema_path` is set, the hook MUST validate the written file against the JSON Schema. YAML files (`.yml`/`.yaml`) MUST be parsed as YAML before validation.
3. If `json_schema_path` is set, the hook MUST validate the written file against the JSON Schema, parsing YAML files (`.yml`/`.yaml`) as YAML before validation.
4. If `verification_bash_command` is set, the hook MUST execute each command with the file path as `$1`, with a 30-second timeout.
5. Validation failures MUST be reported via `hookSpecificOutput.additionalContext` so the agent can act on them.
6. The hook MUST NOT use `systemMessage` for validation output — that route is user-visible only.
Expand All @@ -61,10 +63,17 @@ The DeepSchema system provides rich, file-level schemas with automatic validatio
4. Anonymous schema reviews MUST include only the requirements.
5. All generated reviews MUST use the `"individual"` strategy (one file at a time).
6. Generated reviews MUST be included in both `/review` runs and workflow quality gate checks.
7. Review instructions MUST specify RFC 2119 severity logic: reviewers MUST fail any violation of a MUST requirement, MUST fail any SHOULD requirement that could easily be followed but is not, SHOULD give feedback without failing on other applicable items, and MUST ignore requirements that are not applicable.
7. Review instructions MUST specify RFC 2119 severity logic: fail any violation of a MUST requirement, fail any SHOULD requirement that could easily be followed but is not, give feedback without failing on other applicable items, and ignore requirements that are not applicable.

## DW-REQ-011.9: MCP Tool — get_named_schemas

1. The `get_named_schemas` MCP tool MUST return all discovered named schemas.
2. Each entry MUST include `name`, `summary`, and `matchers` fields.
3. Schemas that fail to parse MUST still appear in the results with an error summary instead of a real summary.

## DW-REQ-011.10: Requirement Quality Constraints

1. Each requirement in the `requirements` field MUST be verifiable by examining files on the filesystem.
2. Requirements about processes, user behavior, or context not present in files SHOULD be placed in the `instructions` section instead.
3. Requirements MUST NOT restate constraints that are already enforced by the schema's `json_schema_path` or `verification_bash_command`, including syntactic validity (e.g., "must be valid JSON"), field types, allowed enum values, required fields, and structural shape.
4. Requirements SHOULD focus on semantic rules, behavioral gotchas, and cross-field concerns that JSON Schema cannot express.
Loading
Loading