Skip to content

feat: Add task-level validation - #501

Open
handreyrc wants to merge 2 commits into
open-workflow-specification:feature/node-editingfrom
handreyrc:task-level-validation
Open

handreyrc wants to merge 2 commits into
open-workflow-specification:feature/node-editingfrom
handreyrc:task-level-validation

Conversation

@handreyrc

@handreyrc handreyrc commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Closes #312

This PR introduces task-level validation on Apply in side-panel task editing forms with live re-validation and Apply anyway option.

  • Errors that can be traced back to fields will cause the fields with errors to be highlighted.
  • Errors that cannot be traced back to fields are still visible from the error session on the top of the form.
image

Not Addressed in This PR

  • Full workflow validation is performed when changes are committed to the model, however, errors caught in the workflow are not fed back to the form. Workflow-level validation will be addressed in a separate issue.

Note: The task-level validation runs when the user clicks o apply, and then if there errors the user has the option to apply the changes with errors or go back to the form and fix the errors highlighted in the form. By fixing a field with error, the validation with run again when the field loses focus and the error counter will be updated.

Changes

  • Added task-level schema validation to side-panel edit forms. It runs on Apply through validateTaskForm, reusing the field-level ajv pipeline (collectSchemaFieldErrors / collectTaskErrors).
  • Errors are split into field errors, written to the form with a schema type, and level errors for containers, sections and the task root. Level errors are rendered by the new LevelErrors component. Subtasks are not validated.
  • The first Apply click with errors is blocked and shows an error count. Clicking again turns the button into a destructive "Apply anyway", so the user can still commit.
  • Validation re-runs live after the first attempt, so errors clear as the user fixes them.
  • Added TaskValidationProvider and the useTaskValidation / useLevelErrors hooks to hold validation state. Added footerValidationState to derive the footer label, variant and bypass state.
  • Added unit tests for task-level validation, the validation context, footer state, error collection and LevelErrors. Added an EditFormFooter integration test.

How to Test

  • Test with the **EXAMPLES ** in edit mode from Storybook.

Signed-off-by: Handrey Cunha <handrey.cunha@gmail.com>
@changeset-bot

changeset-bot Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1eb3080

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@openworkflowspec/diagram-editor Minor
@openworkflowspec/i18n Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@handreyrc handreyrc self-assigned this Oct 26, 2026
@netlify

netlify Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for openworkflow-editor ready!

Name Link
🔨 Latest commit 1eb3080
🔍 Latest deploy log https://app.netlify.com/projects/openworkflow-editor/deploys/6adf8e5618e81f2e0a0b4e67
😎 Deploy Preview https://deploy-preview-501--openworkflow-editor.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Validation can discard or hide actionable errors, and two new test harnesses contain render loops.

6 open issues
What changed in this PR

Adds task-level validation to the diagram editor’s side-panel forms for issue #312, extending field validation to task-wide constraints while leaving workflow-level feedback outside this PR’s scope.

Changes:

  • Validates on Apply, blocks the first invalid submission, and offers “Apply anyway” for bypassable errors.
  • Adds shared validation state, live revalidation, level-error messages, and error counters.
  • Adds validation tests and fixtures, updates existing editing tests, and includes a minor-release changeset.

Paths below are relative to packages/open-workflow-diagram-editor/, except the changeset.

File Description
tests/​test-utils/​validation-helpers.ts Builds task-form validation fixtures.
tests/​test-utils/​index.ts Exports shared Apply helpers.
tests/​test-utils/​edit-helpers.ts Adds Apply and bypass helpers.
tests/​side-panel/​SidePanelTrigger.test.tsx Formatting cleanup only.
tests/​side-panel/​SidePanel.test.tsx Uses shared Apply queries.
tests/​side-panel/​NodeDetailsView.test.tsx Tests workflow-banner behavior with validation state.
tests/​side-panel/​NavigationGuardDialog.test.tsx Formatting cleanup only.
tests/​side-panel/​forms/​validation/​useFieldLevelValidation.test.ts Tests revalidation after Apply attempts.
tests/​side-panel/​forms/​validation/​taskValidationContext.test.tsx Tests validation state and level counts.
tests/​side-panel/​forms/​validation/​taskLevelValidation.test.ts Tests validation and form-error updates.
tests/​side-panel/​forms/​validation/​taskErrorClassifier.test.ts Tests field and level classification.
tests/​side-panel/​forms/​validation/​LevelErrors.test.tsx Tests level-error alerts.
tests/​side-panel/​forms/​validation/​footerValidationState.test.ts Tests footer labels and bypass state.
tests/​side-panel/​forms/​validation/​FooterValidationCounter.test.tsx Tests accessible error counts.
tests/​side-panel/​forms/​validation/​collectTaskErrors.test.ts Tests task validation across variants.
tests/​side-panel/​forms/​validation/​collectSchemaFieldErrors.test.ts Tests shared field-error collection.
tests/​side-panel/​forms/​validation/​branchGroups.test.ts Tests schema-branch error filtering.
tests/​side-panel/​forms/​validation/​activeFormView.test.ts Tests active-field discovery.
tests/​side-panel/​forms/​TaskForm.drill.test.tsx Uses shared Apply queries.
tests/​side-panel/​EditSession.test.tsx Formatting cleanup only.
tests/​side-panel/​EditFormFooter.tryTask.test.tsx Updates Apply queries in retry tests.
tests/​side-panel/​EditFormFooter.test.tsx Updates footer button queries.
tests/​side-panel/​EditFormFooter.taskValidation.test.tsx Adds Apply-validation integration tests.
tests/​side-panel/​EditFormFooter.switchTask.test.tsx Updates Apply queries in switch tests.
tests/​side-panel/​EditFormFooter.runTask.test.tsx Accommodates validation bypass in run tests.
tests/​side-panel/​EditFormFooter.raiseTask.test.tsx Updates Apply queries in raise tests.
tests/​side-panel/​EditFormFooter.presenceKeys.test.tsx Handles bypass for empty variants.
tests/​side-panel/​EditFormFooter.keyValueMap.test.tsx Uses validation-aware commit helpers.
tests/​side-panel/​EditFormFooter.jsonValues.test.tsx Updates Apply queries for structured values.
tests/​side-panel/​EditFormFooter.forkTask.test.tsx Updates Apply queries in fork tests.
tests/​side-panel/​EditFormFooter.emitTask.test.tsx Updates Apply queries in emit tests.
tests/​side-panel/​EditFormFooter.doTask.test.tsx Updates Apply queries in do-task tests.
tests/​side-panel/​EditFormFooter.dirtyCounter.test.tsx Handles bypass in dirty-count regression tests.
tests/​side-panel/​EditFormFooter.callHttpEndpoint.test.tsx Handles bypass in endpoint-switching tests.
tests/​fixtures/​taskValidation.ts Adds valid, invalid, and subtask fixtures.
tests-e2e/​helpers.ts Adds trailing newline only.
tests-e2e/​expression-clear-apply.spec.ts Explicitly confirms “Apply anyway.”
src/​side-panel/​SidePanel.css Styles stacked footer statuses.
src/​side-panel/​NodeDetailsView.tsx Uses mapped errors for the empty-state check.
src/​side-panel/​forms/​VariantPicker.tsx Revalidates after variant changes.
src/​side-panel/​forms/​validation/​validation.css Styles validation counters and alerts.
src/​side-panel/​forms/​validation/​useFieldLevelValidation.ts Runs task validation after an Apply attempt.
src/​side-panel/​forms/​validation/​taskValidationContext.tsx Stores validation results and counts.
src/​side-panel/​forms/​validation/​taskLevelValidation.ts Applies schema errors to form state.
src/​side-panel/​forms/​validation/​taskErrorClassifier.ts Classifies field and container errors.
src/​side-panel/​forms/​validation/​LevelErrors.tsx Renders level-specific alerts.
src/​side-panel/​forms/​validation/​index.ts Exports validation APIs and components.
src/​side-panel/​forms/​validation/​footerValidationState.ts Derives commit-blocking and footer state.
src/​side-panel/​forms/​validation/​FooterValidationCounter.tsx Displays localized error counts.
src/​side-panel/​forms/​validation/​collectSchemaFieldErrors.ts Shares field and task validation pipelines.
src/​side-panel/​forms/​validation/​branchGroups.ts Collapses alternative-schema diagnostics.
src/​side-panel/​forms/​validation/​activeFormView.ts Maps active fields and containers.
src/​side-panel/​forms/​taskFormContext.ts Exposes task revalidation callback.
src/​side-panel/​forms/​TaskForm.tsx Resets validation and renders level errors.
src/​side-panel/​forms/​FormField.tsx Adds errors to inline object groups.
src/​side-panel/​forms/​drill/​DrillRow.tsx Includes level errors in badges.
src/​side-panel/​forms/​drill/​drill.ts Comment whitespace cleanup only.
src/​side-panel/​forms/​customFields/​NumberControl.tsx Triggers numeric-edit revalidation.
src/​side-panel/​EditSession.tsx Provides shared task-validation context.
src/​side-panel/​EditFormFooter.tsx Integrates validation, bypass, and counters.
src/​react-flow/​diagram/​Diagram.css Formatting cleanup only.
src/​i18n/​locales/​en.ts Adds “Apply anyway” translation.
src/​core/​taskTypes.ts Formatting cleanup only.
src/​components/​ui/​sidebar.tsx Formatting cleanup only.
.changeset/​add-task-level-validation.md Announces the feature as a minor release.

Review effort: Balanced

Comment thread packages/open-workflow-diagram-editor/tests/side-panel/NodeDetailsView.test.tsx Outdated
Comment thread packages/open-workflow-diagram-editor/src/side-panel/forms/drill/DrillRow.tsx Outdated
Signed-off-by: Handrey Cunha <handrey.cunha@gmail.com>
fields: FormFieldDescriptor[] = [],
scopedPath?: string,
): Record<string, string> {
const sentinels = extractSentinels(formValues);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both collectSchemaFieldErrors and collectTaskErrors look like they have the first 3 steps repeated - probably good to extract into shared function?


/* Level errors in the form (D14, ST-5b) */
.dec-root .dec-level-errors {
@apply dec:flex dec:flex-col dec:gap-1 dec:mb-3 dec:p-2.5 dec:rounded-md dec:text-xs dec:font-medium dec:bg-red-50 dec:text-red-700 dec:border dec:border-red-200;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have some color variables set in styles.css, would be good to derive dec:bg-red-50 dec:text-red-700 from --dec-error-accent instead so its kept in one place?

}

// Errors that cannot be traced back to fields or containers still block Apply, so they are kept
// and listed in the footer, as no level of the form shows them (D5, D9, D14).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ive seen a few comments with references like D5, D10 etc, what does it mean?

*/
* Copyright 2021-Present The Open Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be a few places where its just reformatted like this file only seems to have formatting changes which bloat the PR, is this correct? same with

  • NavigationGuardDialog.test.tsx
  • SidePanelTrigger.test.tsx
  • Diagram.css
  • drill.ts
  • sidebar.tsx
  • EditSession.test.tsx

/** Records a validation result into state, optionally updating the attempted flag. */
recordValidationResult: (result: TaskValidationResult, attempted?: boolean) => void;
/** Sets the attempted flag (e.g. on Apply click). */
setAttempted: (attempted: boolean) => void;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see setAttempted below as well, is this one needed on the type?

@lornakelly

Copy link
Copy Markdown
Collaborator

@handreyrc Thanks for this PR, just added a few comments

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants