adobe-to-docusign-migrator/docs/CONDITIONAL-LOGIC-DESIGN.md

11 KiB

Conditional Logic: Gap Analysis & Design

This document captures the structural differences between Adobe Sign's and DocuSign's conditional field models, which gaps are solvable in the migrator, and the design of proposed solutions. It complements field-mapping.md (current-state reference) and IMPLEMENTATION-PLAN.md (feature history).


Background: The Two Models

Adobe Sign supports full conditional logic per field:

  • conditionalAction.predicates[] — one or more {fieldName, operator, value} tuples
  • anyOrAll — ANY (OR) or ALL (AND) combining semantics
  • action — SHOW or HIDE the field
  • operator — EQUALS, NOT_EQUALS, GT, LT, CONTAINS, etc.
  • The trigger field can belong to any recipient; cross-recipient conditions are valid

DocuSign supports a single, simple reveal condition per tab:

  • conditionalParentLabel — the tabLabel or groupName of the trigger tab
  • conditionalParentValue — the exact string value that reveals the tab
  • The trigger tab must be a listTab, radioGroupTab, or checkboxTab
  • The trigger and the dependent tab must belong to the same recipient
  • Only one condition per tab, always EQUALS, always a SHOW (reveal)

This is the deepest structural asymmetry in the migration. Every gap below flows from the gap between these two models.


Gap Catalog

Gap 1 — HIDE action

Adobe: action: HIDE — field is visible by default and hides when the condition is met.
DocuSign: No equivalent. DocuSign only supports revealing a tab that starts hidden.
Current behavior: Condition dropped; field always visible. HIDE_ACTION issue emitted.

Gap 2 — NOT_EQUALS and other operators

Adobe: Supports NOT_EQUALS, GT, LT, CONTAINS, etc.
DocuSign: Only EQUALS is supported.
Current behavior: Condition dropped; field always visible. UNSUPPORTED_OPERATOR issue emitted.

The most common real-world case is NOT_EQUALS "" (show this field if the user entered anything in another field). This is doubly broken in DocuSign:

  1. NOT_EQUALS has no equivalent
  2. Text fields can't be conditional parents at all (see Gap 5)

Gap 3 — Cross-recipient conditionals

Adobe: Field B can show/hide based on the value of Field A even if A and B belong to different recipients.
DocuSign: conditionalParentLabel resolves only within the same recipient's tab set. The API silently ignores or rejects cross-recipient references.
Current behavior: Condition dropped. CROSS_RECIPIENT_CONDITIONAL issue emitted.

Gap 4 — Multi-predicate ANY (OR) logic

Adobe: anyOrAll: ANY with multiple predicates — show if condition 1 OR condition 2 OR …
DocuSign: One conditionalParentValue per tab — no native OR.
Current behavior: Only the first EQUALS predicate is mapped; rest are dropped. MULTI_PREDICATE issue emitted.

Gap 5 — Invalid conditional parent tab types

Adobe: Any field can be a conditional trigger — text fields, signature fields, anything.
DocuSign: Only listTabs, radioGroupTabs, and checkboxTabs may be conditional parents. All other types cause CONDITIONALTAB_HAS_INVALID_PARENT (400).
Current behavior: Strip pass removes conditions referencing invalid parent types. INVALID_PARENT_TAB issue emitted.

Gap 6 — Multi-predicate ALL (AND) logic

Adobe: anyOrAll: ALL — show only if ALL conditions are simultaneously true.
DocuSign: No AND logic at the template conditional level.
Current behavior: Only the first EQUALS predicate is mapped. MULTI_PREDICATE issue emitted.


The DocuSign "Flags" Technique

DocuSign's "Building Advanced Templates" guide describes using hidden intermediate tabs ("flags") to work around the platform's single-parent conditional model. The pattern:

  1. Create a hidden checkboxTab or listTab — the "flag" — placed out of the visible form area or given locked: true, selected: false.
  2. Make the flag conditionally revealed by one condition (the flag itself is shown when condition A is true).
  3. Make the dependent field conditionally revealed when the flag is in a specific state.

This creates two-level conditional depth. However, DocuSign tabs don't auto-set their own value — a checkbox flag only "activates" when the signer checks it, or when the sender pre-fills it before sending. This limits the technique to two scenarios:

Scenario A — Sender-prefill flags: The sender manually checks/sets flags before routing the envelope, making explicit business logic decisions that the template cannot express automatically. Useful for bespoke workflows but not for automated migration.

Scenario B — Checkbox-group section selectors: For OR-style logic driven by a single dropdown, radio group, or checkbox, the flag technique is not needed — the multi-copy approach (Gap 4 solution below) handles this cleanly.

Bottom line: The flag technique is a UI/manual-workflow tool, not an automated migration output. It doesn't solve AND logic or cross-recipient conditions without human intervention at sending time.


Solvable Gaps: Proposed Designs

Solution A — ANY multi-predicate fan-out (addresses Gap 4, partially Gap 2)

Scope: When anyOrAll: ANY and all predicates share the same parent field and all use EQUALS, the OR logic can be emitted as one copy of the dependent tab per predicate value, all at the same coordinates with the same tabLabel.

At signing time, DocuSign shows exactly the copies whose condition is satisfied. Because the copies share a tabLabel, their values sync — the signer fills one and DocuSign treats them as the same logical field.

Before (current output — only first predicate mapped):

{ "tabLabel": "Notes", "conditionalParentLabel": "Category",
  "conditionalParentValue": "Option A" }

After (fan-out):

{ "tabLabel": "Notes", "conditionalParentLabel": "Category",
  "conditionalParentValue": "Option A" },
{ "tabLabel": "Notes", "conditionalParentLabel": "Category",
  "conditionalParentValue": "Option B" }

NOT_EQUALS expansion (Gap 2, dropdown parents only): When the operator is NOT_EQUALS and the parent is a listTab, look up the parent field's option list and compute the complement — emit one copy per remaining value. This covers the common "show unless user picked X" pattern.

Limitations:

  • Only works when all predicates reference the same parent field
  • Mixed-parent ANY (field A = x OR field B = y) is still unsupported
  • NOT_EQUALS expansion only works for listTab parents with a finite option set
  • Text field parents remain invalid regardless of operator (Gap 5)

New issue codes proposed:

  • MULTI_PREDICATE_EXPANDED (info) — OR logic successfully fanned out
  • NOT_EQUALS_EXPANDED (info) — NOT_EQUALS resolved via complement enumeration
  • NOT_EQUALS_UNEXPANDABLE (warning) — NOT_EQUALS on a non-list parent; condition dropped

Solution B — Richer guidance messages for unsolvable gaps

All currently unsolvable gaps emit a generic "condition dropped" message. Each gap warrants a specific, actionable message explaining the constraint and what to do manually.

Gap Improved guidance
HIDE_ACTION "Restructure as a SHOW condition: start the field hidden (remove it from the base layout) and show it when the inverse condition is met. If the trigger is a dropdown, this requires listing all values that should reveal the field."
CROSS_RECIPIENT_CONDITIONAL "Add a prefill recipient (routing order 0) that holds the controlling field. Downstream signers' conditional fields can then reference the prefill tab. The sender sets the value before routing."
INVALID_PARENT_TAB (text parent) "DocuSign requires a dropdown, radio group, or checkbox as the condition trigger. Replace the text field trigger with a dropdown containing expected values, then the condition can be mapped."
MULTI_PREDICATE (mixed parents) "DocuSign supports one condition per field. Split this field into two separate positioned fields, each conditional on one predicate."

Unsolvable Gaps (Fundamental Limits of DocuSign Templates)

These gaps cannot be addressed at the template layer regardless of technique:

Gap Why
HIDE action (general) DocuSign has no "start visible, hide when X" model. Inversion via complement enumeration only works for dropdown triggers with finite option sets.
Text field as conditional parent DocuSign's API flatly rejects any tab type other than listTabs, radioGroupTabs, checkboxTabs as a parent — this is a server-side constraint, not a schema quirk.
AND logic (multi-predicate ALL) DocuSign template conditionals have no AND. The flag chaining technique requires a human to set intermediate flags at sending time, making it unsuitable for automated migration output.
Mixed-parent ANY "Show if field A = x OR field B = y" requires two independent conditions on the same tab, which the single-parent model cannot express.
Cross-recipient without prefill restructure True cross-recipient logic (signer 2's visibility driven by signer 1's choice) requires restructuring the recipient list to add a prefill signer — a structural change, not a tab-level fix.

The right platform for these cases is DocuSign Maestro (Workflow automation), which supports proper conditional branching, cross-step data references, and decision gateways. Templates with significant AND logic or cross-recipient conditionals should be flagged as Maestro candidates in the migration report.


Proposed Implementation Phases

Phase 24 — NOT_EQUALS expansion for dropdown parents

  • Detect operator: NOT_EQUALS where parent field is a listTab
  • Look up parent's hiddenOptions/visibleOptions from the Adobe source fields
  • Compute complement set (all options except the excluded value)
  • Emit one tab copy per remaining option with conditionalParentValue = option
  • Emit NOT_EQUALS_EXPANDED info issue
  • Emit NOT_EQUALS_UNEXPANDABLE warning for non-list parents (unchanged drop behavior)
  • Tests: unit tests for complement computation; regression snapshots updated

Phase 25 — ANY multi-predicate fan-out

  • Detect anyOrAll: ANY, multiple predicates, all referencing the same parent field, all using EQUALS
  • Emit one tab copy per predicate value at the same coordinates with the same tabLabel
  • Emit MULTI_PREDICATE_EXPANDED info issue
  • Cases with mixed parents or non-EQUALS operators keep MULTI_PREDICATE warning
  • Tests: unit tests covering fan-out; mixed-parent case stays as warning

Phase 26 — Richer issue guidance text

  • Update HIDE_ACTION, CROSS_RECIPIENT_CONDITIONAL, INVALID_PARENT_TAB, and MULTI_PREDICATE message strings to include specific manual fix instructions
  • No behavioral change — UI display only
  • Tests: update any tests that assert on exact message strings

Phase 27 — Maestro escalation advisory

  • Add template-level MAESTRO_RECOMMENDED advisory (distinct from per-field issues) when a template contains unresolvable AND logic, cross-recipient conditionals, or HIDE actions that affect more than N fields (threshold TBD)
  • Surface in the Issues tab of the template detail view
  • No code generation — guidance only

Created: 2026-05-14. Companion documents: field-mapping.md (current-state reference), docs/IMPLEMENTATION-PLAN.md (feature history), tests/EDGE-CASES.md (known edge cases).