549 lines
14 KiB
Markdown
549 lines
14 KiB
Markdown
# wf_api Slice 3B: Guidance Helpers Move Implementation Plan
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** Move protocol-neutral wrapper guidance helpers from `wf_mcp.workflow_surface` into `wf_api`, while preserving old imports as compatibility shims.
|
||
|
||
**Architecture:** `wrapper_hints.py` and `next_actions.py` are coupled guidance helpers: `next_actions` imports `WrapperAuthoringHints`, and both describe workflow authoring UX rather than MCP transport behavior. This slice moves them together to avoid a half-moved dependency. The old `wf_mcp.workflow_surface` modules remain thin re-export shims so MCP schemas/tests and older imports keep working.
|
||
|
||
**Tech Stack:** Python 3.14+, Pydantic v2 models, pytest, ruff, basedpyright.
|
||
|
||
---
|
||
|
||
## Scope
|
||
|
||
### In Scope
|
||
|
||
- Create `src/wf_api/wrapper_hints.py`.
|
||
- Create `src/wf_api/next_actions.py`.
|
||
- Re-export selected public guidance types/functions from `src/wf_api/__init__.py`.
|
||
- Replace `wf_mcp.workflow_surface.wrapper_hints` with a compatibility shim.
|
||
- Replace `wf_mcp.workflow_surface.next_actions` with a compatibility shim.
|
||
- Update `src/wf_mcp/workflow_surface/handlers.py` to import canonical helpers from `wf_api`.
|
||
- Update `src/wf_mcp/workflow_surface/models.py` to import canonical next-action models from `wf_api`.
|
||
- Update direct tests to use canonical imports while preserving shim compatibility tests.
|
||
- Keep `wf_api` free of `wf_mcp` imports.
|
||
|
||
### Out Of Scope
|
||
|
||
- Do not move `models.py`.
|
||
- Do not move `run_lifecycle.py`.
|
||
- Do not move `runtime_dependencies.py`.
|
||
- Do not move `saved_subgraphs.py`.
|
||
- Do not rename `WorkflowSurfaceHandlers`.
|
||
- Do not change wrapper hint behavior.
|
||
- Do not change next action behavior.
|
||
- Do not change public payloads, MCP tool names, CLI command names, or JSON schema field names.
|
||
|
||
---
|
||
|
||
## File Structure
|
||
|
||
### New Canonical Files
|
||
|
||
| File | Responsibility |
|
||
| --- | --- |
|
||
| `src/wf_api/wrapper_hints.py` | Wrapper scaffolding hints, confidence, missing-decision models, and conservative schema mapping helper. |
|
||
| `src/wf_api/next_actions.py` | Advisory next-action models and factory helpers for wrapper/deployment/run responses. |
|
||
|
||
### Compatibility Shims
|
||
|
||
| File | Responsibility |
|
||
| --- | --- |
|
||
| `src/wf_mcp/workflow_surface/wrapper_hints.py` | Re-export wrapper hint helpers from `wf_api.wrapper_hints`. |
|
||
| `src/wf_mcp/workflow_surface/next_actions.py` | Re-export next action helpers from `wf_api.next_actions`. |
|
||
|
||
### Modified Consumers
|
||
|
||
| File | Change |
|
||
| --- | --- |
|
||
| `src/wf_api/__init__.py` | Re-export public guidance helpers. |
|
||
| `src/wf_mcp/workflow_surface/handlers.py` | Import `NextActions` and wrapper hint helpers from `wf_api`. |
|
||
| `src/wf_mcp/workflow_surface/models.py` | Import `NextActionPatchExample` and `NextActions` from `wf_api.next_actions`. |
|
||
| `tests/wf_mcp/test_workflow_wrapper_hints.py` | Use canonical `wf_api.wrapper_hints`; add shim identity test. |
|
||
| `tests/wf_mcp/workflow_surface/test_next_actions.py` | Use canonical `wf_api.next_actions`; add shim identity test. |
|
||
|
||
---
|
||
|
||
## Task 1: Create Canonical `wf_api.wrapper_hints`
|
||
|
||
**Files:**
|
||
|
||
- Create: `src/wf_api/wrapper_hints.py`
|
||
|
||
- [ ] **Step 1: Copy existing implementation**
|
||
|
||
Create `src/wf_api/wrapper_hints.py` by copying the complete current contents of:
|
||
|
||
```text
|
||
src/wf_mcp/workflow_surface/wrapper_hints.py
|
||
```
|
||
|
||
Do not change behavior. The copied module must not import `wf_mcp`.
|
||
|
||
- [ ] **Step 2: Add `__all__` at the end**
|
||
|
||
Append this block to the copied file:
|
||
|
||
```python
|
||
__all__ = [
|
||
"MissingDecision",
|
||
"MissingDecisionKind",
|
||
"OutcomeCandidate",
|
||
"OutcomeCandidateKind",
|
||
"WrapperAuthoringHints",
|
||
"WrapperHintConfidence",
|
||
"WrapperOutcomePolicy",
|
||
"workflow_output_schema_for_authoring",
|
||
"wrapper_hints_for_capability",
|
||
]
|
||
```
|
||
|
||
- [ ] **Step 3: Run import smoke check**
|
||
|
||
Run:
|
||
|
||
```powershell
|
||
uv run python -c "from wf_api.wrapper_hints import WrapperAuthoringHints, wrapper_hints_for_capability; print(WrapperAuthoringHints.__name__, wrapper_hints_for_capability.__name__)"
|
||
```
|
||
|
||
Expected output:
|
||
|
||
```text
|
||
WrapperAuthoringHints wrapper_hints_for_capability
|
||
```
|
||
|
||
---
|
||
|
||
## Task 2: Create Canonical `wf_api.next_actions`
|
||
|
||
**Files:**
|
||
|
||
- Create: `src/wf_api/next_actions.py`
|
||
|
||
- [ ] **Step 1: Copy existing implementation**
|
||
|
||
Create `src/wf_api/next_actions.py` by copying the complete current contents of:
|
||
|
||
```text
|
||
src/wf_mcp/workflow_surface/next_actions.py
|
||
```
|
||
|
||
- [ ] **Step 2: Keep local wrapper hint import canonical**
|
||
|
||
Ensure the copied file imports wrapper hints from the new `wf_api` package via:
|
||
|
||
```python
|
||
from .wrapper_hints import WrapperAuthoringHints
|
||
```
|
||
|
||
The copied module must not import `wf_mcp`.
|
||
|
||
- [ ] **Step 3: Add `__all__` at the end**
|
||
|
||
Append this block to the copied file:
|
||
|
||
```python
|
||
__all__ = [
|
||
"NextActionPatchExample",
|
||
"NextActionTool",
|
||
"NextActions",
|
||
]
|
||
```
|
||
|
||
- [ ] **Step 4: Run import smoke check**
|
||
|
||
Run:
|
||
|
||
```powershell
|
||
uv run python -c "from wf_api.next_actions import NextActionTool, NextActions; print(NextActionTool.RUN_DEPLOYMENT, NextActions.__name__)"
|
||
```
|
||
|
||
Expected output:
|
||
|
||
```text
|
||
wf.workflow.run_deployment NextActions
|
||
```
|
||
|
||
---
|
||
|
||
## Task 3: Re-export Guidance Helpers From `wf_api`
|
||
|
||
**Files:**
|
||
|
||
- Modify: `src/wf_api/__init__.py`
|
||
|
||
- [ ] **Step 1: Add imports**
|
||
|
||
Add these imports:
|
||
|
||
```python
|
||
from .next_actions import NextActionPatchExample, NextActionTool, NextActions
|
||
from .wrapper_hints import (
|
||
MissingDecision,
|
||
MissingDecisionKind,
|
||
OutcomeCandidate,
|
||
OutcomeCandidateKind,
|
||
WrapperAuthoringHints,
|
||
WrapperHintConfidence,
|
||
WrapperOutcomePolicy,
|
||
workflow_output_schema_for_authoring,
|
||
wrapper_hints_for_capability,
|
||
)
|
||
```
|
||
|
||
- [ ] **Step 2: Add names to `__all__`**
|
||
|
||
Ensure `__all__` includes these names:
|
||
|
||
```python
|
||
"MissingDecision",
|
||
"MissingDecisionKind",
|
||
"NextActionPatchExample",
|
||
"NextActionTool",
|
||
"NextActions",
|
||
"OutcomeCandidate",
|
||
"OutcomeCandidateKind",
|
||
"WrapperAuthoringHints",
|
||
"WrapperHintConfidence",
|
||
"WrapperOutcomePolicy",
|
||
"workflow_output_schema_for_authoring",
|
||
"wrapper_hints_for_capability",
|
||
```
|
||
|
||
- [ ] **Step 3: Run top-level import smoke check**
|
||
|
||
Run:
|
||
|
||
```powershell
|
||
uv run python -c "from wf_api import NextActions, WrapperAuthoringHints; print(NextActions.__name__, WrapperAuthoringHints.__name__)"
|
||
```
|
||
|
||
Expected output:
|
||
|
||
```text
|
||
NextActions WrapperAuthoringHints
|
||
```
|
||
|
||
---
|
||
|
||
## Task 4: Convert Old Workflow-Surface Guidance Modules To Shims
|
||
|
||
**Files:**
|
||
|
||
- Modify: `src/wf_mcp/workflow_surface/wrapper_hints.py`
|
||
- Modify: `src/wf_mcp/workflow_surface/next_actions.py`
|
||
|
||
- [ ] **Step 1: Replace `src/wf_mcp/workflow_surface/wrapper_hints.py`**
|
||
|
||
Replace the file with this shim:
|
||
|
||
```python
|
||
"""Compatibility shim for workflow API wrapper authoring hints.
|
||
|
||
New code should import from `wf_api.wrapper_hints`. This module stays so older
|
||
MCP workflow-surface imports keep working during extraction.
|
||
"""
|
||
|
||
from wf_api.wrapper_hints import (
|
||
MissingDecision,
|
||
MissingDecisionKind,
|
||
OutcomeCandidate,
|
||
OutcomeCandidateKind,
|
||
WrapperAuthoringHints,
|
||
WrapperHintConfidence,
|
||
WrapperOutcomePolicy,
|
||
workflow_output_schema_for_authoring,
|
||
wrapper_hints_for_capability,
|
||
)
|
||
|
||
__all__ = [
|
||
"MissingDecision",
|
||
"MissingDecisionKind",
|
||
"OutcomeCandidate",
|
||
"OutcomeCandidateKind",
|
||
"WrapperAuthoringHints",
|
||
"WrapperHintConfidence",
|
||
"WrapperOutcomePolicy",
|
||
"workflow_output_schema_for_authoring",
|
||
"wrapper_hints_for_capability",
|
||
]
|
||
```
|
||
|
||
- [ ] **Step 2: Replace `src/wf_mcp/workflow_surface/next_actions.py`**
|
||
|
||
Replace the file with this shim:
|
||
|
||
```python
|
||
"""Compatibility shim for workflow API next-action guidance.
|
||
|
||
New code should import from `wf_api.next_actions`. This module stays so older
|
||
MCP workflow-surface imports keep working during extraction.
|
||
"""
|
||
|
||
from wf_api.next_actions import NextActionPatchExample, NextActionTool, NextActions
|
||
|
||
__all__ = [
|
||
"NextActionPatchExample",
|
||
"NextActionTool",
|
||
"NextActions",
|
||
]
|
||
```
|
||
|
||
- [ ] **Step 3: Run shim import smoke check**
|
||
|
||
Run:
|
||
|
||
```powershell
|
||
uv run python -c "from wf_mcp.workflow_surface.wrapper_hints import WrapperAuthoringHints; from wf_mcp.workflow_surface.next_actions import NextActions; print(WrapperAuthoringHints.__name__, NextActions.__name__)"
|
||
```
|
||
|
||
Expected output:
|
||
|
||
```text
|
||
WrapperAuthoringHints NextActions
|
||
```
|
||
|
||
---
|
||
|
||
## Task 5: Update Production Imports To Canonical Paths
|
||
|
||
**Files:**
|
||
|
||
- Modify: `src/wf_mcp/workflow_surface/handlers.py`
|
||
- Modify: `src/wf_mcp/workflow_surface/models.py`
|
||
|
||
- [ ] **Step 1: Update `handlers.py` next action import**
|
||
|
||
Replace:
|
||
|
||
```python
|
||
from .next_actions import NextActions
|
||
```
|
||
|
||
with:
|
||
|
||
```python
|
||
from wf_api.next_actions import NextActions
|
||
```
|
||
|
||
- [ ] **Step 2: Update `handlers.py` wrapper hint import**
|
||
|
||
Replace:
|
||
|
||
```python
|
||
from .wrapper_hints import (
|
||
workflow_output_schema_for_authoring,
|
||
wrapper_hints_for_capability,
|
||
)
|
||
```
|
||
|
||
with:
|
||
|
||
```python
|
||
from wf_api.wrapper_hints import (
|
||
workflow_output_schema_for_authoring,
|
||
wrapper_hints_for_capability,
|
||
)
|
||
```
|
||
|
||
- [ ] **Step 3: Update `models.py` next action import**
|
||
|
||
Replace:
|
||
|
||
```python
|
||
from .next_actions import NextActionPatchExample, NextActions
|
||
```
|
||
|
||
with:
|
||
|
||
```python
|
||
from wf_api.next_actions import NextActionPatchExample, NextActions
|
||
```
|
||
|
||
- [ ] **Step 4: Run production import smoke check**
|
||
|
||
Run:
|
||
|
||
```powershell
|
||
uv run python -c "from wf_mcp.workflow_surface.handlers import WorkflowSurfaceHandlers; from wf_mcp.workflow_surface.models import WrapperDraftNextActions; print(WorkflowSurfaceHandlers.__name__, WrapperDraftNextActions.__name__)"
|
||
```
|
||
|
||
Expected output:
|
||
|
||
```text
|
||
WorkflowSurfaceHandlers NextActions
|
||
```
|
||
|
||
---
|
||
|
||
## Task 6: Update Direct Tests And Add Shim Compatibility Tests
|
||
|
||
**Files:**
|
||
|
||
- Modify: `tests/wf_mcp/test_workflow_wrapper_hints.py`
|
||
- Modify: `tests/wf_mcp/workflow_surface/test_next_actions.py`
|
||
|
||
- [ ] **Step 1: Update wrapper hints test imports**
|
||
|
||
In `tests/wf_mcp/test_workflow_wrapper_hints.py`, replace imports from:
|
||
|
||
```python
|
||
from wf_mcp.workflow_surface.wrapper_hints import (
|
||
```
|
||
|
||
with:
|
||
|
||
```python
|
||
from wf_api.wrapper_hints import (
|
||
```
|
||
|
||
- [ ] **Step 2: Add wrapper hints shim identity test**
|
||
|
||
Append this test to `tests/wf_mcp/test_workflow_wrapper_hints.py`:
|
||
|
||
```python
|
||
def test_workflow_surface_wrapper_hints_shim_reexports_canonical_helper() -> None:
|
||
from wf_api.wrapper_hints import wrapper_hints_for_capability
|
||
from wf_mcp.workflow_surface.wrapper_hints import (
|
||
wrapper_hints_for_capability as wrapper_hints_for_capability_shim,
|
||
)
|
||
|
||
assert wrapper_hints_for_capability_shim is wrapper_hints_for_capability
|
||
```
|
||
|
||
- [ ] **Step 3: Update next actions test imports**
|
||
|
||
In `tests/wf_mcp/workflow_surface/test_next_actions.py`, replace:
|
||
|
||
```python
|
||
from wf_mcp.workflow_surface.next_actions import NextActionTool, NextActions
|
||
```
|
||
|
||
with:
|
||
|
||
```python
|
||
from wf_api.next_actions import NextActionTool, NextActions
|
||
```
|
||
|
||
- [ ] **Step 4: Add next actions shim identity test**
|
||
|
||
Append this test to `tests/wf_mcp/workflow_surface/test_next_actions.py`:
|
||
|
||
```python
|
||
def test_workflow_surface_next_actions_shim_reexports_canonical_model() -> None:
|
||
from wf_api.next_actions import NextActions
|
||
from wf_mcp.workflow_surface.next_actions import NextActions as NextActionsShim
|
||
|
||
assert NextActionsShim is NextActions
|
||
```
|
||
|
||
- [ ] **Step 5: Run focused tests**
|
||
|
||
Run:
|
||
|
||
```powershell
|
||
uv run pytest tests/wf_mcp/test_workflow_wrapper_hints.py tests/wf_mcp/workflow_surface/test_next_actions.py tests/wf_api/test_import_direction.py -q
|
||
```
|
||
|
||
Expected: all pass.
|
||
|
||
---
|
||
|
||
## Task 7: Search For Remaining Canonical Import Opportunities
|
||
|
||
**Files:**
|
||
|
||
- Inspect only unless the search finds new low-risk direct consumers.
|
||
|
||
- [ ] **Step 1: Search old imports**
|
||
|
||
Run:
|
||
|
||
```powershell
|
||
rg -n "from \\.next_actions|from \\.wrapper_hints|from wf_mcp\\.workflow_surface\\.(next_actions|wrapper_hints)" src tests
|
||
```
|
||
|
||
Expected remaining matches:
|
||
|
||
```text
|
||
src/wf_mcp/workflow_surface/next_actions.py
|
||
src/wf_mcp/workflow_surface/wrapper_hints.py
|
||
tests/wf_mcp/test_workflow_wrapper_hints.py
|
||
tests/wf_mcp/workflow_surface/test_next_actions.py
|
||
```
|
||
|
||
If any other production module imports the old paths, update it to import from
|
||
`wf_api.next_actions` or `wf_api.wrapper_hints`.
|
||
|
||
- [ ] **Step 2: Search for accidental `wf_api -> wf_mcp` imports**
|
||
|
||
Run:
|
||
|
||
```powershell
|
||
rg -n "from wf_mcp|import wf_mcp|wf_mcp\\." src/wf_api
|
||
```
|
||
|
||
Expected: no matches.
|
||
|
||
---
|
||
|
||
## Task 8: Verification
|
||
|
||
- [ ] **Step 1: Run focused tests**
|
||
|
||
```powershell
|
||
uv run pytest tests/wf_api tests/wf_mcp/test_workflow_wrapper_hints.py tests/wf_mcp/workflow_surface/test_next_actions.py tests/wf_mcp/workflow_surface tests/wf_mcp/server/test_config.py -q
|
||
```
|
||
|
||
Expected: all pass.
|
||
|
||
- [ ] **Step 2: Run CLI tests that assert next_actions/wrapper_hints payloads**
|
||
|
||
```powershell
|
||
uv run pytest tests/wf_cli/test_discovery_lifecycle.py tests/wf_cli/test_run_deploy.py -q
|
||
```
|
||
|
||
Expected: all pass.
|
||
|
||
- [ ] **Step 3: Run ruff on touched files**
|
||
|
||
```powershell
|
||
uv run ruff check src/wf_api src/wf_mcp/workflow_surface/next_actions.py src/wf_mcp/workflow_surface/wrapper_hints.py src/wf_mcp/workflow_surface/handlers.py src/wf_mcp/workflow_surface/models.py tests/wf_mcp/test_workflow_wrapper_hints.py tests/wf_mcp/workflow_surface/test_next_actions.py tests/wf_api
|
||
```
|
||
|
||
Expected: all checks pass.
|
||
|
||
- [ ] **Step 4: Run basedpyright on touched files**
|
||
|
||
```powershell
|
||
uv run basedpyright --level error src/wf_api src/wf_mcp/workflow_surface/next_actions.py src/wf_mcp/workflow_surface/wrapper_hints.py src/wf_mcp/workflow_surface/handlers.py src/wf_mcp/workflow_surface/models.py tests/wf_mcp/test_workflow_wrapper_hints.py tests/wf_mcp/workflow_surface/test_next_actions.py tests/wf_api
|
||
```
|
||
|
||
Expected: `0 errors`.
|
||
|
||
- [ ] **Step 5: Optional full suite**
|
||
|
||
Run this if time allows:
|
||
|
||
```powershell
|
||
uv run pytest -q
|
||
```
|
||
|
||
Expected: full suite passes with the project’s existing skipped/xfailed counts.
|
||
|
||
---
|
||
|
||
## Self-Review Checklist
|
||
|
||
- `wf_api.wrapper_hints` imports no `wf_mcp`.
|
||
- `wf_api.next_actions` imports no `wf_mcp`.
|
||
- Old `wf_mcp.workflow_surface.wrapper_hints` import path still works.
|
||
- Old `wf_mcp.workflow_surface.next_actions` import path still works.
|
||
- `WorkflowSurfaceHandlers` imports canonical guidance helpers from `wf_api`.
|
||
- `wf_mcp.workflow_surface.models` imports canonical next-action models from `wf_api`.
|
||
- Wrapper hint behavior is unchanged.
|
||
- Next action behavior is unchanged.
|
||
- No public payload shape changed.
|
||
- No other workflow-surface helper moved in this slice.
|