This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/docs/archive/DESIGN-0.35.0.md
2026-03-20 16:08:12 +00:00

5.7 KiB

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