Context
This is a separate product-usability follow-up to the visual alignment work in #3194 and #3189. It does not reopen the NyxID visual-spec discussion.
Audit method: on 2026-08-06, I walked the real signed-in Workflow Activity vNext user paths in the existing browser session: Workflows, New workflow, editor, Test run, Activity, failed run detail (Steps / Diagnostics / Timeline / Statistics and usage / Graph), and Settings. Findings below are ranked by impact on a user's ability to choose the right object, understand system state, recover from failure, and predict the result of an action.
Ranked findings
1. Same-name workflows are not distinguishable before opening
User goal: Reopen the correct workflow draft without trial and error.
Current friction: The catalogue contains repeated names such as 周报 Workflow, Test Member, and weekly_report_five_nodes. Rows expose only name/description, updated time, and actions. They do not show a stable user-facing discriminator, draft/published state, owner, or meaningful version. Delete is available on some rows but absent on others without explaining why.
Semantic mismatch: The UI implies that a name and timestamp identify a workflow, but the user expects each row to explain which workflow it is and what state it is in.
Classification: mental-model / contract
Semantic owner: Workflow definition catalogue read model; action eligibility belongs to workflow definition capabilities.
Prominence: Primary path. Identity and state must be first-order row information; internal IDs should remain secondary/copyable details.
Recommended product direction: Give every row a stable, human-usable discriminator and an honest lifecycle/capability summary. Explain unavailable destructive actions instead of silently removing them.
Acceptance criteria: A user can distinguish two same-name workflows without opening them; draft/published state is visible; unavailable delete is explained; fixtures use distinct memberId, workflowId, and publishedServiceId values.
2. The row-level Activity action drops the selected workflow context
User goal: See runs for the workflow whose row they are viewing.
Current friction: Clicking Activity on the incident_triage row navigates to the unfiltered global /activity page. The selected workflow is not represented in the URL, heading, filter state, or results.
Semantic mismatch: The UI implies "activity for this workflow," but the action opens "all activity."
Classification: placement / contract
Semantic owner: Activity query/filter contract keyed by the explicit draft workflow identity supplied by the row.
Prominence: Primary row action. It must preserve context by default.
Recommended product direction: Deep-link to Activity with an explicit workflow filter and a visible removable filter chip/label. Do not infer identity from a display name or conflate workflow/member/service IDs.
Acceptance criteria: Activating a row's Activity action shows only runs belonging to that workflow; the active filter is visible, shareable, removable, and survives refresh/back-forward navigation.
3. A save-location lookup failure disables every creation method
User goal: Start a workflow from a description, blank canvas, YAML, or template.
Current friction: The New workflow page shows Save locations unavailable, disables all four creation choices, and offers only Retry. It does not explain what a save location is, why it is required before choosing a method, or whether the user's work can be started safely and assigned later.
Semantic mismatch: The UI implies that choosing a creation method depends on an unexplained storage lookup, while the user expects to choose how to start and be told exactly what prerequisite is missing.
Classification: ownership / runtime
Semantic owner: Workspace/save-target availability belongs to the creation preflight and target-selection boundary, not to the four creation-method controls.
Prominence: Blocking prerequisite; explain it before disabling the primary path.
Recommended product direction: Separate creation-method selection from save-target resolution where safe. When blocking is unavoidable, identify the missing target, explain the consequence, and offer a concrete recovery path beyond blind retry.
Acceptance criteria: A user can understand what failed and what to do next; choices are not silently disabled; retry preserves the chosen method; no draft is accidentally created in an implicit or guessed owner.
4. Saved, Save workflow, and disabled Publish do not explain editor readiness
User goal: Know whether edits are persisted and what remains before the workflow can be published.
Current friction: The editor simultaneously shows editable content, a Saved label, a Save workflow button, and a disabled Publish button. There is no explanation of what Saved covers, whether changes are local or committed, or why Publish is unavailable.
Semantic mismatch: The UI implies a simple saved/unsaved binary, but the user needs distinct, honest states for dirty edits, save in progress, saved draft, validation, publish eligibility, and published runtime identity.
Classification: label / runtime
Semantic owner: Draft persistence status belongs to the workflow draft; publish eligibility belongs to validation plus the explicit published-service contract.
Prominence: Primary editor status and actions.
Recommended product direction: Make persistence and publish readiness separate states. Explain disabled Publish at the point of action and never use a weak save acknowledgement to imply publish/runtime readiness.
Acceptance criteria: After each edit the user can tell whether it is unsaved, saving, saved, invalid, or publishable; disabled Publish exposes a specific reason; successful publish exposes the resulting publishedServiceId without replacing the draft workflowId.
5. Test run accepts context-free input and does not set outcome expectations
User goal: Test the current workflow with a valid input and know where to inspect the result.
Current friction: Run opens a Test run region with an unlabeled free-form textbox beyond the generic name Test input. It gives no example/schema, allows Start run with empty input, and places Open Activity alongside the form without explaining whether the run stays here, navigates, or appears asynchronously.
Semantic mismatch: The UI implies that any text is a valid run contract and that starting a run has an obvious destination, but the user expects workflow-specific input guidance and a predictable observation path.
Classification: contract / mental-model
Semantic owner: Input requirements belong to the workflow definition; accepted/run-observed state belongs to the run command and Activity/read-model boundary.
Prominence: Primary execution path.
Recommended product direction: Derive input affordances from the workflow contract, validate before dispatch, and state what will happen after Start run without implying synchronous completion.
Acceptance criteria: Required input cannot be omitted; examples or field guidance reflect the selected workflow; acceptance yields a stable run identity and a clear link to its Activity detail; the UI distinguishes accepted from observed/completed.
6. Activity cannot support routine run triage at real history volume
User goal: Find the exact run that failed or was reported by another user.
Current friction: Rows expose only workflow display name, status, broad source (Editor, Chat, Service), and updated time. The observed history contains long stretches of identical hourly rows. There is no short run identifier, initiator, duration, start time, input summary, or visible pagination/grouping to distinguish them.
Semantic mismatch: The UI implies that workflow name/source/time are sufficient identifiers, but users investigate individual run instances and need stable, shareable evidence.
Classification: mental-model / contract
Semantic owner: Actor-scoped run read model and Activity query contract.
Prominence: Primary Activity table; common triage fields should be scannable, while technical details remain secondary.
Recommended product direction: Add a compact run identity and user-relevant context, support scalable paging/grouping, and make search/filter semantics explicit.
Acceptance criteria: A user can identify and share one exact run among same-workflow runs; can distinguish started/updated/duration; can filter by workflow, status, source, and time range; large histories do not become one unbounded table.
7. Failure diagnosis repeats raw backend evidence instead of leading with recovery
User goal: Understand why the run failed and take the next useful action.
Current friction: The summary says only The run did not complete. Diagnostics then repeats the same 403/GROUP_NOT_ALLOWED failure through step_failed, current_state_last_error, final_error, and timeline rows, including route paths, model names, JSON, and projection-language explanations. The actionable suggestion to sign in again is buried inside the raw message.
Semantic mismatch: The UI implies that more diagnostic rows equal more clarity, but users expect one primary cause, one recommended recovery, and optional evidence for support.
Classification: placement / label
Semantic owner: User-facing failure classification belongs to the run report projection; raw committed evidence belongs under technical details.
Prominence: Primary cause and next action first; repeated/raw evidence secondary.
Recommended product direction: Deduplicate equivalent evidence, map known failures to human language, surface the next action, and keep raw messages/codes available for copying under a technical disclosure.
Acceptance criteria: The observed 403 case renders one primary cause and one recovery action; raw evidence remains accessible and copyable; the same underlying error is not presented as multiple independent failures.
8. Retry actions do not communicate eligibility, scope, or consequences
User goal: Recover a failed run without repeating an action that cannot succeed or creating an unexpected fork.
Current friction: Retry failed step is enabled even when the displayed cause is an access/group authorization rejection, while Run again is disabled without a reason. The page does not explain whether retry mutates the existing run, creates a new run, reuses the same input/definition version, or where the result will appear.
Semantic mismatch: The UI implies that retry is safe and likely useful, but retryability depends on the failure class and must preserve an honest original-versus-new-run boundary.
Classification: runtime / contract
Semantic owner: Retry eligibility belongs to the run command capability contract; lineage belongs to run read models.
Prominence: Destructive/cost-incurring recovery actions require explicit scope before execution.
Recommended product direction: Gate or warn based on retryability, explain disabled actions, preview reused inputs/version, and show the new run's lineage after dispatch.
Acceptance criteria: Non-retryable auth/config failures do not offer an unexplained retry; each action states whether it creates a new run and what it reuses; a retried/forked run links to its original and vice versa.
9. Debug views expose machine concepts and even contradict the visible failure
User goal: Reconstruct what happened and trust the run metrics.
Current friction: Timeline uses raw ISO UTC timestamps, RunStarted/RunError, and command IDs. Graph is primarily long internal actor/run/step identifiers rather than a visual workflow path. Statistics reports Completed steps = 1 even though the only step and the run are both visibly Failed; token and cost values show bare zeroes without availability/currency semantics.
Semantic mismatch: The UI implies these tabs explain the run and that completed means success, but they expose storage/runtime vocabulary and ambiguous counters.
Classification: label / mental-model
Semantic owner: User-facing timeline/metrics/graph projections derived from the authoritative run state; internal IDs remain support evidence.
Prominence: User events, local time, durations, outcome, and workflow nodes first; internal identities secondary.
Recommended product direction: Translate events into user language, render the workflow execution path, and rename/recalculate counters so attempted, finished, succeeded, and failed cannot be confused.
Acceptance criteria: A one-step failed run never reports one successful Completed step; timestamps follow locale with timezone available; Graph shows named workflow steps and outcomes; raw IDs are hidden by default but copyable; unavailable usage is distinct from measured zero.
10. Account settings contradict the identity already shown in the shell
User goal: Confirm who is signed in, what access they have, and whether the session is valid.
Current friction: The shell shows Abigail Deng, while Account says Signed in: Yes but Name: Unavailable, Email: Unavailable, and Access: Unavailable, alongside an expiry timestamp. This leaves the user unable to decide whether failures are caused by identity, access, expiry, or missing profile data.
Semantic mismatch: The UI implies that Account is the authoritative place to understand identity/access, but it presents a weaker and contradictory state than the surrounding shell.
Classification: ownership / runtime
Semantic owner: Authenticated principal/session read model shared by the shell and Account; service/model authorization is a separate capability.
Prominence: Signed-in identity and session validity are primary; raw token/connection data remains technical detail.
Recommended product direction: Use one account/session source, distinguish unknown from unauthorized from expired, and provide an explicit sign-in/refresh path when session state is not valid.
Acceptance criteria: Shell and Account show consistent identity; access and expiry states are human-readable and timezone-aware; expired/invalid sessions produce a direct recovery action; missing optional profile fields do not make the whole account appear unavailable.
Cross-cutting product principles
- Preserve user context across navigation; row-level actions must not silently degrade into global views.
- Keep
memberId, draft workflowId, run identity, and publishedServiceId distinct in routes, queries, copy, and fixtures.
- Show the strongest state actually guaranteed: accepted, saved draft, published, observed, completed, and failed are not interchangeable.
- Put the common user action and explanation first; retain raw actor/projection/API evidence as secondary support detail.
- Disabled actions must explain the missing prerequisite or capability.
Path-level acceptance summary
- Workflows: same-name definitions are distinguishable and row Activity preserves the selected workflow.
- New workflow: save-target failure is understandable and recoverable without guessing ownership.
- Editor/Test run: save/publish readiness and the run input/observation contract are explicit.
- Activity: exact runs remain findable and shareable at large history volume.
- Run detail: failure cause, recovery, retry lineage, events, graph, and metrics agree with one another.
- Settings: identity/access/session information is consistent with the application shell.
Out of scope
- No API identity conflation or string-based ID guessing.
- No mock data added to make the UI appear complete.
- No weakening of authoritative actor state or read-model semantics.
- No reintroduction of legacy
/teams/:scopeId... routes.
- No implementation is included in this issue-creation task.
Background: #3194 and #3189.
Migrated from #3212 to correct the GitHub author account. The original issue remains as the historical discussion record.
Context
This is a separate product-usability follow-up to the visual alignment work in #3194 and #3189. It does not reopen the NyxID visual-spec discussion.
Audit method: on 2026-08-06, I walked the real signed-in Workflow Activity vNext user paths in the existing browser session: Workflows, New workflow, editor, Test run, Activity, failed run detail (Steps / Diagnostics / Timeline / Statistics and usage / Graph), and Settings. Findings below are ranked by impact on a user's ability to choose the right object, understand system state, recover from failure, and predict the result of an action.
Ranked findings
1. Same-name workflows are not distinguishable before opening
User goal: Reopen the correct workflow draft without trial and error.
Current friction: The catalogue contains repeated names such as
周报 Workflow,Test Member, andweekly_report_five_nodes. Rows expose only name/description, updated time, and actions. They do not show a stable user-facing discriminator, draft/published state, owner, or meaningful version. Delete is available on some rows but absent on others without explaining why.Semantic mismatch: The UI implies that a name and timestamp identify a workflow, but the user expects each row to explain which workflow it is and what state it is in.
Classification:
mental-model/contractSemantic owner: Workflow definition catalogue read model; action eligibility belongs to workflow definition capabilities.
Prominence: Primary path. Identity and state must be first-order row information; internal IDs should remain secondary/copyable details.
Recommended product direction: Give every row a stable, human-usable discriminator and an honest lifecycle/capability summary. Explain unavailable destructive actions instead of silently removing them.
Acceptance criteria: A user can distinguish two same-name workflows without opening them; draft/published state is visible; unavailable delete is explained; fixtures use distinct
memberId,workflowId, andpublishedServiceIdvalues.2. The row-level Activity action drops the selected workflow context
User goal: See runs for the workflow whose row they are viewing.
Current friction: Clicking
Activityon theincident_triagerow navigates to the unfiltered global/activitypage. The selected workflow is not represented in the URL, heading, filter state, or results.Semantic mismatch: The UI implies "activity for this workflow," but the action opens "all activity."
Classification:
placement/contractSemantic owner: Activity query/filter contract keyed by the explicit draft workflow identity supplied by the row.
Prominence: Primary row action. It must preserve context by default.
Recommended product direction: Deep-link to Activity with an explicit workflow filter and a visible removable filter chip/label. Do not infer identity from a display name or conflate workflow/member/service IDs.
Acceptance criteria: Activating a row's Activity action shows only runs belonging to that workflow; the active filter is visible, shareable, removable, and survives refresh/back-forward navigation.
3. A save-location lookup failure disables every creation method
User goal: Start a workflow from a description, blank canvas, YAML, or template.
Current friction: The New workflow page shows
Save locations unavailable, disables all four creation choices, and offers onlyRetry. It does not explain what a save location is, why it is required before choosing a method, or whether the user's work can be started safely and assigned later.Semantic mismatch: The UI implies that choosing a creation method depends on an unexplained storage lookup, while the user expects to choose how to start and be told exactly what prerequisite is missing.
Classification:
ownership/runtimeSemantic owner: Workspace/save-target availability belongs to the creation preflight and target-selection boundary, not to the four creation-method controls.
Prominence: Blocking prerequisite; explain it before disabling the primary path.
Recommended product direction: Separate creation-method selection from save-target resolution where safe. When blocking is unavoidable, identify the missing target, explain the consequence, and offer a concrete recovery path beyond blind retry.
Acceptance criteria: A user can understand what failed and what to do next; choices are not silently disabled; retry preserves the chosen method; no draft is accidentally created in an implicit or guessed owner.
4.
Saved,Save workflow, and disabledPublishdo not explain editor readinessUser goal: Know whether edits are persisted and what remains before the workflow can be published.
Current friction: The editor simultaneously shows editable content, a
Savedlabel, aSave workflowbutton, and a disabledPublishbutton. There is no explanation of whatSavedcovers, whether changes are local or committed, or why Publish is unavailable.Semantic mismatch: The UI implies a simple saved/unsaved binary, but the user needs distinct, honest states for dirty edits, save in progress, saved draft, validation, publish eligibility, and published runtime identity.
Classification:
label/runtimeSemantic owner: Draft persistence status belongs to the workflow draft; publish eligibility belongs to validation plus the explicit published-service contract.
Prominence: Primary editor status and actions.
Recommended product direction: Make persistence and publish readiness separate states. Explain disabled Publish at the point of action and never use a weak save acknowledgement to imply publish/runtime readiness.
Acceptance criteria: After each edit the user can tell whether it is unsaved, saving, saved, invalid, or publishable; disabled Publish exposes a specific reason; successful publish exposes the resulting
publishedServiceIdwithout replacing the draftworkflowId.5. Test run accepts context-free input and does not set outcome expectations
User goal: Test the current workflow with a valid input and know where to inspect the result.
Current friction:
Runopens aTest runregion with an unlabeled free-form textbox beyond the generic nameTest input. It gives no example/schema, allowsStart runwith empty input, and placesOpen Activityalongside the form without explaining whether the run stays here, navigates, or appears asynchronously.Semantic mismatch: The UI implies that any text is a valid run contract and that starting a run has an obvious destination, but the user expects workflow-specific input guidance and a predictable observation path.
Classification:
contract/mental-modelSemantic owner: Input requirements belong to the workflow definition; accepted/run-observed state belongs to the run command and Activity/read-model boundary.
Prominence: Primary execution path.
Recommended product direction: Derive input affordances from the workflow contract, validate before dispatch, and state what will happen after
Start runwithout implying synchronous completion.Acceptance criteria: Required input cannot be omitted; examples or field guidance reflect the selected workflow; acceptance yields a stable run identity and a clear link to its Activity detail; the UI distinguishes accepted from observed/completed.
6. Activity cannot support routine run triage at real history volume
User goal: Find the exact run that failed or was reported by another user.
Current friction: Rows expose only workflow display name, status, broad source (
Editor,Chat,Service), and updated time. The observed history contains long stretches of identical hourly rows. There is no short run identifier, initiator, duration, start time, input summary, or visible pagination/grouping to distinguish them.Semantic mismatch: The UI implies that workflow name/source/time are sufficient identifiers, but users investigate individual run instances and need stable, shareable evidence.
Classification:
mental-model/contractSemantic owner: Actor-scoped run read model and Activity query contract.
Prominence: Primary Activity table; common triage fields should be scannable, while technical details remain secondary.
Recommended product direction: Add a compact run identity and user-relevant context, support scalable paging/grouping, and make search/filter semantics explicit.
Acceptance criteria: A user can identify and share one exact run among same-workflow runs; can distinguish started/updated/duration; can filter by workflow, status, source, and time range; large histories do not become one unbounded table.
7. Failure diagnosis repeats raw backend evidence instead of leading with recovery
User goal: Understand why the run failed and take the next useful action.
Current friction: The summary says only
The run did not complete.Diagnostics then repeats the same 403/GROUP_NOT_ALLOWEDfailure throughstep_failed,current_state_last_error,final_error, and timeline rows, including route paths, model names, JSON, and projection-language explanations. The actionable suggestion to sign in again is buried inside the raw message.Semantic mismatch: The UI implies that more diagnostic rows equal more clarity, but users expect one primary cause, one recommended recovery, and optional evidence for support.
Classification:
placement/labelSemantic owner: User-facing failure classification belongs to the run report projection; raw committed evidence belongs under technical details.
Prominence: Primary cause and next action first; repeated/raw evidence secondary.
Recommended product direction: Deduplicate equivalent evidence, map known failures to human language, surface the next action, and keep raw messages/codes available for copying under a technical disclosure.
Acceptance criteria: The observed 403 case renders one primary cause and one recovery action; raw evidence remains accessible and copyable; the same underlying error is not presented as multiple independent failures.
8. Retry actions do not communicate eligibility, scope, or consequences
User goal: Recover a failed run without repeating an action that cannot succeed or creating an unexpected fork.
Current friction:
Retry failed stepis enabled even when the displayed cause is an access/group authorization rejection, whileRun againis disabled without a reason. The page does not explain whether retry mutates the existing run, creates a new run, reuses the same input/definition version, or where the result will appear.Semantic mismatch: The UI implies that retry is safe and likely useful, but retryability depends on the failure class and must preserve an honest original-versus-new-run boundary.
Classification:
runtime/contractSemantic owner: Retry eligibility belongs to the run command capability contract; lineage belongs to run read models.
Prominence: Destructive/cost-incurring recovery actions require explicit scope before execution.
Recommended product direction: Gate or warn based on retryability, explain disabled actions, preview reused inputs/version, and show the new run's lineage after dispatch.
Acceptance criteria: Non-retryable auth/config failures do not offer an unexplained retry; each action states whether it creates a new run and what it reuses; a retried/forked run links to its original and vice versa.
9. Debug views expose machine concepts and even contradict the visible failure
User goal: Reconstruct what happened and trust the run metrics.
Current friction: Timeline uses raw ISO UTC timestamps,
RunStarted/RunError, and command IDs. Graph is primarily long internal actor/run/step identifiers rather than a visual workflow path. Statistics reportsCompleted steps = 1even though the only step and the run are both visiblyFailed; token and cost values show bare zeroes without availability/currency semantics.Semantic mismatch: The UI implies these tabs explain the run and that
completedmeans success, but they expose storage/runtime vocabulary and ambiguous counters.Classification:
label/mental-modelSemantic owner: User-facing timeline/metrics/graph projections derived from the authoritative run state; internal IDs remain support evidence.
Prominence: User events, local time, durations, outcome, and workflow nodes first; internal identities secondary.
Recommended product direction: Translate events into user language, render the workflow execution path, and rename/recalculate counters so attempted, finished, succeeded, and failed cannot be confused.
Acceptance criteria: A one-step failed run never reports one successful
Completed step; timestamps follow locale with timezone available; Graph shows named workflow steps and outcomes; raw IDs are hidden by default but copyable; unavailable usage is distinct from measured zero.10. Account settings contradict the identity already shown in the shell
User goal: Confirm who is signed in, what access they have, and whether the session is valid.
Current friction: The shell shows
Abigail Deng, while Account saysSigned in: YesbutName: Unavailable,Email: Unavailable, andAccess: Unavailable, alongside an expiry timestamp. This leaves the user unable to decide whether failures are caused by identity, access, expiry, or missing profile data.Semantic mismatch: The UI implies that Account is the authoritative place to understand identity/access, but it presents a weaker and contradictory state than the surrounding shell.
Classification:
ownership/runtimeSemantic owner: Authenticated principal/session read model shared by the shell and Account; service/model authorization is a separate capability.
Prominence: Signed-in identity and session validity are primary; raw token/connection data remains technical detail.
Recommended product direction: Use one account/session source, distinguish unknown from unauthorized from expired, and provide an explicit sign-in/refresh path when session state is not valid.
Acceptance criteria: Shell and Account show consistent identity; access and expiry states are human-readable and timezone-aware; expired/invalid sessions produce a direct recovery action; missing optional profile fields do not make the whole account appear unavailable.
Cross-cutting product principles
memberId, draftworkflowId, run identity, andpublishedServiceIddistinct in routes, queries, copy, and fixtures.Path-level acceptance summary
Out of scope
/teams/:scopeId...routes.Background: #3194 and #3189.