Skip to content

Commit 4436f82

Browse files
feat(workflows): compare deployment versions across UI and API (#8455)
* feat(workflows): describe container changes and build a canvas diff overlay The comparison engine now reports which loop and parallel fields changed and which blocks entered or left a container, and exposes the field lists and a shared hasChanges helper. A new overlay module merges two workflow states into one canvas: removed blocks, containers and edges ride along as ghosts at their old positions (nudged clear of live cards), deleted condition and router branches stay on the surviving card so their ghost edge keeps a handle, and every edge is classified by canonical port key. The renderer edge view gains a quiet ghost style for those removed connections. * feat(preview): paint comparison status on the read-only canvas The preview canvas accepts per-block and per-edge diff status: added and modified cards get a ring and a shared status label, removed cards and containers fade to a ghost, changed sub-block rows and sentence chips tint, and ghost edges sit under live ones so a rewired port shows the new line on top. * feat(workflows): version diff view with a field-level change list Side-by-side view of two workflow states: the overlaid canvas on the left and a change list on the right, sharing selection. Each touched block is a collapsible card with the app's block tile; modified blocks show field rows as folded line diffs with word marks, item-by-item list diffs for tools, conditions, routes and input fields, old to new pairs for scalars, and only the fact for secrets. Added and removed blocks show every field diffed against nothing, with long one-sided bodies capped behind one expander. Fork comparisons group credentials, picked resources and trigger paths into a muted environment bindings section. * feat(deploy): compare deployment versions and the draft The deploy modal offers "View changes" (live against the draft) when a redeploy is pending and a "Compare" action on every version row, opening a full-width comparison whose two sides are pickable from the header. The draft state hook is shared with change detection and only subscribes while something to compare against exists. * feat(forks): preview one workflow's block-level changes before a sync The synced deployed workflows list gets a "View changes" action per row. A new internal route and fork use case return the target as its editor holds it and the source deployment re-keyed into the target's block ids through the fork block map (or the derived id the sync would assign), with condition and route ids and variable ids aligned, so the two sides diff block for block like two versions of one workflow. * fix(workflows): harden the version diff after review Comparison: keep basic/advanced mode changes visible, include a tool's permission, server and implementation fields in list diffs, include input field defaults, read checkbox records as records, show whitespace-only edits, cap word and line diffing so a pathological prompt cannot stall the pane, slot deleted branches back at their old position, never reuse a ghost edge id, and mask secret-looking keys at any depth (including key/value table rows) with a name-based fallback when a block definition is unknown. Change list: memoized cards that only re-render when their own selection changes, nested cards for blocks inside an added or removed container, a shared sign map, muted tokens that exist, hover and focus treatment, scroll edge fades, and a shared skeleton for both hosts. Fork preview: the before side is the target draft the sync overwrites, read in one snapshot and scoped to the target workspace; variables and their assignments are re-keyed by unique name; a create reports no target id; the change rows are a discriminated union; the query key sits under the fork diff keys so a sync invalidates it; a direction switch closes the preview. * fix(workflows): scope the fork preview to one workflow and close review gaps - Fork "View changes" now loads only the previewed workflow: its deployed state, its identity mapping, its target row and its block pairs, instead of every deployed state in the source workspace plus the full promote plan. The plan item comes from the same buildForkPromotePlanItems decision the promote uses. The route gets a per-user rate limit. - Word marks give up past 64 edits per line pair, so many long rewritten lines cannot stall the tab. - Agent tool params that their block marks as password fields are masked whatever their name. - A list item whose label changed but whose body did not is no longer flagged as a masked value change. - Hoist double casts under their annotations, make sourceWorkflowId optional on the wire for rollout, lazy-load both diff modals, and re-record the settings module baseline: the block registry the diff canvas needs is reached only through the lazy chunk opened on click. * test(forks): use a neutral workflow name in preview fixtures * fix(forks): offer "View changes" only on workflows the sync changes - Sync details load each replaced target's draft and diff it against the projected source, using the same projection and "has changes" rule as the per-workflow preview, so a row and its preview never disagree. Rows the sync would not change read "No changes" and offer no comparison. - Preview buttons wait until the list matches the selected direction. - Mask JSON-encoded secrets in text and scalar fields, and say "A masked value changed" when masking hides the only difference. - Show role changes on agent messages, highlight a router's changed Context on the canvas, and keep ghost edges under live ones into containers. - Added or removed loops and parallels list their iteration settings. - Size ghost containers the way the preview draws them. - "Order changed" only when items moved; CRLF and CR read as line breaks; collapsing unchanged lines closes every fold; selecting a nested block opens its container card; the version pickers have distinct names. - Drop redundant mock resets flagged by check:test-patterns. * fix(workflows): bound the sync change check and tighten diff rendering - The sync list's per-workflow change check measures the target drafts in one query first and skips itself past the fork state limit, then reads drafts a few at a time and drops each after comparing, instead of holding them all. - Mask keys with a secret word anywhere in them (secretAccessKey, aws_secret_access_key) while credential references stay readable. - Inline diffs show whitespace-only changes. - Opened folds reset when the compared bodies change. - Ghost collision boxes use the canvas's own block measurement. * fix(workflows): mask message text, count all block columns, reset selection per comparison - Agent message bodies go through the same masking as other text fields. - The sync change check's size guard counts block outputs and data, not only sub-blocks. - Picking another version clears the block selection. * fix(workflows): scope selection reset to picked versions and test outcomes, not mock calls - Key the comparison view by the picked version pair instead of resetting on state identity, so live draft updates no longer clear the selection. - Agent message changes hidden by masking say so, like other fields. - Fork preview tests assert results, with mocks that answer only the right arguments, instead of asserting mock calls. * fix(workflows): only call a message change masked when the message exists on both sides * test(workflows): use absolute imports in new tests * fix(workflows): unify version comparison and simplify diff UI * fix(workflows): compare against previous saved version by default * fix(workflows): preserve comparison semantics and preview ports * feat(workflows): render structured version changes by subblock type * fix(api): remove stale OpenAPI operation count assertions * fix(workflows): preserve scoped fields and snapshot ports * fix(workflows): preserve version-specific container labels * fix(workflows): retain tool context when masking encoded params --------- Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>
1 parent 3f29a16 commit 4436f82

84 files changed

Lines changed: 8855 additions & 773 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/test-build.yml‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ jobs:
195195
# immediately, and either way the server log tail lands in the job log. No
196196
# step timeout: the job's bound covers a hang without cutting a slow but
197197
# healthy suite short of writing its report.
198-
- name: Verify SCIM and administration over real HTTP
198+
- name: Verify SCIM, administration and workflow comparisons over real HTTP
199199
working-directory: apps/sim
200200
env:
201201
NEXT_PUBLIC_APP_URL: http://127.0.0.1:3017
@@ -247,6 +247,11 @@ jobs:
247247
SCIM_E2E_AUTH_SECRET="$BETTER_AUTH_SECRET" \
248248
SCIM_E2E_REPORT_PATH="$report_dir/scim-e2e-report.json" \
249249
bun run test:scim:e2e
250+
VERSION_COMPARE_E2E_BASE_URL="$NEXT_PUBLIC_APP_URL" \
251+
VERSION_COMPARE_E2E_DATABASE_URL="$DATABASE_URL" \
252+
VERSION_COMPARE_E2E_AUTH_SECRET="$BETTER_AUTH_SECRET" \
253+
VERSION_COMPARE_E2E_REPORT_PATH="$report_dir/version-compare-http-report.json" \
254+
bun run test:workflow-version-compare:e2e
250255
251256
- name: Upload end-to-end reports and server logs
252257
if: failure()

‎apps/docs/content/docs/api-reference/(generated)/workflows/meta.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"applyWorkflowVariables",
1515
"listWorkflowVersionsV2",
1616
"getWorkflowVersionV2",
17+
"compareWorkflowVersionsV2",
1718
"updateWorkflowVersionV2",
1819
"activateWorkflowVersion",
1920
"revertWorkflowVersion",

‎apps/docs/content/docs/cli/reference.mdx‎

Lines changed: 107 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -6277,6 +6277,113 @@ sim workflows runs wait <runId> [options]
62776277

62786278
</CommandTable>
62796279

6280+
### sim workflows versions compare
6281+
6282+
Compare Workflow Versions
6283+
6284+
```bash
6285+
sim workflows versions compare <workflowId> [options]
6286+
```
6287+
6288+
**Arguments**
6289+
6290+
<CommandTable>
6291+
6292+
| Argument | Required | Description |
6293+
| --- | --- | --- |
6294+
| `workflowId` | Yes | Unique workflow identifier. |
6295+
6296+
</CommandTable>
6297+
6298+
**Options**
6299+
6300+
<CommandTable>
6301+
6302+
| Option | Required | Description |
6303+
| --- | --- | --- |
6304+
| `--base <value>` | Yes | Deployment version to compare from. |
6305+
| `--target <value>` | Yes | Deployment version to compare to, in the same workflow. |
6306+
6307+
</CommandTable>
6308+
6309+
### sim workflows versions get
6310+
6311+
Get Workflow Version
6312+
6313+
```bash
6314+
sim workflows versions get <workflowId> <version>
6315+
```
6316+
6317+
**Arguments**
6318+
6319+
<CommandTable>
6320+
6321+
| Argument | Required | Description |
6322+
| --- | --- | --- |
6323+
| `workflowId` | Yes | Unique workflow identifier. |
6324+
| `version` | Yes | Numeric deployment version. |
6325+
6326+
</CommandTable>
6327+
6328+
### sim workflows versions list
6329+
6330+
List Workflow Versions
6331+
6332+
```bash
6333+
sim workflows versions list <workflowId> [options]
6334+
```
6335+
6336+
**Arguments**
6337+
6338+
<CommandTable>
6339+
6340+
| Argument | Required | Description |
6341+
| --- | --- | --- |
6342+
| `workflowId` | Yes | Unique workflow identifier. |
6343+
6344+
</CommandTable>
6345+
6346+
**Options**
6347+
6348+
<CommandTable>
6349+
6350+
| Option | Required | Description |
6351+
| --- | --- | --- |
6352+
| `--limit <n>` | No | Maximum items to return (0 for everything). Defaults to `100`. |
6353+
| `--cursor <value>` | No | Continue from nextCursor returned by a previous result. |
6354+
6355+
</CommandTable>
6356+
6357+
### sim workflows versions update
6358+
6359+
Update Workflow Version
6360+
6361+
```bash
6362+
sim workflows versions update <workflowId> <version> [options]
6363+
```
6364+
6365+
**Arguments**
6366+
6367+
<CommandTable>
6368+
6369+
| Argument | Required | Description |
6370+
| --- | --- | --- |
6371+
| `workflowId` | Yes | Unique workflow identifier. |
6372+
| `version` | Yes | Numeric deployment version. |
6373+
6374+
</CommandTable>
6375+
6376+
**Options**
6377+
6378+
<CommandTable>
6379+
6380+
| Option | Required | Description |
6381+
| --- | --- | --- |
6382+
| `--name <value>` | No | New label for the deployment version. |
6383+
| `--description <value>` | No | New release note for the deployment version, or null to clear it. (--description null sends the word, not JSON null). |
6384+
6385+
</CommandTable>
6386+
62806387
### sim workflows create
62816388

62826389
Create Workflow
@@ -6750,84 +6857,6 @@ sim workflows state replace <workflowId> [options]
67506857

67516858
</CommandTable>
67526859

6753-
### sim workflows versions get
6754-
6755-
Get Workflow Version
6756-
6757-
```bash
6758-
sim workflows versions get <workflowId> <version>
6759-
```
6760-
6761-
**Arguments**
6762-
6763-
<CommandTable>
6764-
6765-
| Argument | Required | Description |
6766-
| --- | --- | --- |
6767-
| `workflowId` | Yes | Unique workflow identifier. |
6768-
| `version` | Yes | Numeric deployment version. |
6769-
6770-
</CommandTable>
6771-
6772-
### sim workflows versions list
6773-
6774-
List Workflow Versions
6775-
6776-
```bash
6777-
sim workflows versions list <workflowId> [options]
6778-
```
6779-
6780-
**Arguments**
6781-
6782-
<CommandTable>
6783-
6784-
| Argument | Required | Description |
6785-
| --- | --- | --- |
6786-
| `workflowId` | Yes | Unique workflow identifier. |
6787-
6788-
</CommandTable>
6789-
6790-
**Options**
6791-
6792-
<CommandTable>
6793-
6794-
| Option | Required | Description |
6795-
| --- | --- | --- |
6796-
| `--limit <n>` | No | Maximum items to return (0 for everything). Defaults to `100`. |
6797-
| `--cursor <value>` | No | Continue from nextCursor returned by a previous result. |
6798-
6799-
</CommandTable>
6800-
6801-
### sim workflows versions update
6802-
6803-
Update Workflow Version
6804-
6805-
```bash
6806-
sim workflows versions update <workflowId> <version> [options]
6807-
```
6808-
6809-
**Arguments**
6810-
6811-
<CommandTable>
6812-
6813-
| Argument | Required | Description |
6814-
| --- | --- | --- |
6815-
| `workflowId` | Yes | Unique workflow identifier. |
6816-
| `version` | Yes | Numeric deployment version. |
6817-
6818-
</CommandTable>
6819-
6820-
**Options**
6821-
6822-
<CommandTable>
6823-
6824-
| Option | Required | Description |
6825-
| --- | --- | --- |
6826-
| `--name <value>` | No | New label for the deployment version. |
6827-
| `--description <value>` | No | New release note for the deployment version, or null to clear it. (--description null sends the word, not JSON null). |
6828-
6829-
</CommandTable>
6830-
68316860
### sim workflows import
68326861

68336862
Import Workflow

0 commit comments

Comments
 (0)