docs: make lda report plan authoring-first
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
|
||||
**Goal:** Add a deterministic `examples/lda_report_workflow/` case study that exercises document reading, report synthesis, a typed human approval interrupt, issue creation, resume, trace, and final output.
|
||||
|
||||
**Architecture:** Implement three trusted Python sources in one example package: `local.lda_docs`, `local.lda_report`, and `local.issue_board`. Ship a raw workflow plan that uses the new self-describing interrupt contract, plus tests that run artifact, deployment, interrupt inspection, resume, issue creation, and final output through the product API.
|
||||
**Architecture:** Implement three trusted Python sources in one example package: `local.lda_docs`, `local.lda_report`, and `local.issue_board`. Author the graph with `wf_authoring.WorkflowBuilder`, generate a committed raw workflow plan from the compiled `Workflow`, and test artifact, deployment, interrupt inspection, resume, issue creation, and final output through the product API.
|
||||
|
||||
**Tech Stack:** Python 3.14, Pydantic models, static Python workflow sources, raw workflow plans, `wf_config`, `wf_server`, pytest.
|
||||
**Tech Stack:** Python 3.14, Pydantic models, `wf_authoring.WorkflowBuilder`, static Python workflow sources, generated raw workflow plans, `wf_config`, `wf_server`, pytest.
|
||||
|
||||
---
|
||||
|
||||
@@ -36,9 +36,10 @@ examples/lda_report_workflow/
|
||||
document_source.py
|
||||
report_source.py
|
||||
issue_board_source.py
|
||||
build_workflow.py
|
||||
run-input.json
|
||||
wf.config.json
|
||||
workflow.plan.json
|
||||
workflow.plan.json # generated by build_workflow.py and committed
|
||||
```
|
||||
|
||||
Create tests:
|
||||
@@ -98,7 +99,8 @@ The interrupt:
|
||||
- request payload contains rendered report markdown and proposed issues
|
||||
- resume payload contains `approved`, `selected_issue_ids`, and optional
|
||||
`comment`
|
||||
- request/resume schemas are explicit JSON Schema objects in the raw plan
|
||||
- request/resume schemas are explicit JSON Schema objects authored in
|
||||
`build_workflow.py` and generated into the raw plan
|
||||
|
||||
---
|
||||
|
||||
@@ -981,11 +983,12 @@ git commit -m "feat: add local issue board source example"
|
||||
|
||||
---
|
||||
|
||||
### Task 5: Add Config, Run Input, And Raw Workflow Plan
|
||||
### Task 5: Add Config, Run Input, And Workflow Builder
|
||||
|
||||
**Files:**
|
||||
- Create: `examples/lda_report_workflow/wf.config.json`
|
||||
- Create: `examples/lda_report_workflow/run-input.json`
|
||||
- Create: `examples/lda_report_workflow/build_workflow.py`
|
||||
- Create: `examples/lda_report_workflow/workflow.plan.json`
|
||||
- Modify: `tests/examples/test_lda_report_workflow_example.py`
|
||||
|
||||
@@ -1052,12 +1055,17 @@ Create `examples/lda_report_workflow/run-input.json`:
|
||||
|
||||
- [ ] **Step 3: Add config loading test**
|
||||
|
||||
Append to `tests/examples/test_lda_report_workflow_example.py`:
|
||||
Add these imports to the top import block in
|
||||
`tests/examples/test_lda_report_workflow_example.py`:
|
||||
|
||||
```python
|
||||
from wf_config import load_workflow_config
|
||||
from wf_server.config import build_workflow_server_from_workflow_config
|
||||
```
|
||||
|
||||
Append this test:
|
||||
|
||||
```python
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_lda_report_workflow_config_loads_sources(tmp_path: Path) -> None:
|
||||
@@ -1082,203 +1090,276 @@ uv run pytest tests/examples/test_lda_report_workflow_example.py::test_lda_repor
|
||||
|
||||
Expected: pass.
|
||||
|
||||
- [ ] **Step 5: Create raw workflow plan**
|
||||
- [ ] **Step 5: Create workflow builder**
|
||||
|
||||
Create `examples/lda_report_workflow/workflow.plan.json` with this content:
|
||||
Create `examples/lda_report_workflow/build_workflow.py`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "lda_report_case_study",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"selected_documents": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"board_path": {"type": "string"}
|
||||
},
|
||||
"required": ["selected_documents", "board_path"]
|
||||
},
|
||||
"state_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"documents": {"type": "array"},
|
||||
"analysis": {"type": "array"},
|
||||
"report": {"type": "object"},
|
||||
"report_markdown": {"type": "string"},
|
||||
"proposed_issues": {"type": "array"},
|
||||
"selected_issue_ids": {"type": "array"},
|
||||
"approval_comment": {"type": "string"},
|
||||
"approved": {"type": "boolean"},
|
||||
"created_issues": {"type": "array"},
|
||||
"final_markdown": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"output_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"approved": {"type": "boolean"},
|
||||
"markdown": {"type": "string"},
|
||||
"created_issues": {"type": "array"},
|
||||
"selected_issue_ids": {"type": "array"}
|
||||
}
|
||||
},
|
||||
"output": [
|
||||
```python
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from wf_api.models import RawWorkflowPlan
|
||||
from wf_authoring import WorkflowBuilder
|
||||
from wf_core import Workflow
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
|
||||
WORKFLOW_OUTPUT = [
|
||||
{"path": "state.approved", "target": "approved"},
|
||||
{"path": "state.final_markdown", "target": "markdown"},
|
||||
{"path": "state.created_issues", "target": "created_issues"},
|
||||
{"path": "state.selected_issue_ids", "target": "selected_issue_ids"}
|
||||
],
|
||||
"outcomes": ["completed", "cancelled"],
|
||||
"start": "read_docs",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "read_docs",
|
||||
"type": "node",
|
||||
"node": "local.lda_docs.read_documents",
|
||||
"input": [
|
||||
{"path": "input.selected_documents", "target": "names"}
|
||||
],
|
||||
"output": [
|
||||
{"source": "documents", "target": "state.documents"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "analyze",
|
||||
"type": "node",
|
||||
"node": "local.lda_report.analyze_documents",
|
||||
"input": [
|
||||
{"path": "state.documents", "target": "documents"}
|
||||
],
|
||||
"output": [
|
||||
{"source": "analysis", "target": "state.analysis"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "build_report",
|
||||
"type": "node",
|
||||
"node": "local.lda_report.build_report",
|
||||
"input": [
|
||||
{"path": "state.analysis", "target": "analysis"}
|
||||
],
|
||||
"output": [
|
||||
{"source": "report", "target": "state.report"},
|
||||
{"source": "markdown", "target": "state.report_markdown"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "draft_issues",
|
||||
"type": "node",
|
||||
"node": "local.lda_report.create_issue_drafts",
|
||||
"input": [
|
||||
{"path": "state.report", "target": "report"}
|
||||
],
|
||||
"output": [
|
||||
{"source": "issues", "target": "state.proposed_issues"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "review_issues",
|
||||
"type": "interrupt",
|
||||
"kind": "issue_review",
|
||||
"request": [
|
||||
{"path": "state.report_markdown", "target": "report_markdown"},
|
||||
{"path": "state.proposed_issues", "target": "proposed_issues"}
|
||||
],
|
||||
"resume": [
|
||||
{"source": "approved", "target": "state.approved"},
|
||||
{"source": "selected_issue_ids", "target": "state.selected_issue_ids"},
|
||||
{"source": "comment", "target": "state.approval_comment"}
|
||||
],
|
||||
"outcomes": ["submitted", "cancelled"],
|
||||
"request_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"report_markdown": {"type": "string"},
|
||||
"proposed_issues": {"type": "array"}
|
||||
{"path": "state.selected_issue_ids", "target": "selected_issue_ids"},
|
||||
]
|
||||
|
||||
|
||||
def build_workflow() -> Workflow:
|
||||
"""Build the demo workflow with the public authoring API.
|
||||
|
||||
`WorkflowBuilder` does not yet expose a workflow-output setter, so this
|
||||
module adds the final output projection in `_with_workflow_output()` after
|
||||
compiling the graph. Keep that seam small and validated.
|
||||
"""
|
||||
builder = WorkflowBuilder(
|
||||
name="lda_report_case_study",
|
||||
input_schema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"selected_documents": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
},
|
||||
"board_path": {"type": "string"},
|
||||
},
|
||||
"required": ["selected_documents", "board_path"],
|
||||
},
|
||||
"required": ["report_markdown", "proposed_issues"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"resume_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"approved": {"type": "boolean"},
|
||||
"selected_issue_ids": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"comment": {"type": "string"}
|
||||
state_schema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"documents": {"type": "array"},
|
||||
"analysis": {"type": "array"},
|
||||
"report": {"type": "object"},
|
||||
"report_markdown": {"type": "string"},
|
||||
"proposed_issues": {"type": "array"},
|
||||
"selected_issue_ids": {"type": "array"},
|
||||
"approval_comment": {"type": "string"},
|
||||
"approved": {"type": "boolean"},
|
||||
"created_issues": {"type": "array"},
|
||||
"final_markdown": {"type": "string"},
|
||||
},
|
||||
},
|
||||
"required": ["approved", "selected_issue_ids"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "create_issues",
|
||||
"type": "node",
|
||||
"node": "local.issue_board.create_issues",
|
||||
"input": [
|
||||
{"path": "state.proposed_issues", "target": "issues"},
|
||||
{"path": "state.selected_issue_ids", "target": "selected_issue_ids"},
|
||||
{"path": "input.board_path", "target": "board_path"}
|
||||
],
|
||||
"output": [
|
||||
{"source": "created_issues", "target": "state.created_issues"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "finalise",
|
||||
"type": "node",
|
||||
"node": "local.lda_report.finalise_report",
|
||||
"input": [
|
||||
{"path": "state.report", "target": "report"},
|
||||
{"path": "state.created_issues", "target": "created_issues"},
|
||||
{"path": "state.approved", "target": "approved"},
|
||||
{"path": "state.selected_issue_ids", "target": "selected_issue_ids"},
|
||||
{"path": "state.approval_comment", "target": "comment"}
|
||||
],
|
||||
"output": [
|
||||
{"source": "markdown", "target": "state.final_markdown"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "revision_requested",
|
||||
"type": "node",
|
||||
"node": "local.lda_report.record_revision_request",
|
||||
"input": [
|
||||
{"path": "state.approval_comment", "target": "comment"}
|
||||
],
|
||||
"output": [
|
||||
{"source": "approved", "target": "state.approved"},
|
||||
{"source": "markdown", "target": "state.final_markdown"},
|
||||
{"source": "created_issues", "target": "state.created_issues"},
|
||||
{"source": "selected_issue_ids", "target": "state.selected_issue_ids"}
|
||||
]
|
||||
},
|
||||
{"id": "end_completed", "type": "end", "outcome": "completed"},
|
||||
{"id": "end_cancelled", "type": "end", "outcome": "cancelled"}
|
||||
],
|
||||
"edges": [
|
||||
{"from": "read_docs", "outcome": "ok", "to": "analyze"},
|
||||
{"from": "analyze", "outcome": "ok", "to": "build_report"},
|
||||
{"from": "build_report", "outcome": "ok", "to": "draft_issues"},
|
||||
{"from": "draft_issues", "outcome": "ok", "to": "review_issues"},
|
||||
{"from": "review_issues", "outcome": "submitted", "to": "create_issues"},
|
||||
{"from": "review_issues", "outcome": "cancelled", "to": "revision_requested"},
|
||||
{"from": "create_issues", "outcome": "ok", "to": "finalise"},
|
||||
{"from": "finalise", "outcome": "ok", "to": "end_completed"},
|
||||
{"from": "revision_requested", "outcome": "ok", "to": "end_cancelled"}
|
||||
]
|
||||
}
|
||||
output_schema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"approved": {"type": "boolean"},
|
||||
"markdown": {"type": "string"},
|
||||
"created_issues": {"type": "array"},
|
||||
"selected_issue_ids": {"type": "array"},
|
||||
},
|
||||
},
|
||||
outcomes=["completed", "cancelled"],
|
||||
)
|
||||
|
||||
read_docs = builder.use_ref(
|
||||
"local.lda_docs.read_documents",
|
||||
id="read_docs",
|
||||
input=[{"path": "input.selected_documents", "target": "names"}],
|
||||
output=[{"source": "documents", "target": "state.documents"}],
|
||||
)
|
||||
analyze = builder.use_ref(
|
||||
"local.lda_report.analyze_documents",
|
||||
id="analyze",
|
||||
input=[{"path": "state.documents", "target": "documents"}],
|
||||
output=[{"source": "analysis", "target": "state.analysis"}],
|
||||
)
|
||||
build_report = builder.use_ref(
|
||||
"local.lda_report.build_report",
|
||||
id="build_report",
|
||||
input=[{"path": "state.analysis", "target": "analysis"}],
|
||||
output=[
|
||||
{"source": "report", "target": "state.report"},
|
||||
{"source": "markdown", "target": "state.report_markdown"},
|
||||
],
|
||||
)
|
||||
draft_issues = builder.use_ref(
|
||||
"local.lda_report.create_issue_drafts",
|
||||
id="draft_issues",
|
||||
input=[{"path": "state.report", "target": "report"}],
|
||||
output=[{"source": "issues", "target": "state.proposed_issues"}],
|
||||
)
|
||||
review_issues = builder.interrupt(
|
||||
id="review_issues",
|
||||
kind="issue_review",
|
||||
request=[
|
||||
{"path": "state.report_markdown", "target": "report_markdown"},
|
||||
{"path": "state.proposed_issues", "target": "proposed_issues"},
|
||||
],
|
||||
resume=[
|
||||
{"source": "approved", "target": "state.approved"},
|
||||
{"source": "selected_issue_ids", "target": "state.selected_issue_ids"},
|
||||
{"source": "comment", "target": "state.approval_comment"},
|
||||
],
|
||||
outcomes=["submitted", "cancelled"],
|
||||
request_schema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"report_markdown": {"type": "string"},
|
||||
"proposed_issues": {"type": "array"},
|
||||
},
|
||||
"required": ["report_markdown", "proposed_issues"],
|
||||
"additionalProperties": False,
|
||||
},
|
||||
resume_schema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"approved": {"type": "boolean"},
|
||||
"selected_issue_ids": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
},
|
||||
"comment": {"type": "string"},
|
||||
},
|
||||
"required": ["approved", "selected_issue_ids"],
|
||||
"additionalProperties": False,
|
||||
},
|
||||
)
|
||||
create_issues = builder.use_ref(
|
||||
"local.issue_board.create_issues",
|
||||
id="create_issues",
|
||||
input=[
|
||||
{"path": "state.proposed_issues", "target": "issues"},
|
||||
{"path": "state.selected_issue_ids", "target": "selected_issue_ids"},
|
||||
{"path": "input.board_path", "target": "board_path"},
|
||||
],
|
||||
output=[{"source": "created_issues", "target": "state.created_issues"}],
|
||||
)
|
||||
finalise = builder.use_ref(
|
||||
"local.lda_report.finalise_report",
|
||||
id="finalise",
|
||||
input=[
|
||||
{"path": "state.report", "target": "report"},
|
||||
{"path": "state.created_issues", "target": "created_issues"},
|
||||
{"path": "state.approved", "target": "approved"},
|
||||
{"path": "state.selected_issue_ids", "target": "selected_issue_ids"},
|
||||
{"path": "state.approval_comment", "target": "comment"},
|
||||
],
|
||||
output=[{"source": "markdown", "target": "state.final_markdown"}],
|
||||
)
|
||||
revision_requested = builder.use_ref(
|
||||
"local.lda_report.record_revision_request",
|
||||
id="revision_requested",
|
||||
input=[{"path": "state.approval_comment", "target": "comment"}],
|
||||
output=[
|
||||
{"source": "approved", "target": "state.approved"},
|
||||
{"source": "markdown", "target": "state.final_markdown"},
|
||||
{"source": "created_issues", "target": "state.created_issues"},
|
||||
{"source": "selected_issue_ids", "target": "state.selected_issue_ids"},
|
||||
],
|
||||
)
|
||||
end_completed = builder.end("completed", id="end_completed")
|
||||
end_cancelled = builder.end("cancelled", id="end_cancelled")
|
||||
|
||||
builder.set_entry_point(read_docs)
|
||||
builder.connect(read_docs, "ok", analyze)
|
||||
builder.connect(analyze, "ok", build_report)
|
||||
builder.connect(build_report, "ok", draft_issues)
|
||||
builder.branch(
|
||||
review_issues,
|
||||
{
|
||||
"submitted": create_issues,
|
||||
"cancelled": revision_requested,
|
||||
},
|
||||
)
|
||||
builder.connect(create_issues, "ok", finalise)
|
||||
builder.connect(finalise, "ok", end_completed)
|
||||
builder.connect(revision_requested, "ok", end_cancelled)
|
||||
return _with_workflow_output(builder.compile())
|
||||
|
||||
|
||||
def _with_workflow_output(workflow: Workflow) -> Workflow:
|
||||
payload = workflow.model_dump(mode="json", by_alias=True)
|
||||
payload["output"] = WORKFLOW_OUTPUT
|
||||
return Workflow.model_validate(payload)
|
||||
|
||||
|
||||
def workflow_plan_payload() -> dict[str, Any]:
|
||||
payload = build_workflow().model_dump(mode="json", by_alias=True)
|
||||
payload.pop("node_defs", None)
|
||||
RawWorkflowPlan.model_validate(payload)
|
||||
return payload
|
||||
|
||||
|
||||
def write_plan(path: Path = HERE / "workflow.plan.json") -> None:
|
||||
payload = workflow_plan_payload()
|
||||
path.write_text(
|
||||
json.dumps(payload, indent=2, sort_keys=True) + "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
write_plan()
|
||||
```
|
||||
|
||||
- [ ] **Step 6: Commit config and plan**
|
||||
- [ ] **Step 6: Generate raw workflow plan**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
git add examples/lda_report_workflow/wf.config.json examples/lda_report_workflow/run-input.json examples/lda_report_workflow/workflow.plan.json tests/examples/test_lda_report_workflow_example.py
|
||||
git commit -m "feat: add lda report workflow plan"
|
||||
uv run python examples/lda_report_workflow/build_workflow.py
|
||||
```
|
||||
|
||||
Expected: `examples/lda_report_workflow/workflow.plan.json` is written.
|
||||
|
||||
- [ ] **Step 7: Add builder/generator regression test**
|
||||
|
||||
Add these imports to the top import block:
|
||||
|
||||
```python
|
||||
import json
|
||||
|
||||
from examples.lda_report_workflow.build_workflow import (
|
||||
build_workflow,
|
||||
workflow_plan_payload,
|
||||
)
|
||||
from wf_api.models import RawWorkflowPlan
|
||||
```
|
||||
|
||||
Append this test:
|
||||
|
||||
```python
|
||||
|
||||
def test_lda_report_workflow_builder_generates_committed_raw_plan() -> None:
|
||||
workflow = build_workflow()
|
||||
payload = workflow_plan_payload()
|
||||
committed = json.loads(
|
||||
(EXAMPLE_DIR / "workflow.plan.json").read_text(encoding="utf-8")
|
||||
)
|
||||
validated = RawWorkflowPlan.model_validate(payload)
|
||||
|
||||
assert workflow.name == "lda_report_case_study"
|
||||
assert validated.name == "lda_report_case_study"
|
||||
assert any(node.id == "review_issues" for node in validated.nodes)
|
||||
assert payload == committed
|
||||
```
|
||||
|
||||
- [ ] **Step 8: Run builder and config tests**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
uv run pytest tests/examples/test_lda_report_workflow_example.py::test_lda_report_workflow_config_loads_sources tests/examples/test_lda_report_workflow_example.py::test_lda_report_workflow_builder_generates_committed_raw_plan -q -n0
|
||||
```
|
||||
|
||||
Expected: pass.
|
||||
|
||||
- [ ] **Step 9: Commit config, builder, and plan**
|
||||
|
||||
```powershell
|
||||
git add examples/lda_report_workflow/wf.config.json examples/lda_report_workflow/run-input.json examples/lda_report_workflow/build_workflow.py examples/lda_report_workflow/workflow.plan.json tests/examples/test_lda_report_workflow_example.py
|
||||
git commit -m "feat: add lda report workflow builder"
|
||||
```
|
||||
|
||||
---
|
||||
@@ -1290,12 +1371,10 @@ git commit -m "feat: add lda report workflow plan"
|
||||
|
||||
- [ ] **Step 1: Add full lifecycle test**
|
||||
|
||||
Append to `tests/examples/test_lda_report_workflow_example.py`:
|
||||
Append to `tests/examples/test_lda_report_workflow_example.py`. Do not add a
|
||||
second `import json`; Task 5 already added it to the top import block.
|
||||
|
||||
```python
|
||||
import json
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_lda_report_workflow_artifact_interrupt_resume_path(tmp_path: Path) -> None:
|
||||
config = load_workflow_config(EXAMPLE_DIR / "wf.config.json")
|
||||
@@ -1486,6 +1565,15 @@ It does not call Google Drive, email, GitHub, or an LLM.
|
||||
proposed issue drafts, and finalises the report.
|
||||
- `local.issue_board`: writes selected issues to a local JSON file.
|
||||
|
||||
## Workflow Definition
|
||||
|
||||
`workflow.plan.json` is generated from `build_workflow.py`. After changing the
|
||||
graph, regenerate and review the raw plan:
|
||||
|
||||
```powershell
|
||||
uv run python examples/lda_report_workflow/build_workflow.py
|
||||
```
|
||||
|
||||
## Product Path
|
||||
|
||||
From the repository root:
|
||||
@@ -1579,14 +1667,17 @@ If either `docs/add/...` file was not changed, omit it from `git add`.
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
uv run python examples/lda_report_workflow/build_workflow.py
|
||||
git diff --exit-code examples/lda_report_workflow/workflow.plan.json
|
||||
uv run pytest tests/examples/test_lda_report_workflow_example.py tests/wf_sources_python/test_loader.py -q -n0
|
||||
uv run ruff check examples/lda_report_workflow tests/examples/test_lda_report_workflow_example.py
|
||||
uv run ruff format --check examples/lda_report_workflow tests/examples/test_lda_report_workflow_example.py
|
||||
uv run basedpyright --level error examples/lda_report_workflow tests/examples/test_lda_report_workflow_example.py
|
||||
```
|
||||
|
||||
Expected: all pass. If `basedpyright` reports import-package issues for the
|
||||
example package, add `examples/lda_report_workflow/__init__.py` and rerun.
|
||||
Expected: generation exits 0, `git diff --exit-code` reports no generated-plan
|
||||
diff, and all checks pass. If `basedpyright` reports import-package issues for
|
||||
the example package, add `examples/lda_report_workflow/__init__.py` and rerun.
|
||||
|
||||
- [ ] **Step 2: Smoke the CLI path**
|
||||
|
||||
@@ -1638,7 +1729,7 @@ Spec coverage:
|
||||
|
||||
- deterministic documents: Task 1;
|
||||
- first-party document/report/issue-board sources: Tasks 2-4;
|
||||
- raw plan and config: Task 5;
|
||||
- authoring builder, generated raw plan, and config: Task 5;
|
||||
- typed issue-review interrupt and resume: Task 6;
|
||||
- product runbook and roadmap: Task 7;
|
||||
- final verification/archive: Task 8.
|
||||
|
||||
Reference in New Issue
Block a user