Skip to content

refactor: drive workflow node forms from backend descriptors - #3707

Open
AbigailDeng wants to merge 6 commits into
devfrom
refactor/2026-10-21_workflow-descriptor-forms
Open

AbigailDeng wants to merge 6 commits into
devfrom
refactor/2026-10-21_workflow-descriptor-forms

Conversation

@AbigailDeng

Copy link
Copy Markdown
Contributor

Workflow node forms currently maintain frontend field definitions independently of the backend primitive descriptors. The two sources have drifted, and adding a module cannot reliably add its configuration controls to the console.

This change makes module-contributed backend descriptors the primary form contract. The shipped frontend schema remains an explicitly identified compatibility fallback when a descriptor is unavailable.

Changes

  • Add typed parameter definitions to workflow module registrations, including value types, controls, labels, defaults, enums and numeric constraints. Core and schedule extension modules contribute through the same contract.
  • Publish the complete authoring contract through /api/primitives and preserve string control values in /api/capabilities. Correct existing descriptor drift, including workflow-call lifecycle values and canonical prompt parameters.
  • Derive both workflow node panels and the older Studio adapter from the shared descriptor codec. A matching descriptor supplies the complete field list; an explicit parameters: [] stays authoritative. Legacy fields are never merged into a successful descriptor.
  • Keep the old schema for failed or missing catalogue entries, with visible fallback status and retry. Unknown nodes retain advanced JSON editing without inferring a schema from current values.
  • Preserve dirty edits across loading, retries and descriptor changes, including removed fields. Preserve unadvertised parameters, runtime expressions, JSON strings, whitespace separators and large integer literals. Object and array literals keep their structure when they contain nested template strings.
  • Keep bilingual presentation messages in the latest dev branch's lazy-loaded locale catalogues. Add the explicit config return type required for the upstream bundle-report config to pass TypeScript declaration checks.
  • Document ownership, wire fields, fallback rules and the distinct risks protected by the focused regression cases in docs/canon/workflow-primitive-descriptors.md.

Validation

All validation below ran after rebasing the change onto dev at 481eb042d. After the final codec review fix, the 16 frontend unit cases, TypeScript check, production build, affected-file lint, test stability guards, docs lint and diff checks were repeated.

  • Frontend descriptor/codec/legacy adapter unit tests: 16 passed.
  • Locale key parity, English copy and ICU placeholder unit checks: 3 passed.
  • Core descriptor, lifecycle and primitive-catalog unit tests: 29 passed.
  • Affected Host endpoint/capability unit tests: 3 passed using isolated compilation, as described below.
  • Frontend TypeScript check and production build: passed.
  • Workflow Infrastructure and Schedules builds: passed.
  • Biome lint on all 20 changed frontend TS/TSX files: passed without warnings; the four codec/test files changed during final review were checked again.
  • Architecture guards, test stability guards, docs lint and git diff --check: passed.

Exact incremental test commands:

pnpm --dir apps/aevatar-console-web exec jest --runInBand \
  --runTestsByPath \
  src/shared/studio/nodeConfigFields.structured.test.ts \
  src/shared/studio/nodeConfigFields.test.ts \
  src/shared/api/__tests__/runtimeDecoders.test.ts \
  --testNamePattern 'descriptor-driven node configuration|legacy Studio descriptor adapter|primitive descriptor form contracts'

pnpm --dir apps/aevatar-console-web exec jest --runInBand \
  --runTestsByPath src/locales/catalog.test.ts \
  --testNamePattern 'keeps the English and Chinese message catalogs structurally aligned|keeps the English message catalog free of Chinese copy|keeps ICU placeholder names aligned across locales'

dotnet test test/Aevatar.Workflow.Core.Tests/Aevatar.Workflow.Core.Tests.csproj \
  --no-restore --nologo -v quiet \
  --filter 'FullyQualifiedName~WorkflowPrimitiveDefinitionTests|FullyQualifiedName~WorkflowCallLifecycleTests|FullyQualifiedName~WorkflowPrimitiveCatalogTests'

dotnet test test/Aevatar.Workflow.Host.Api.Tests/Aevatar.Workflow.Host.Api.Tests.csproj \
  --no-restore --nologo -v quiet \
  -p:BuildProjectReferences=false \
  -p:EnableDefaultCompileItems=false \
  -p:CustomAfterMicrosoftCommonTargets=/tmp/aevatar-descriptor-focused.targets \
  --filter 'FullyQualifiedName~WorkflowPrimitiveCapabilitiesTests|FullyQualifiedName~ListPrimitives_ShouldComposePrimitiveDescriptorsFromCapabilitiesAndCatalog|FullyQualifiedName~CatalogEndpoints_ShouldAwaitAsyncQueryServiceAndPassCancellationToken'

Static and build verification:

pnpm --dir apps/aevatar-console-web tsc
pnpm --dir apps/aevatar-console-web build
dotnet build src/workflow/Aevatar.Workflow.Infrastructure/Aevatar.Workflow.Infrastructure.csproj --no-restore --nologo -v quiet
dotnet build src/workflow/extensions/Aevatar.Workflow.Extensions.Schedules/Aevatar.Workflow.Extensions.Schedules.csproj --no-restore --nologo -v quiet
PATH="/tmp/aevatar-descriptor-guards:$PATH" bash tools/ci/architecture_guards.sh
bash tools/ci/test_stability_guards.sh
bash tools/docs/lint.sh
git diff --check

The temporary guard path contains the repository CI's pinned buf 1.68.3 binary; no repository dependency or guard was bypassed.

The normal Host test project build is blocked by existing MCP SDK API incompatibilities in MCPClientManager.cs and a missing JwtBearer reference in ChatEndpointsInternalTests.cs. The temporary MSBuild target compiles the affected ChatQueryEndpointsTests.cs and WorkflowPrimitiveCapabilitiesTests.cs, plus the existing GlobalUsings and ProcessEnvSerialCollection, in the original test project. It does not modify the project file. This is evidence for the three selected tests, not a claim that the complete Host test project builds successfully.

Reproduce the temporary Host test compilation selection

Create /tmp/aevatar-descriptor-focused.targets with the following content before running the selected Host command above. The project directory is resolved by MSBuild; this adds only the named files while default compile items are disabled for that command.

<Project>
  <ItemGroup>
    <Compile Include="$(MSBuildProjectDirectory)/ChatQueryEndpointsTests.cs" />
    <Compile Include="$(MSBuildProjectDirectory)/WorkflowPrimitiveCapabilitiesTests.cs" />
    <Compile Include="$(MSBuildProjectDirectory)/GlobalUsings.cs" />
    <Compile Include="$(MSBuildProjectDirectory)/ProcessEnvSerialCollection.cs" />
  </ItemGroup>
</Project>

Component and route regressions were added/updated but were not executed under the task's unit-only local test policy. No full frontend or solution suite, integration, E2E or smoke tests ran. The main remaining validation gap is the rendered interaction flow. Coverage percentages were not measured; the case-by-case risk inventory is in the architecture document.

Review and recurrence prevention

Independent adversarial review found a nested-template round-trip defect in object/array fields. It is fixed in both the shared codec and legacy adapter with pure unit regressions. No other actionable findings were reported by that review. A separate read-only Codex CLI review was stopped after exceeding five minutes without a final result and is not counted as a passing review.

  • Immediate symptom: editable form fields and backend descriptors disagree, so module changes require frontend schema edits.
  • Root cause: separate hand-maintained field tables and conversion paths diverge from module registrations.
  • General failure pattern: duplicated authoritative contracts plus display identifiers used as runtime parameter keys.
  • Similar locations checked: both node panels, the older Studio consumers, shared codec/decoders, Core modules, primitive aliases and the schedule extension.
  • Guard added: module-contributed typed descriptors and a shared descriptor-first codec; fallback never augments a successful response.
  • Regression coverage: descriptor precedence, explicit empty schemas, fallback, aliases, type constraints, canonical writes, raw preservation and async edit recovery. The architecture document explains the distinct risk for each case.
  • Hard gates: incremental unit tests, TypeScript/build, changed-file lint, architecture/test-stability/docs guards.
  • Remaining risks: rendered tests are unexecuted locally; normal Host project compilation is blocked by the existing dependency errors above. Runtime modules retain final business validation, including conditional and cross-field rules.

Workflow Activity vNext baseline

The existing Excalidraw baseline is preserved: SHA-256 30e74d7b410ae72c4c91432355436679033679c54c10b1702908435b001577de.

The design and journey contracts remain apps/aevatar-console-web/docs/superpowers/specs/2026-08-04-workflow-activity-vnext-design.md and apps/aevatar-console-web/docs/superpowers/specs/2026-08-04-workflow-activity-vnext-user-paths.md. Remote state comes from real API responses; the shipped schema is a visibly identified compatibility fallback. Authentication, identities, routing and locale mechanisms are preserved. Backend changes complete the descriptor contract required by the existing forms.

@codecov

codecov Bot commented Oct 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.25837% with 24 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.44%. Comparing base (481eb04) to head (5526b5b).

Files with missing lines Patch % Lines
...Infrastructure/CapabilityApi/ChatQueryEndpoints.cs 61.11% 13 Missing and 1 partial ⚠️
...ties/WorkflowInfrastructureCapabilitiesProvider.cs 81.25% 6 Missing and 3 partials ⚠️
...ow.Core/Primitives/WorkflowPrimitiveDefinitions.cs 99.59% 0 Missing and 1 partial ⚠️
@@           Coverage Diff            @@
##              dev    #3707    +/-   ##
========================================
  Coverage   83.43%   83.44%            
========================================
  Files        1685     1687     +2     
  Lines      193217   193505   +288     
  Branches    23239    23254    +15     
========================================
+ Hits       161218   161472   +254     
- Misses      21188    21214    +26     
- Partials    10811    10819     +8     
Flag Coverage Δ
ci 83.44% <94.25%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...Primitives/WorkflowPrimitiveParameterDefinition.cs 100.00% <100.00%> (ø)
...Abstractions/Queries/WorkflowCapabilitiesModels.cs 93.47% <100.00%> (+0.97%) ⬆️
....Workflow.Core/Primitives/WorkflowCallLifecycle.cs 100.00% <100.00%> (ø)
...rkflow.Core/Primitives/WorkflowPrimitiveCatalog.cs 95.19% <100.00%> (+0.19%) ⬆️
...ow/Aevatar.Workflow.Core/WorkflowCoreModulePack.cs 100.00% <100.00%> (ø)
...evatar.Workflow.Core/WorkflowModuleRegistration.cs 95.45% <100.00%> (+1.51%) ⬆️
....Schedules/Modules/WorkflowSelfRescheduleModule.cs 80.31% <100.00%> (+1.58%) ⬆️
...Extensions.Schedules/WorkflowScheduleModulePack.cs 100.00% <100.00%> (ø)
...ow.Core/Primitives/WorkflowPrimitiveDefinitions.cs 99.59% <99.59%> (ø)
...ties/WorkflowInfrastructureCapabilitiesProvider.cs 89.30% <81.25%> (-5.39%) ⬇️
... and 1 more

... and 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

1 participant