diff --git a/.github/ISSUE_TEMPLATE/mcp-ticket.md b/.github/ISSUE_TEMPLATE/mcp-ticket.md new file mode 100644 index 00000000..d22c4b91 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/mcp-ticket.md @@ -0,0 +1,23 @@ +--- +name: MCP agent-loop ticket +about: Filed by the implementer/tester agent loop (see the iterate repo's CLAUDE.md) — not for human bug reports, use "Bug report" for those. +title: "" +labels: ["owner:implementer"] +--- + +**tool/endpoint:** which MCP tool or method this concerns + +**repro:** exact call made (tool name + params, or command run) + +**expected:** + +**actual:** + + diff --git a/CLAUDE.md b/CLAUDE.md index c7066661..3a6e311c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -154,6 +154,10 @@ docs/WORKSPACES.md, and docs/proposals/server-workspaces-complete.md for the lat rooted at the library rather than the workflow file. The library is `DW_PROMPT_DIR` / `--prompt-dir`, else `./prompts` if it exists, else found by walking up from the workflow file's directory +- A step's `result.subfolder` names a subfolder of the run directory for that step's + files - by convention `final` for the deliverable and `intermediate` for the rest; any + relative path (`shots/act-1`); `variable:`/`item:` allowed; no default. Mechanics under + *Result subfolders* in Critical Gotchas - A step carrying `for_each` (a list, or `variable:` naming one) is expanded by `expand_for_each` (`dw/for_each.py`) into one ordinary step per entry, named `@`, immediately after `replace_variables` in @@ -298,6 +302,36 @@ same reason - default setup cannot load a pack. `JobManager.realized` finds the file. `exports` is a reserved workspace name: `POST /api/jobs/{id}/export` gathers one finished job into `/exports//` and `GET /exports/.zip` streams it. +- **Result subfolders**: a step's `result.subfolder` (`dw/subfolders.py`) puts its files + in a subfolder of the run directory - `/final/x.mp4` - by convention `final` or + `intermediate`; the engine treats no name specially and there is no default. + `Workflow.step_output_dir` computes the directory once and hands it to both + `Result.save` and the pipeline wrapper, so a chain's `save_segments` spill follows it. + Shape is `SUBFOLDER_PATTERN` (the `output:` segment rule, so a subfolder is + `output:`-addressable up to `OUTPUT_REFERENCE_PATTERN`'s seven-segment ceiling), + checked by `subfolder_errors` in `validation_errors` after + `for_each` expansion and again at run time; containment is `validate_output_path` + against the run directory. Manifest entries and `step_end` carry `subfolder`. + `split_run_path` finds the run id anywhere in a path, so `strip_run_id` still groups a + workflow's runs. Gallery entries carry it too; `GET /api/gallery?subfolder=` and MCP + `list_gallery(subfolder=)` filter on it. The web UI reads the field only: + the gallery page offers a subfolder pick once any entry has one, and the + job page sections results under `final/` / `intermediate/` headings (or + whatever the step named) (`sectionBySubfolder`, `ui/src/lib/results.ts`), + unchanged for a run that chose none. `file_base_name` may not contain a + separator - + it is a name, not a path. + Every `workflows/templates/**` file with two or more saving steps + marks each one `final`/`intermediate` (`tests/test_template_subfolders.py` pins the rule; + `dw/workflows/` builtins stay unmarked - a role is the parent's to assign). That moved + the templates' outputs into `/final/` and `/intermediate/`: an + `output: