docs: auto-derive declared_outputs from script scan

This commit is contained in:
2026-07-21 10:05:45 +01:00
parent d9d241f83b
commit 56f06b9eaf
@@ -4,7 +4,7 @@ Date: 2026-07-21
## Summary
Three related additions to the workflow step system:
Four related additions to the workflow step system:
1. **Ad-hoc steps** — steps defined inline in a single workflow, not written to the
shared step library.
@@ -12,6 +12,8 @@ Three related additions to the workflow step system:
target the shared library or a workflow as an inline ad-hoc step.
3. **Default steps** — JSON files in a bind-mounted directory, seeded into the
library on boot and re-syncable on demand. Org-ready for a future SaaS plan.
4. **Auto-derived outputs**`declared_outputs` is scanned from the script
(writes to `$WORKFLOW_ENV`) instead of being entered by hand.
Existing model: shared steps live in the `workflow_steps` collection; a
`Workflow.Steps[]` is a list of `WorkflowStepRef` that reference a library step by
@@ -182,7 +184,53 @@ Signature stays global today. When Orgs land, `SeedDefaultSteps(orgID)` seeds
per-org and the upsert key becomes `{ org_id, slug, source }`. No schema churn
blocks that later change.
## 5. Web
## 5. Auto-derived outputs
Today `WorkflowStep.DeclaredOutputs` is entered by hand and consumed only by the
UI (no runtime reads it — outputs are captured at run time by `parseEnvFile` on
the agent). Replace manual entry with a server-side scan of the script.
At run time the agent exposes an env file path in `$WORKFLOW_ENV` (bash) /
`$env:WORKFLOW_ENV` (powershell); a step emits an output by appending a
`KEY=value` line to it, e.g. `echo "test=123" >> $WORKFLOW_ENV`.
### Scanner
`services.DeriveOutputs(script string) []string`:
- Scan line by line. For each line that references `WORKFLOW_ENV`, extract every
`KEY=` assignment target on that line, where `KEY` matches
`[A-Za-z_][A-Za-z0-9_]*`.
- Covers the common forms across both interpreters (line mentions `WORKFLOW_ENV`
and contains `KEY=...`):
- `echo "test=123" >> $WORKFLOW_ENV`
- `echo "test=123" >> "$WORKFLOW_ENV"`
- `printf 'k=v\n' >> $WORKFLOW_ENV`
- `"k=v" >> $env:WORKFLOW_ENV` / `Add-Content $env:WORKFLOW_ENV "k=v"`
- Deduplicate, preserve first-seen order. Best-effort heuristic — false positives
are acceptable (they only widen the documented output list); it never affects
what the agent actually captures.
### Wiring
- `CreateStep` and `UpdateStep` set `DeclaredOutputs = DeriveOutputs(s.Script)`,
ignoring any client-sent value.
- Inline ad-hoc steps: `DeriveOutputs` is applied when the workflow is saved (for
each `ref.Inline`), so inline outputs are derived too.
- `ParseStepDoc` (import) also derives outputs, so `declared_outputs` in an
imported/exported file is informational and always recomputed on import.
- `SeedDefaultSteps` derives outputs the same way when upserting.
`DeclaredOutputs` stays in the model and JSON (still shown in the UI and used to
wire step-to-step input references), it is just no longer user-authored.
### Web
The step editor's "declared outputs" input becomes a read-only, auto-populated
display (derived from the script, refreshed on save / on script edit). No manual
add/remove.
## 6. Web
`web/app/workflows/[id]/page.tsx` and the steps list page.
@@ -208,6 +256,9 @@ blocks that later change.
- `SeedDefaultSteps`: insert-then-update idempotency; user steps untouched;
user-edited default step reverted on re-sync; counts correct.
- `DeleteStep` cascade ignores ad-hoc refs.
- `DeriveOutputs`: extracts keys from each interpreter form above, dedupes,
preserves order, ignores lines not referencing `WORKFLOW_ENV`; create/update/
import/seed all populate `declared_outputs` from it and ignore client input.
## Out of scope