specs/019-sub-dag-working-directory.md
Rama main · réplica de lectura del repositorio original.
# Spec: Sub-DAG Working Directory
## Status
Implemented.
## Scope
This spec defines the default process working directory behavior for a child DAG
run started by `dag.run`.
It covers:
- child DAG runs started by a normal `dag.run` step
- represented child DAG runs started by `parallel` with `action: dag.run`
- the interaction between child run work directories and explicit
`working_dir` configuration
- observable behavior of relative file writes inside child DAG steps
This spec does not define:
- `parallel` item expansion, duplicate coalescing, or aggregate outputs
- `dag.enqueue` queue processing behavior
- scheduler, coordinator, worker, or storage internals
- physical storage layout for run work directories
- automatic cleanup of work directories
- a fresh work directory for each retry attempt
- new YAML fields for inheriting or sharing parent working directories
## Goal
Child DAG runs can be launched concurrently without accidental relative-path
collisions.
A workflow author can rely on this rule: a child DAG that does not declare a
working directory writes relative files into that child run's own work
directory, not into the parent step's current working directory.
## Related Specs
- Step run: [Spec 013: Step Run](013-step-run.md)
- Built-in run context: [Spec 017: Built-In Run Context](017-built-in-run-context.md)
- Parallel fan-out: [Spec 018: Parallel Fan-Out and Foreach Iteration](018-parallel-and-foreach.md)
## Terms
A parent DAG run is the DAG run that contains the `dag.run` step.
A child DAG run is the DAG run started by a `dag.run` step.
A represented child DAG run is a child run represented by `parallel` after item
expansion and duplicate coalescing under Spec 018.
A child run work directory is the per-run work directory exposed to the child
DAG as `DAG_RUN_WORK_DIR` and `${context.paths.work_dir}`.
An explicit child working directory is a `working_dir` value declared by the
child DAG document, by child DAG base configuration, or by a step inside the
child DAG.
## Behavior
### Default Child Working Directory
- Every child DAG run has its own child run work directory.
- The child run work directory is scoped to the child DAG run, not to the parent
DAG run.
- A child DAG run that does not have an explicit child working directory must
use the child run work directory as the default process working directory for
its steps.
- Starting a child DAG run must not implicitly set the child DAG's explicit
`working_dir` from the parent step process working directory.
- Starting a child DAG run must not implicitly set the child DAG's explicit
`working_dir` from the parent DAG run work directory.
- The parent step process working directory and the child run work directory may
be the same path only when workflow-authored configuration explicitly selects
the same path.
- A child DAG step process sees `DAG_RUN_WORK_DIR` for the child DAG run, not
for the parent DAG run.
- `${context.paths.work_dir}` in a child DAG run resolves to the child run work
directory.
### Explicit Working Directory
- Step-level `working_dir` inside the child DAG has highest precedence for that
child step.
- An explicit root `working_dir` in the child DAG changes the default process
working directory for child steps that do not declare step-level
`working_dir`.
- An explicit `working_dir` inherited through child DAG base configuration is
explicit child working directory configuration.
- Dagu must not ignore, rewrite, or isolate an explicit child working directory
solely because the child DAG was started by `dag.run`.
- A workflow that needs parent and child steps to share a directory must set the
child working directory explicitly.
### Parallel Child Runs
- Each represented child DAG run started by a `parallel` `dag.run` step has its
own child run work directory.
- Distinct represented child DAG runs in the same `parallel` step must not share
the same default child run work directory.
- If `parallel` duplicate coalescing represents multiple item slots as one child
DAG run, that represented child run has one child run work directory.
- A relative file created by one represented child DAG run must not collide with
the same relative file created by another represented child DAG run unless
workflow-authored explicit working directory configuration selects a shared
path.
### Retry Behavior
- This spec does not require a fresh process working directory for each retry
attempt.
- Retrying a child DAG run may reuse that child run's work directory unless
another spec defines attempt-scoped working directory behavior.
## Errors
Validation errors for malformed `working_dir` fields are defined by the owning
YAML schema and step run specs.
Runtime must fail when the selected process working directory for a child step
cannot be used as a working directory.
Runtime must not fail solely because the parent step process working directory
is unavailable to the child DAG when the child DAG has no explicit
`working_dir`.
## Examples
### Parallel Children Do Not Collide
Workflow:
```yaml
steps:
- id: fanout
action: dag.run
with:
dag: child
params: item=${ITEM}
parallel:
- a
- b
---
name: child
steps:
- id: write
run: |
printf '%s\n' "$DAG_RUN_ID" > result.txt
pwd > pwd.txt
```
Expected behavior:
- The parent step starts two represented child DAG runs.
- Both child DAG runs succeed.
- Each child run writes its own `result.txt`.
- The two child `pwd.txt` files record different default working directories.
### Parent Working Directory Is Not Inherited
Workflow:
```yaml
working_dir: parent-work
steps:
- id: child
action: dag.run
with:
dag: child
---
name: child
steps:
- id: inspect
run: |
pwd > pwd.txt
printf '%s\n' "$DAG_RUN_WORK_DIR" > run-work-dir.txt
```
Expected behavior:
- The child `pwd.txt` value is the child run work directory.
- The child `run-work-dir.txt` value is the same path as `pwd.txt`.
- The child default working directory is not `parent-work`.
### Explicit Child Working Directory Wins
Workflow:
```yaml
steps:
- id: child
action: dag.run
with:
dag: child
---
name: child
working_dir: shared-child-work
steps:
- id: inspect
run: pwd > pwd.txt
```
Expected behavior:
- The child step runs in `shared-child-work`.
- The explicit child `working_dir` takes precedence over the child run work
directory.