Ctrl K
ComunidadGuías…

specs/011-dynamic-evaluation.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Spec: Dynamic Evaluation

## Status

Implemented.

## Scope

This spec defines Dagu dynamic evaluation for fields that explicitly opt in.

It does not make every shell syntax form part of the workflow language.

## Goal

Define what Dagu does when a field is marked dynamic-evaluated.

In this spec set, dynamic evaluation is available only for fields that opt in
explicitly, such as `params[].eval` and precondition `eval`.
No other field executes this command-substitution syntax as Dagu field
evaluation.

## Input

Input is a workflow YAML file accepted by the YAML schema spec.

Dynamic-evaluation validation extends `dagu validate` when that validation is implemented.
Validation parses dynamic-evaluation syntax, but it must not execute commands.

Example:

```yaml
params:
  - name: build_date
    type: string
    eval: `date +%Y%m%d`
steps:
  - name: print
    run: echo ${params.build_date}
```

## Evaluation pipeline

Dynamic evaluation runs these operations in order:

- Resolve Dagu value references such as `${params.name}`.
- Expand available environment variables according to the field's evaluation scope.
- Execute command substitutions.

Rules:

- Dagu expands value references before executing command substitutions.
- Dagu expands available environment variables such as `$HOME` and `${HOME}` according to the owning field's scope.
- Dagu executes command substitutions written in backtick form or `$()` form.
- Dagu inserts command stdout into the evaluated value after trimming surrounding whitespace.
- Backtick text and `$()` text in fields other than dynamic-evaluated fields are not dynamic evaluation.
- Dagu leaves them unchanged during dynamic evaluation.

## Command Substitution Syntax

Rules:

- A backtick command starts with `` ` `` and ends with the next unescaped `` ` ``.
- An escaped backtick is preserved literally.
- An unclosed backtick is preserved literally.
- A `$()` command starts with `$(` and ends with the next unescaped `)`.
- An escaped `)` inside `$()` command text is preserved literally.
- An unclosed `$()` command is preserved literally.
- Command substitutions must not be nested.
- The command text is passed to the configured shell.

## Shell execution

Command substitution bodies run through the configured shell.

| Rule | Behavior |
| --- | --- |
| Shell | Dagu's configured default shell, the scoped `SHELL`, or the platform fallback selected by the implementation. |
| Environment | The command inherits the evaluation scope available to the owning field. |
| Return value | Stdout, trimmed of surrounding whitespace. |
| Successful stderr | Captured and ignored. |
| Timeout | The implementation applies a short bounded timeout. |
| Sandbox | Dagu does not sandbox the command. |

Command side effects are real side effects.
If the command writes files, starts processes, or uses the network, those effects are outside the workflow result model.

Dynamic evaluation itself does not write workflow events, run logs, artifacts, or result files.

## Failures

Rules:

- A command substitution that exits with a non-zero status makes dynamic evaluation fail.
- A command substitution that times out makes dynamic evaluation fail.
- Each command substitution occurrence is evaluated independently.
- Spec 003 defines field-specific fallbacks, such as `params[].eval` falling back to `default`.
- Precondition `eval` has no fallback; a dynamic-evaluation failure is a precondition evaluation error.

## Outputs

When dynamic evaluation succeeds, Dagu inserts the evaluated value into the owning field.

Backtick text and `$()` text outside dynamic-evaluated fields remain part of the evaluated value.
A target runtime may still interpret them after Dagu starts that runtime.

## Errors

Passive notices:

- A supported Dagu-owned value reference that cannot resolve must preserve the original reference text.
- Explicit inspection surfaces must report a passive notice for that preserved reference.
- Braced text that does not match a supported Dagu-owned reference form remains ordinary string content under Spec 003.
- Preservation means Dagu leaves the original text unchanged.
- Dagu does not escape preserved text for a later shell or script interpreter.

Runtime errors:

- A failed command substitution must fail before the owning field is consumed unless the owning field defines a fallback.
- A timed-out command substitution must fail before the owning field is consumed unless the owning field defines a fallback.

## Examples

Parameter value from backtick substitution:

```yaml
params:
  - name: today
    type: string
    eval: `printf 20260131`
steps:
  - name: print
    run: echo ${params.today}
```

Parameter value from `$()` substitution:

```yaml
params:
  - name: today
    type: string
    eval: $(printf 20260131)
steps:
  - name: print
    run: echo ${params.today}
```

Parameter `eval` with Dagu references:

```yaml
params:
  - name: environment
    type: string
    default: prod
  - name: service_name
    type: string
    eval: `printf '%s-api' ${params.environment}`
steps:
  - name: print
    run: echo ${params.service_name}
```

Precondition `eval` matched with `expected`:

```yaml
steps:
  - name: gated
    preconditions:
      - eval: $(printf ready)
        expected: ready
    run: echo ready
```

Command substitution in ordinary value-resolved fields stays text for Dagu:

```yaml
env:
  TODAY: $(date)
```