# DESIGN — Workflow System Redesign (0.9.x) **Version:** v0.9.0 **Status:** Draft **Author:** Jeff / Claude session 2026-04-03 --- ## Problem The workflow system spans ~7,600 lines across 25+ files and was built incrementally from v0.3.x through v0.7.10. It works, but several concepts are redundant, primitives are buried, and the Starlark module is read-only. Before shipping reference extensions (v0.10.x) that build on workflows, the system needs cleanup and promotion of reusable primitives. ## Audit Summary Full audit in `/config/Downloads/AUDIT-workflow-0.9.md`. Classification: ### KEEP — Core primitives that survive | Component | File(s) | Lines | Rationale | |-----------|---------|-------|-----------| | Engine core | `workflow/engine.go` | ~400 | Stateless state machine — Start, Advance, Cancel, version-pinned execution | | Conditional routing | `workflow/routing.go` | ~500 | Pure functions, 8 operators, well-tested (497 lines of tests) | | Automated processing | `workflow/automated.go` | ~300 | Starlark hook execution, cycle guard (max 10) | | Scanner | `workflow/scanner.go` | ~200 | Background SLA + staleness checks, 5-minute interval | | Signoff system | engine.go + handlers | ~400 | Multi-party approve/reject with quorum, role-gated | | Assignment queue | handlers | ~300 | Claim/unclaim/complete/cancel lifecycle | | Version snapshots | store + models | ~200 | Immutable snapshots, version-pinned instances | | Typed form system | `models/workflow.go` | ~300 | 8 field types, fieldsets, conditional visibility | | Store interface | `store/workflow_iface.go` | 61 methods | Complete lifecycle coverage | ### OBE — Superseded by new design | Concept | Superseded by | |---------|---------------| | Per-stage `audience` field | Multi-page packages with mixed access declarations | | `entry_mode` (public_link/team_only) | Package-level `scope: adoptable` + per-page access | | `stage_mode` proliferation (4 values) | Collapse to 3: form / delegated / automated | | `stage_type` (simple/dynamic/automated) | Redundant with `starlark_hook` presence check | | `AdoptTeamWorkflow` clone | Package adoption model | | `ExportWorkflowPackage` endpoint | Standard package export | ### PROMOTE — Buried features to expose as kernel primitives 1. **Roles → kernel primitive**: `team_user_roles` table, manifest `requires_roles`, team admin UI, kernel middleware, Starlark SDK 2. **Typed forms → SDK primitive**: Move from workflow models to `forms` package, FE SDK `sw.forms.render()` / `sw.forms.validate()` 3. **Conditional routing → SDK primitive**: Starlark `routing.evaluate(rules, data)` 4. **Workflow Starlark module → full read/write**: `workflow.start()`, `.advance()`, `.cancel()`, `.submit_signoff()` --- ## Technical Debt ### Starlark Converter Duplication Three files contain nearly identical Go↔Starlark conversion functions: | File | Functions | |------|-----------| | `workflow/automated.go` | `goToStarlark`, `starlarkDictToMap`, `starlarkToGo` | | `handlers/workflow_hooks.go` | `starlarkDictToMap`, `starlarkToGo`, `jsonToStarlark` | | `sandbox/workflow_module.go` | `goValToStarlark` | **Fix:** Consolidate into `sandbox/convert.go`. ### Snapshot Format Inconsistency Two formats exist (wrapped `{stages, workflow}` vs legacy flat array). Three copies of the parser across engine, instance handlers, and assignment handlers. **Fix:** Consolidate into one exported function. Standardize on wrapped format. --- ## Sequencing | Version | Feature | Dependencies | |---------|---------|-------------| | **v0.9.0** | Starlark converter consolidation + snapshot format cleanup | None | | **v0.9.1** | `team_user_roles` table + management API + admin UI | None | | **v0.9.2** | `scope: adoptable` manifest field + adoption flow with role auto-populate | v0.9.1 | | **v0.9.3** | Promote typed forms to SDK primitive (`sw.forms`) | None | | **v0.9.4** | Deprecate `stage_type`, collapse `stage_mode` to 3 values | None | | **v0.9.5** | Full read/write workflow Starlark module | v0.9.0 | | **v0.9.6** | Conditional routing as SDK primitive | v0.9.5 | | **v0.9.7** | Multi-surface manifest + kernel route resolution | None | | **v0.9.8** | Wire roles into surface access (`access: role:X`) + kernel middleware | v0.9.1, v0.9.7 | Each step is CI-green independently. The first four are the high-value items. --- ## Files Affected (by component) ### Converter Consolidation (v0.9.0) - New: `sandbox/convert.go` - Modified: `workflow/automated.go`, `handlers/workflow_hooks.go`, `sandbox/workflow_module.go` ### Team Roles (v0.9.1) - New: migration (PG + SQLite), `store/team_roles.go`, `handlers/team_roles.go` - Modified: manifest validation, adoption flow, team admin UI ### Typed Forms (v0.9.3) - New: `forms/` package (extracted from `models/workflow.go`) - New: `sw.forms` SDK module - Modified: workflow engine to import from `forms/` instead of inline ### Workflow Starlark Module (v0.9.5) - Modified: `sandbox/workflow_module.go` — add start/advance/cancel/signoff - Modified: `workflow/engine.go` — extract interface to break circular import --- ## Non-Goals - Rewriting the workflow engine. The state machine is correct and stays. - Adding a visual workflow builder. That's an extension concern, not kernel. - Multi-tenancy changes. Team scoping works as designed.