Plan — scoped_context (variables): run, contract, designer¶
This document is the implementation plan for workflow scoped_context, focused on variables first. It extends ADR 0001 with milestones, deliverables, and acceptance criteria.
For narrative background (“easier run side vs designer”), keep reading; for execution order, see Workstreams & sequencing at the end.
Architecture (2026-06): variable values and types live in the orchestrator run context; the variables provider is stateless (operations only). See ADR 0008.
Scope¶
| In scope | Out of scope (later) |
|---|---|
Variables-oriented scoped_context (name, type, optional init) |
Non-variable scoped declarations (other providers) until schema exists |
Orchestrator merge into run context + type metadata (_scoped.declarations) |
Provider-side variable storage / Redis buckets |
| Dashboard: visibility → edit path | Replacing workflow YAML with registry-only storage |
Stateless variables.* operations via service_call |
Full static analysis of every payload binding at design time |
Source of truth remains scoped_context inside workflow YAML/JSON loaded by Orchestrator. Runtime values are in orchestrator context, not the provider.
Current baseline (implemented)¶
| Layer | What exists |
|---|---|
| Orchestrator | WorkflowDoc.scoped_context parsed; apply_scoped_context_to_run_context; reserved _scoped.* keys; workflow_run_scoped_context structured log (workflow, scoped_declaration_count, provider_service, scoped_context_applied); operand type check before variables.* service_call when payload_from binds a declared variable; X-Scoped-Declarations header on variables.* HTTP calls |
| Variables service | Stateless — variables.string_concat, variables.numbers_add, variables.scoped_context registry metadata; no set/get/list, no Redis |
| Dashboard | Banner on workflow header + Run tab; Code tab: hint + schema link, read-only banner, admin table editor for scoped_context; buildWorkflowYaml emits scoped_context; save validates via POST /api/runtime/validate-workflow; fetchScopedDeclarationSchema / listScopedDeclarationProviderNames + provider datalist (registry scoped_declarations) |
Deprecated / removed:
push_scoped_context_to_variables_provider/variables.setseeding- Dashboard
GET /api/runtime/variables-list/{root_run_id}(provider had no list endpoint) — to be removed from UI; use run context / trace instead
Workstream R — Run-time observability & ops¶
Goal: Operators and developers can see scoped declarations and merge outcome without reading logs blindly.
| ID | Deliverable | Acceptance criteria |
|---|---|---|
| R1 | Structured log at workflow run start (or immediately after context merge) | Done: Logger workflow, level INFO, message id workflow_run_scoped_context; extra fields: workflow, scoped_declaration_count, provider_service, scoped_context_applied (true when declarations merged); no secret values |
| R2 | Dashboard run overview (minimal) | Done (baseline): On Run tab for a selected run, fetch current workflow via GET /api/workflows/{name} and show the same read-only Scoped context banner as on the workflow header when scoped_context.variables is non-empty; subtitle clarifies it matches Design/Code. |
| R3 | ~~variables list for current root run id~~ | Superseded by ADR 0008 — values are in orchestrator context, not provider buckets. Optional future: show declared variables + current context slice from run ledger. |
| R4 | Docs: operator note | Done: Context variables; ADR 0008 |
Dependencies: R2 uses client-side GET /api/workflows/{name} when a run is selected (same payload as Design/Code); no trace-by-run endpoint required for the banner.
Workstream C — Capability contract & registry metadata¶
Goal: Designer can eventually render forms without hard-coding variables.service field lists (ADR 0001).
| ID | Deliverable | Acceptance criteria |
|---|---|---|
| C1 | Extend canonical doc Capability Provider Contract | Done: Section Workflow scoped declarations (metadata.designer.scoped_declarations) — schema_version, variable_row, provider_block; settled key name scoped_declarations |
| C2 | Variables service registration | Done: Service registration includes metadata.designer.scoped_declarations (Python _scoped_declarations_metadata() aligned with ScopedVariableDecl / provider block) |
| C3 | Dashboard helper (optional) | Done: fetchScopedDeclarationSchema(serviceName), listScopedDeclarationProviderNames() (registry services with metadata.designer.scoped_declarations); Code-tab provider field uses datalist populated from registry |
Dependencies: C1 before C2; C2 before Designer B3.
Workstream B — Dashboard designer¶
Goal: Edit scoped_context without raw YAML for common cases.
| Phase | ID | Deliverable | Acceptance criteria |
|---|---|---|---|
| B1 | B1 | Read-only everywhere useful | Done: Code tab shows read-only Scoped context banner when declarations exist (subtitle ties to generated YAML) |
| B2 | B2 | YAML/Code editor assist | Done: Hint + link to /static/schemas/workflow-scoped-context.json; wiki remains canonical narrative |
| B3 | B3 | Table UI | Done (MVP): Admins get table (+ variable, name/type/init, provider service_name text field); Apply updates in-memory workflow + YAML preview; persist via existing Code → Save (PUT). Registry-driven provider dropdown deferred (optional after C3) |
| B4 | B4 | Validation | Done: _validateScopedContextErrors in _validateWorkflow; Save YAML calls POST /api/runtime/validate-workflow → orchestrator /admin/validate |
Dependencies: B3 MVP shipped with fixed columns + provider text field; optional C3 + registry dropdown can replace provider input later.
Cross-cutting¶
| Topic | Action |
|---|---|
| Testing | Integration test: workflow with scoped_context + run → assert context contains init values and _scoped.declarations (variables_provider_test) |
| Security | Never log init.value if marked sensitive (future); internal APIs use authz consistent with dashboard admin |
| i18n | Solution language English for UI strings and docs |
| Type safety | Orchestrator checks declared type vs variables.* operation when payload_from references context:<declared-name>; provider receives X-Scoped-Declarations header |
Workstreams & sequencing¶
Recommended order:
- R1 + R4 — fast feedback loop for operators (logs + docs).
- R2 — improves daily debugging without designer work.
- C1 → C2 — unlocks generic designer.
- B1 → B2 — progressive UX on Code tab.
- B3 → B4 — full editing path.
Parallelism: R can proceed while C is drafted; B1–B2 can overlap R2**.
Open questions¶
- Whether child workflows (
workflow_call) should inherit parent scoped declarations in UI only — document behaviour (orchestrator already passes context). - Design-time warnings when a
variables.*step binds a declared variable of the wrong type (today: runtime check only forpayload_from: context:<name>).
Related documents¶
- ADR 0001 — Registry-driven declarations
- ADR 0008 — Stateless variables provider
- ADR 0003 — Workflow scope concept (inner scopes vs
scoped_context, connections) - ADR 0004 — scoped_context per scope (orchestrator) (nested
scoped_context, shadowing, parallel lanes) - ADR index
- Workflow YAML
- Context variables