Skip to content

feat(apollo-react): add uipath.case.stage manifest and drive StageNode handles from it [MST-12554]#947

Draft
kittyyueli wants to merge 1 commit into
mainfrom
claude/friendly-curie-3429ra
Draft

feat(apollo-react): add uipath.case.stage manifest and drive StageNode handles from it [MST-12554]#947
kittyyueli wants to merge 1 commit into
mainfrom
claude/friendly-curie-3429ra

Conversation

@kittyyueli

@kittyyueli kittyyueli commented Jul 22, 2026

Copy link
Copy Markdown
Member

CLAUDE BUG BURN-DOWN

https://claude.ai/code/session_012dGQD9cuKGicUg426htYEy

Description

Follow-up to MST-12554 (add-stage handle on trigger vs. stages is inconsistent), taking the direction from the Case unified-schema onboarding doc: the stage node adopts the apollo manifest system rather than PO.Frontend keeping a custom add button.

What's in here:

  1. caseManagementStageManifest (uipath.case.stage) in CaseFlow/case-flow.manifest.ts, per the onboarding doc's stage manifest, adjusted per review:
    • display.shape: 'container' (the doc's 'group' is not a valid NodeShape); icon square-plus.
    • The doc's top condition handles are omitted (conditions have no manifest or visual display yet); handles are input (left target), next (right source, showButton: true), reentry (bottom source).
    • inputDefinition mirrors the current stage node data model: name, tasks, entryConditions, exitConditions, slaRules, stageType ('secondary' = exception stage, the combined node type).
    • A case-stage category is added, which also makes the trigger manifest's existing allowedTargetCategories: ['case-stage'] constraint resolvable. Category ids follow the ones already landed here (case-management-trigger).
  2. StageNodeHandles follows the unified flow schema strictly: handle groups and ids come straight from the manifest (input/next/reentry, same pattern as the trigger's output). No instance-scoped id rewriting and no legacy bottom target anchor. Runtime contributes only hover visibility and header-aligned notch offsets.
  3. New optional StageNode props onHandleAction / onHandleMouseEnter / onHandleMouseLeave, threaded to the handles. onHandleAction emits the manifest handle id (next). The add button renders only when onHandleAction is provided, so existing consumers see no change until they opt in.

Consumer side (PO.Frontend, will be handled in UiPath/PO.Frontend#6373):

  • Stage.tsx passes the new callbacks (replacing the custom circular StageNodeAddNodeButtonComponent).
  • Stage edge generation must emit the manifest handle ids, like it already does for the v24 trigger's output handle.
  • Pre-unified-schema documents' stage edges (e.g. "targetHandle": "stage-1____target____bottom") need the unified-schema edge migration to render against the new handle ids.

Testing

  • case-flow.manifest.test.ts: both manifests parse against nodeManifestSchema, categories parse, category cross-references resolve, handle ids unique, only next shows the button.
  • StageNode.test.tsx: add button renders and fires onHandleAction with the manifest next handle id; hidden without onHandleAction, in read-only, and on exception stages; manifest handle ids (input/next/reentry) render. Un-mocked useButtonHandles (was stubbed to null) and stubbed xyflow's Handle so handle rendering is actually exercised.
  • Full apollo-react suite green locally; tsc --noEmit clean; package build passes; Biome lint/format clean.
  • New Storybook story StageNode / Manifest Add Next Stage showing the opt-in add button.

Checklist

  • Uses tokens/design-system conventions
  • TypeScript types included
  • Storybook story
  • Unit tests
  • Visual regression tests (existing StageNode VR coverage applies; no new variant snapshots added)
  • No linting errors

Copilot AI review requested due to automatic review settings July 22, 2026 04:55
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (PT)
apollo-design 🟢 Ready Preview, Logs Jul 23, 2026, 12:19:09 AM
apollo-docs 🟢 Ready Preview, Logs Jul 23, 2026, 12:19:09 AM
apollo-landing 🟢 Ready Preview, Logs Jul 23, 2026, 12:19:09 AM
apollo-vertex 🟢 Ready Preview, Logs Jul 23, 2026, 12:19:09 AM

@github-actions

Copy link
Copy Markdown
Contributor

Dependency License Review

  • 1950 package(s) scanned
  • ✅ No license issues found
  • ⚠️ 2 package(s) excluded (see details below)
License distribution
License Packages
MIT 1720
ISC 89
Apache-2.0 55
BSD-3-Clause 27
BSD-2-Clause 23
BlueOak-1.0.0 8
MPL-2.0 4
MIT-0 3
CC0-1.0 3
MIT OR Apache-2.0 2
(MIT OR Apache-2.0) 2
Unlicense 2
LGPL-3.0-or-later 1
Python-2.0 1
CC-BY-4.0 1
(MPL-2.0 OR Apache-2.0) 1
Unknown 1
Artistic-2.0 1
(WTFPL OR MIT) 1
(BSD-2-Clause OR MIT OR Apache-2.0) 1
CC-BY-3.0 1
0BSD 1
(MIT OR CC0-1.0) 1
MIT AND ISC 1
Excluded packages
Package Version License Reason
@img/sharp-libvips-linux-x64 1.2.4 LGPL-3.0-or-later LGPL pre-built binary, not linked
khroma 2.1.0 Unknown MIT per GitHub repo, missing license field in package.json

@kittyyueli
kittyyueli force-pushed the claude/friendly-curie-3429ra branch from a742c6f to d839a7a Compare July 22, 2026 04:57
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

📊 Coverage + size by package

Per-package coverage and bundle size on this PR. New-line coverage = of the source lines this PR adds or changes, the % hit by tests.

Package Coverage New-line coverage Packed (gzip) Unpacked vs main
@uipath/apollo-core 9.0% 43.84 MB 57.45 MB ±0
@uipath/apollo-react 37.6% 75.0% (6/8) 7.40 MB 28.31 MB +810 B
@uipath/apollo-wind 41.0% 397.6 KB 2.58 MB −4 B
@uipath/ap-chat 85.8% 43.43 MB 55.93 MB +1.0 KB

"Coverage" is each package's own coverage.include scope (e.g. apollo-core instruments only scripts/). "Packed"/"Unpacked" come from npm pack --dry-run and only cover built packages — "—" means not measured this run (package not affected / not built). "vs main" is the packed (gzipped) delta against the last successful main build (the package-sizes artifact from the Release workflow); "—" there means no main baseline was available this run. The baseline is main's latest build, not this PR's exact merge-base, so it includes any drift since the branch diverged. Packages with no vitest config are omitted.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds a Case Management stage node manifest (uipath.case.stage) and updates the existing StageNode handle rendering so the standard canvas “add” button can be driven from manifest metadata (opt-in via callbacks), aligning Stage behavior with the manifest-based canvas node system.

Changes:

  • Introduces caseManagementStageManifest and a case-stage category, and registers both trigger + stage manifests in the combined caseFlowManifest.
  • Updates StageNodeHandles to derive rendered handle groups from the stage manifest (while preserving legacy instance-scoped handle ids and the bottom target anchor).
  • Adds optional StageNode handle callbacks and tests/story coverage to verify add-button rendering and behavior.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/apollo-react/src/canvas/components/StageNode/StageNodeHandles.tsx Derives handle groups from caseManagementStageManifest, preserves legacy handle ids/anchors, wires handle callbacks into useButtonHandles.
packages/apollo-react/src/canvas/components/StageNode/StageNode.types.ts Adds optional onHandleAction / onHandleMouseEnter / onHandleMouseLeave props for opt-in add-button behavior.
packages/apollo-react/src/canvas/components/StageNode/StageNode.tsx Threads the new optional handle callbacks through to StageNodeHandles.
packages/apollo-react/src/canvas/components/StageNode/StageNode.test.tsx Exercises real handle rendering (stubs xyflow Handle) and verifies add-button presence/behavior + legacy bottom target anchor.
packages/apollo-react/src/canvas/components/StageNode/StageNode.stories.tsx Adds a Storybook story demonstrating the manifest-driven “add next stage” button via onHandleAction.
packages/apollo-react/src/canvas/components/CaseFlow/index.ts Exports caseManagementStageManifest.
packages/apollo-react/src/canvas/components/CaseFlow/case-flow.manifest.ts Adds the case-stage category and defines caseManagementStageManifest; registers it in caseFlowManifest.
packages/apollo-react/src/canvas/components/CaseFlow/case-flow.manifest.test.ts Validates trigger + stage manifests/categories against schemas and checks key cross-references/uniqueness/button visibility rules.

Copilot AI review requested due to automatic review settings July 22, 2026 05:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Comment on lines +56 to +65
const manifestGroups = (caseManagementStageManifest.handleConfiguration ?? [])
.filter((group) => RENDERED_POSITIONS.has(group.position))
.map((group) => ({
position: group.position,
handles: group.handles.map((handle) => ({
id: `${id}____${handle.type}____${group.position}`,
type: handle.type,
handleType: handle.handleType,
showButton: handle.showButton,
})),

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Accurate description of the usePreviewNode lookup, but this is intentional and not a regression: the instance-scoped ids are the pre-existing StageNode scheme, and stage edges in existing case documents already anchor to them — switching the DOM ids to the manifest ids (input/next/reentry) would orphan those edges. The usePreviewNode/AddNodePanel flow also isn't used by the case canvas today (PO.Frontend has its own preview pipeline; this PR's add button goes through the new onHandleAction prop, not AddNodePanel). Documented this as a known limitation in the code comment here, with id unification deferred to the unified-schema edge migration, which has to migrate existing documents' edges anyway.


Generated by Claude Code

@kittyyueli kittyyueli Jul 23, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'd rather move completely to using flow unified schema so I want to follow that as strictly as possible

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done — reworked to follow the flow unified schema strictly: StageNodeHandles now uses the manifest handle ids verbatim (input/next/reentry, same pattern as the trigger's output), no instance-scoped rewriting, and the legacy bottom target anchor is removed. onHandleAction now emits the manifest id. Follow-ups this implies on the PO.Frontend side (will handle in #6373): stage edge generation must emit the manifest ids like it already does for the v24 trigger, and pre-unified-schema documents' stage edges (e.g. stage-1____target____bottom in existing case JSON) will need the edge migration to render again.


Generated by Claude Code

Comment on lines +104 to +108
/**
* Fired when the manifest-driven add button on a source handle is clicked
* (the `next` handle of `caseManagementStageManifest`). The add button only
* renders when this callback is provided.
*/
Copilot AI review requested due to automatic review settings July 22, 2026 05:12
@kittyyueli
kittyyueli force-pushed the claude/friendly-curie-3429ra branch from d839a7a to e994699 Compare July 22, 2026 05:12

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

@kittyyueli kittyyueli self-assigned this Jul 22, 2026
Comment thread packages/apollo-react/src/canvas/components/CaseFlow/case-flow.manifest.ts Outdated
Comment thread packages/apollo-react/src/canvas/components/CaseFlow/case-flow.manifest.ts Outdated
Comment thread packages/apollo-react/src/canvas/components/CaseFlow/case-flow.manifest.ts Outdated
Comment thread packages/apollo-react/src/canvas/components/CaseFlow/case-flow.manifest.ts Outdated
Comment thread packages/apollo-react/src/canvas/components/CaseFlow/case-flow.manifest.ts Outdated
Comment on lines +83 to +92
// Legacy re-entry anchor: not part of the manifest, but existing edges
// target `${id}____target____bottom`, so it must keep rendering.
{
position: Position.Bottom,
handles: [
{
id: `${id}____target____bottom`,
type: 'target' as const,
handleType: 'input' as const,
},

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

why do we need to keep the legacy one?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Removed. It was there because existing case documents' re-entry edges anchor to it ("targetHandle": "stage-1____target____bottom" in e.g. PO.Frontend's example.case.json), but per your call to follow the flow schema strictly, those edges are now covered by the unified-schema edge migration instead. The reentry manifest handle is the only bottom handle now.


Generated by Claude Code

Copilot AI review requested due to automatic review settings July 23, 2026 04:57
@kittyyueli
kittyyueli force-pushed the claude/friendly-curie-3429ra branch from e994699 to 16ec773 Compare July 23, 2026 04:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

packages/apollo-react/src/canvas/components/StageNode/StageNodeHandles.tsx:73

  • Handle ids are derived as ${id}____${handle.type}____${group.position}. This collapses multiple manifest handles that share the same position+type into the same DOM id (the manifest schema allows multiple handles per group, including repeat). That will produce duplicate handle ids and make edges/connected-handle visibility ambiguous if the stage manifest ever adds a second handle on the same side.

Consider preserving the legacy ids for the existing anchors, but disambiguating any additional handles by appending the manifest handle id.

        handles: group.handles.map((handle) => ({
          id: `${id}____${handle.type}____${group.position}`,
          type: handle.type,
          handleType: handle.handleType,
          showButton: handle.showButton,
        })),

Comment on lines +7 to +10
* Scope (this file): trigger and stage nodes. Exception stages are regular stages
* with `isSecondary` instance metadata (the two node types were combined), so they
* share the stage manifest. Task, condition, and edge manifests are intentionally
* out of scope.
Copilot AI review requested due to automatic review settings July 23, 2026 05:03
@kittyyueli
kittyyueli force-pushed the claude/friendly-curie-3429ra branch from 16ec773 to 1bca828 Compare July 23, 2026 05:03

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (2)

packages/apollo-react/src/canvas/components/StageNode/StageNodeHandles.tsx:46

  • StageNodeHandles now renders handles with manifest ids (input/next/reentry). However, this package still includes StageNode edge examples that reference the legacy instance-scoped handle ids (e.g. 0____source____right / 1____target____left in StageNode.stories.tsx:600+), which will no longer anchor correctly. Those fixtures (and any downstream consumers still emitting legacy handle ids) need to be migrated to the new ids as part of this change, otherwise Storybook examples and existing graphs can regress.
  const handleConfigurations: HandleGroupManifest[] = useMemo(() => {
    if (isException) return [];

    const visible = selected || isHovered || isConnecting;
    return (caseManagementStageManifest.handleConfiguration ?? []).map((group) => ({

packages/apollo-react/src/canvas/components/StageNode/StageNodeHandles.tsx:72

  • The PR description mentions that a “legacy bottom target anchor still renders”, but StageNodeHandles now derives handles exclusively from the manifest, and the stage manifest defines only input (left target), next (right source), and reentry (bottom source) with no bottom target handle. Please update the PR description (or reintroduce the legacy anchor if it’s still required) to avoid confusion for reviewers/consumers.
  const handleElements = useButtonHandles({
    handleConfigurations,
    shouldShowHandles,
    nodeId: id,
    selected,
    hovered: isHovered,
    showAddButton: !isReadOnly,
    handleAction: onHandleAction,
    handleMouseEnter: onHandleMouseEnter,
    handleMouseLeave: onHandleMouseLeave,
  });

Comment on lines +38 to +41
// Handle groups come straight from `caseManagementStageManifest` (ids included,
// per the unified flow schema); the runtime contributes only hover visibility
// and the header-aligned notch offsets. Edges reference the manifest handle ids
// (`input` / `next` / `reentry`); pre-unified-schema documents are migrated.
Comment on lines +342 to +344
onHandleAction: () => {
window.alert('Add next stage: this would append a new stage after Intake');
},
Copilot AI review requested due to automatic review settings July 23, 2026 06:10
@kittyyueli
kittyyueli force-pushed the claude/friendly-curie-3429ra branch from 1bca828 to c297874 Compare July 23, 2026 06:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

packages/apollo-react/src/canvas/components/StageNode/StageNodeHandles.tsx:60

  • StageNodeHandles is meant to be manifest-driven, but the mapping currently rebuilds each handle with only {id,type,handleType,showButton}. This drops other manifest fields that are already defined on the stage manifest (e.g. constraints, isDefaultForType, and any future handle/group metadata like boundary, connectionPosition, labelVisibility). That makes the rendered handle config diverge from the manifest and can silently disable constraint/behavior metadata.

Consider preserving the manifest objects and only overriding the few runtime-controlled fields (visibility + left/right notch offsets).

    return (caseManagementStageManifest.handleConfiguration ?? []).map((group) => ({
      position: group.position,
      handles: group.handles.map((handle) => ({
        id: handle.id,
        type: handle.type,
        handleType: handle.handleType,
        showButton: handle.showButton,
      })),
      visible,
      customPositionAndOffsets:
        group.position === Position.Left || group.position === Position.Right
          ? { top: 0, height: HANDLE_LANE_HEIGHT }
          : undefined,
    }));

…e handles from it

Adds caseManagementStageManifest per the Case unified-schema onboarding doc
(MST-12554), with two corrections against the doc's draft: display.shape is
'container' ('group' is not a valid NodeShape), and the top source handle is
'exitConditions' (the doc lists 'entryConditions' twice). Category ids follow
the ones already landed here.

StageNodeHandles now derives its handle groups from the manifest instead of
an inline hardcoded list, keeping the per-instance handle id scheme existing
edges anchor to, plus the legacy bottom target anchor. The manifest's next
handle carries showButton: true, so StageNode gains optional onHandleAction /
onHandleMouseEnter / onHandleMouseLeave props that light up the standard
canvas add button, the same affordance BaseNode-driven nodes (e.g. the case
trigger) already use.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012dGQD9cuKGicUg426htYEy
Copilot AI review requested due to automatic review settings July 23, 2026 07:13
@kittyyueli
kittyyueli force-pushed the claude/friendly-curie-3429ra branch from c297874 to 5a7b088 Compare July 23, 2026 07:13

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants