Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
149 lines
5.7 KiB
Markdown
149 lines
5.7 KiB
Markdown
# DESIGN-0.35.0 — Workflow Product
|
|
|
|
Transforms the workflow engine from a linear stage-runner into a
|
|
product-grade automation tool. Seven changesets covering conditional
|
|
routing, AI-triggered routing, data pipeline hooks, progressive forms,
|
|
conditional fields, structured review, and a monitoring dashboard.
|
|
|
|
Depends on: v0.34.0 (Data Portability), v0.31.2 (Team Workflows),
|
|
v0.29.0 (Starlark Sandbox).
|
|
|
|
## Schema Changes
|
|
|
|
Migrations modified in-place (DB rebuild required):
|
|
|
|
**005_channels.sql** — add `stage_entered_at` (PG: `TIMESTAMPTZ`,
|
|
SQLite: `TEXT`). Tracks when the current stage was entered for SLA
|
|
computation. Also add index `idx_channels_workflow_active` on
|
|
`(workflow_id, workflow_status)` for monitoring queries.
|
|
|
|
**018_workflows.sql** — add `sla_seconds INTEGER` to `workflow_stages`.
|
|
Add `review_comments` (PG: `JSONB DEFAULT '[]'`, SQLite: `TEXT
|
|
DEFAULT '[]'`) to `workflow_assignments`.
|
|
|
|
No new migration files. No new tables.
|
|
|
|
## Conditional Routing Engine
|
|
|
|
**File:** `server/workflow/routing.go`
|
|
|
|
The existing advance logic hardcoded `nextStage = currentStage + 1`.
|
|
The routing engine replaces this with condition evaluation:
|
|
|
|
1. Parse `transition_rules.conditions[]` from the departing stage
|
|
2. Evaluate each condition against accumulated `stage_data`
|
|
3. First match → resolve `target_stage` (by name or ordinal)
|
|
4. No match → fallback to `ordinal + 1`
|
|
|
|
**Expression format:** `{field, op, value, target_stage}`. Operators:
|
|
`eq`, `neq`, `gt`, `lt`, `gte`, `lte`, `in`, `contains`, `exists`,
|
|
`not_exists`. Loose equality via `fmt.Sprintf("%v")` comparison.
|
|
Numeric comparison extracts `float64` from both sides.
|
|
|
|
**Wiring:** `ResolveNextStage()` called in all 4 advance sites:
|
|
handler (`workflow_instances.go`), tool (`tools/workflow.go`), forms
|
|
auto-advance (`workflow_forms.go`), Starlark module
|
|
(`sandbox/workflow_module.go`).
|
|
|
|
**Backward compatible:** no conditions = `ordinal + 1`.
|
|
|
|
## AI-Triggered Routing
|
|
|
|
**Tool:** `workflow_route` — persona calls with `{target_stage, reason}`.
|
|
Uses `ResolveStageByName()` (case-insensitive). Records decision in
|
|
`stage_data._route_history_latest`. Allows forward and backward jumps
|
|
(loop stages for iterative correction).
|
|
|
|
**Starlark:** `workflow.route(channel_id, target_stage, reason)` for
|
|
extension-driven escalation patterns. Requires `workflow.access`.
|
|
|
|
## on_advance Hook
|
|
|
|
**File:** `server/handlers/workflow_hooks.go`
|
|
|
|
Fires synchronously after `AdvanceWorkflowStage` succeeds. Configured
|
|
per-stage in `transition_rules.on_advance: {package_id, entry_point}`.
|
|
|
|
Hook receives: `{stage_data, previous_stage, current_stage, channel_id}`.
|
|
Returns: `{stage_data: {...}}` (enriched), `None` (no change), or
|
|
`{error: "msg"}` (logged, not rolled back — future: rollback support).
|
|
|
|
The existing `http` Starlark module (v0.29.1) is available in hooks,
|
|
enabling external API enrichment without new infrastructure.
|
|
|
|
## Progressive Forms
|
|
|
|
**Model:** `TypedFormTemplate.Fieldsets []FormFieldset` — optional
|
|
array of `{label, fields[]}`. When present, top-level `fields` is
|
|
replaced by flattened fieldset fields in `ParseTypedFormTemplate()`.
|
|
|
|
**Frontend:** `workflow.html` renders one fieldset at a time with
|
|
step indicator, next/back navigation. All fields submitted together
|
|
on the final step.
|
|
|
|
## Conditional Fields
|
|
|
|
**Model:** `FormField.Condition *FieldCondition` — `{when, op, value}`.
|
|
Operators: `eq` (default), `neq`, `in`, `exists`.
|
|
|
|
**Server-side:** `ValidateFormData()` calls `evaluateFieldCondition()`
|
|
before each field. Hidden fields are skipped (no required check, no
|
|
type validation).
|
|
|
|
**Client-side:** `workflow.html` attaches `change`/`input` listeners
|
|
to source fields. Target fields toggle `cond-hidden` CSS class.
|
|
|
|
## Structured Review
|
|
|
|
**Review comments:** `review_comments JSONB` on `workflow_assignments`.
|
|
`POST /workflow-assignments/:id/comment` appends `{text, user_id,
|
|
created_at}`. `GET /workflow-assignments/:id` returns full assignment.
|
|
|
|
**Review surface:** Side-by-side layout in `workflow.html` — left panel
|
|
shows structured `stage_data` table (internal `_`-prefixed keys hidden),
|
|
right panel has comment textarea + approve/reject buttons. Keyboard
|
|
shortcuts: `Ctrl+Enter` approve, `Ctrl+Shift+Enter` reject.
|
|
|
|
## Monitoring Dashboard
|
|
|
|
**File:** `server/handlers/workflow_monitor.go`
|
|
|
|
**Endpoints:**
|
|
- `GET /admin/workflows/monitor/instances` — all active instances
|
|
- `GET /admin/workflows/monitor/funnel/:id` — stage counts
|
|
- `GET /admin/workflows/monitor/stale?threshold_hours=N`
|
|
- `GET /teams/:teamId/workflows/monitor/instances` — team-scoped
|
|
|
|
**SLA computation:** `stage_entered_at + sla_seconds` vs `NOW()`.
|
|
Returned as `sla_remaining_seconds` (negative = breached) and
|
|
`sla_breached` boolean. Computed at query time, not stored.
|
|
|
|
**Store:** New `ListByType(ctx, "workflow")` method on `ChannelStore`
|
|
(both PG and SQLite). Monitoring queries iterate active channels,
|
|
joining workflow definitions and stage metadata.
|
|
|
|
**Frontend:** `src/js/workflow-monitor.js` — auto-refresh every 30s,
|
|
SLA color indicators (green > 50%, yellow > 20%, red), stale instance
|
|
alert section.
|
|
|
|
## Workflow Branding
|
|
|
|
`WorkflowPageData.BrandingJSON` passes the workflow's `branding` JSON
|
|
to the visitor template. Applied as:
|
|
- `--accent` CSS custom property (from `accent_color`)
|
|
- Logo image in header (from `logo_url`)
|
|
- Tagline text below header (from `tagline`)
|
|
|
|
Previously branding was only on the landing page; now also on the
|
|
active workflow surface.
|
|
|
|
## New Files
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `server/workflow/routing.go` | Conditional routing engine |
|
|
| `server/handlers/workflow_hooks.go` | on_advance hook dispatch |
|
|
| `server/handlers/workflow_monitor.go` | Monitoring dashboard |
|
|
| `src/js/workflow-monitor.js` | Admin monitoring frontend |
|
|
| `packages/icd-test-runner/js/crud/workflow-product.js` | E2E tests |
|