changedInput schema / properties / steps / items / oneOf
Previous value: -[
- {
- "properties": {
- "action": {
- "anyOf": [
- {
- "minLength": 1,
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Verb-led one-liner summarizing the concrete action performed. Example: \"Reviews invoice line items in NetSuite against the purchase order.\""
- },
- "assumptions": {
- "anyOf": [
- {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- {
- "type": "null"
- }
- ],
- "description": "Assumptions the LLM made when extracting this step that were not directly stated in captures. Null if none. Used by verification agents to flag risky inferences. Example: [\"Invoices are reviewed within 24 hours of receipt\"]"
- },
- "condition": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Always null on events; included for shape compatibility across variants."
- },
- "confidence": {
- "description": "Confidence in the accuracy of this step given evidence quality and completeness. \"high\" = directly stated by multiple sources, \"medium\" = stated by one source or inferred from strong signals, \"low\" = inferred with significant assumptions.",
- "enum": [
- "low",
- "medium",
- "high"
- ],
- "type": "string"
- },
- "description": {
- "anyOf": [
- {
- "minLength": 1,
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Optional prose describing what happens at this event. May be null for structural markers."
- },
- "exception": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Known exceptions, errors, or failure modes observed in the captures for this step. Null when none were mentioned. Example: \"Customer disputes line items or PO number does not match\""
- },
- "extraCaptureNeeded": {
- "anyOf": [
- {
- "properties": {
- "gap": {
- "description": "Plain-language description of what about this step is unknown or under-specified, blocking automation. One short sentence. Example: \"We don't know which fields the AP analyst copies from the invoice into NetSuite.\"",
- "minLength": 1,
- "type": "string"
- },
- "id": {
- "description": "Id of the `clarity_proposal_extra_capture_request` row this slot points at. Created server-side by the agent after the LLM call; the LLM never produces this value.",
- "format": "uuid",
- "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
- "type": "string"
- },
- "proposal": {
- "anyOf": [
- {
- "minLength": 1,
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "What the new capture should include in order to resolve the gap — concrete actions, screens, or decisions the user should walk through. Optional: omit when no specific proposal can be inferred. Example: \"Walk through reviewing one invoice in NetSuite end-to-end while narrating each field you check.\""
- }
- },
- "required": [
- "id",
- "gap"
- ],
- "type": "object"
- },
- {
- "type": "null"
- }
- ]
- },
- "handling": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "How exceptions or escalations are handled — escalation path, fallback action, or retry strategy. Null when no exception or no handling described. Example: \"Escalate to AP manager via email and pause processing until resolved\""
- },
- "id": {
- "description": "Stable identifier for the step. Referenced by targetSteps[].stepId and by postprocessing agents annotating specific steps. Example: \"step-review-invoice\"",
- "minLength": 1,
- "type": "string"
- },
- "input": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Information or artifacts required to start this step. Null on start events or steps with no preconditions. Example: \"Invoice PDF and matching purchase order number\""
- },
- "nodeSubtype": {
- "description": "BPMN event subtype. \"start\" (entry trigger), \"end\" (terminal state), \"timer\" (time-based wait), \"message\" (external communication), \"escalation\" (route to higher authority).",
- "enum": [
- "start",
- "end",
- "timer",
- "message",
- "escalation"
- ],
- "type": "string"
- },
- "nodeType": {
- "const": "event",
- "type": "string"
- },
- "openQuestions": {
- "anyOf": [
- {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- {
- "type": "null"
- }
- ],
- "description": "Specific gaps in understanding that a follow-up capture should address. Null if none. Drives the next interview or document request. Example: [\"Is there a backup approver when the AP manager is out of office?\"]"
- },
- "output": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "What this step produces or updates. Null on pure waits or events that emit nothing. Example: \"Approved invoice record in NetSuite with reviewer signature\""
- },
- "rationale": {
- "anyOf": [
- {
- "minLength": 1,
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Optional reason for the event's existence. May be null for structural markers."
- },
- "readiness": {
- "anyOf": [
- {
- "enum": [
- "low",
- "medium",
- "high"
- ],
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Automation-readiness rating for this step. \"high\" = fully automatable today, \"medium\" = partially automatable or needs minor changes, \"low\" = blocked by manual review, judgement, or missing data."
- },
- "readinessRationale": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "One-sentence justification for the readiness rating, citing the specific signals that drove the choice. Example: \"Requires human judgement on edge cases that are not documented in the captures.\""
- },
- "role": {
- "anyOf": [
- {
- "minLength": 1,
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Performer of this step — the specific job title, team, or system. Use \"Duvo\" for automated actions and \"System\" for system-triggered steps. Examples: \"Finance Analyst\", \"Sales Operations\", \"Duvo\", \"System\""
- },
- "sources": {
- "description": "Evidence supporting this event. Empty array allowed (structural markers carry no evidence); non-empty values must follow the source schema.",
- "items": {
- "properties": {
- "attribution": {
- "description": "Human-readable source label identifying who or what the evidence comes from. Examples: \"Anna (sales interview)\", \"Onboarding SOP §3.2\", \"Slack #ops 2024-06-12\"",
- "minLength": 1,
- "type": "string"
- },
- "captureId": {
- "description": "Durable clarity_capture id for this source. Use app-owned ids from the evidence index, never sandbox file paths.",
- "minLength": 1,
- "type": "string"
- },
- "evidenceId": {
- "description": "Stable id of the evidence unit from /workspace/captures/evidence-index.json when generation used that index.",
- "minLength": 1,
- "type": "string"
- },
- "excerpt": {
- "description": "Verbatim supporting text quoted from the capture, document, or transcript. Example: \"We always wait for finance to sign off before sending the invoice.\"",
- "minLength": 1,
- "type": "string"
- },
- "locator": {
- "description": "Durable in-capture location for the excerpt. Missing means legacy free-text source; unresolved means a structured citation was attempted but could not be resolved.",
- "oneOf": [
- {
- "properties": {
- "messageIndex": {
- "description": "Zero-based index into the capture transcript message array. This is the durable key; timestampMs is only supplemental.",
- "maximum": 9007199254740991,
- "minimum": 0,
- "type": "integer"
- },
- "timestampMs": {
- "description": "Optional epoch-millisecond timestamp for the transcript message when the capture supplied one.",
- "maximum": 9007199254740991,
- "minimum": 0,
- "type": "integer"
- },
- "type": {
- "const": "transcript_message",
- "type": "string"
- }
- },
- "required": [
- "type",
- "messageIndex"
- ],
- "type": "object"
- },
- {
- "properties": {
- "endLine": {
- "description": "Optional one-based line number where the cited text ends on pageNumber.",
- "exclusiveMinimum": 0,
- "maximum": 9007199254740991,
- "type": "integer"
- },
- "endOffset": {
- "description": "Exclusive character offset into the stored capture text. Must be greater than startOffset.",
- "exclusiveMinimum": 0,
- "maximum": 9007199254740991,
- "type": "integer"
- },
- "pageNumber": {
- "description": "Optional one-based PDF page number when the stored capture has page metadata.",
- "exclusiveMinimum": 0,
- "maximum": 9007199254740991,
- "type": "integer"
- },
- "startLine": {
- "description": "Optional one-based line number where the cited text starts on pageNumber.",
- "exclusiveMinimum": 0,
- "maximum": 9007199254740991,
- "type": "integer"
- },
- "startOffset": {
- "description": "Zero-based character offset into the stored capture text.",
- "maximum": 9007199254740991,
- "minimum": 0,
- "type": "integer"
- },
- "type": {
- "const": "document_text_range",
- "type": "string"
- }
- },
- "required": [
- "type",
- "startOffset",
- "endOffset"
- ],
- "type": "object"
- },
- {
- "properties": {
- "elementId": {
- "description": "BPMN XML element id within an uploaded .bpmn document.",
- "minLength": 1,
- "type": "string"
- },
- "elementType": {
- "description": "Optional BPMN element type as parsed from the XML, for example \"bpmn:UserTask\" or \"bpmn:ExclusiveGateway\".",
- "minLength": 1,
- "type": "string"
- },
- "name": {
- "description": "Optional BPMN element name as parsed from the XML. The element id is the durable key.",
- "minLength": 1,
- "type": "string"
- },
- "type": {
- "const": "bpmn_element",
- "type": "string"
- }
- },
- "required": [
- "type",
- "elementId"
- ],
- "type": "object"
- },
- {
- "properties": {
- "timestampMs": {
- "description": "Epoch-millisecond frame timestamp matching a screenshare frame filename.",
- "maximum": 9007199254740991,
- "minimum": 0,
- "type": "integer"
- },
- "type": {
- "const": "screenshare_frame",
- "type": "string"
- }
- },
- "required": [
- "type",
- "timestampMs"
- ],
- "type": "object"
- },
- {
- "properties": {
- "type": {
- "const": "manual",
- "type": "string"
- }
- },
- "required": [
- "type"
- ],
- "type": "object"
- },
- {
- "properties": {
- "reason": {
- "minLength": 1,
- "type": "string"
- },
- "type": {
- "const": "unresolved",
- "type": "string"
- }
- },
- "required": [
- "type"
- ],
- "type": "object"
- }
- ]
- },
- "resolutionStatus": {
- "description": "Resolution status for the structured source link. Legacy sources may omit this field.",
- "enum": [
- "resolved",
- "unresolved",
- "legacy",
- "manual"
- ],
- "type": "string"
- },
- "sourceConfidence": {
- "description": "Confidence in this individual source citation. \"high\" = direct quote at the locator, \"medium\" = strong nearby evidence, \"low\" = weak or inferred support.",
- "enum": [
- "low",
- "medium",
- "high"
- ],
- "type": "string"
- }
- },
- "required": [
- "attribution",
- "excerpt"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "system": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "System, tool, or application used to perform this step. Null when the step is purely manual or is a decision/event with no associated tool. Examples: \"NetSuite\", \"Gmail\", \"Excel\", null"
- },
- "targetSteps": {
- "description": "Outgoing BPMN edges from this step. Empty array only on end events. Exclusive and inclusive gateways must have ≥2 entries with exactly one isDefault: true.",
- "items": {
- "properties": {
- "isDefault": {
- "description": "True on exactly one outgoing edge of an exclusive or inclusive gateway, marking the fallback taken when no other condition matches. False on all other edges.",
- "type": "boolean"
- },
- "label": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Human-readable label shown on the BPMN edge. For gateways, the outcome answer; for default flows, \"Otherwise\". Examples: \"Approved\", \"> $5k\", \"Otherwise\""
- },
- "stepId": {
- "description": "Id of the step this edge points to. Must match an existing step.id in the same steps array. Example: \"step-review-invoice\"",
- "minLength": 1,
- "type": "string"
- }
- },
- "required": [
- "stepId",
- "label",
- "isDefault"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "title": {
- "description": "Required node label used in lists and BPMN node labels. Structural markers use defaults such as \"Start\" and \"End\".",
- "minLength": 1,
- "type": "string"
- }
- },
- "required": [
- "id",
- "targetSteps",
- "title",
- "action",
- "role",
- "system",
- "input",
- "output",
- "exception",
- "handling",
- "assumptions",
- "openQuestions",
- "confidence",
- "nodeType",
- "nodeSubtype",
- "description",
- "rationale",
- "sources",
- "condition"
- ],
- "type": "object"
- },
- {
- "properties": {
- "action": {
- "anyOf": [
- {
- "minLength": 1,
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Verb-led one-liner summarizing the concrete action performed. Example: \"Reviews invoice line items in NetSuite against the purchase order.\""
- },
- "assumptions": {
- "anyOf": [
- {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- {
- "type": "null"
- }
- ],
- "description": "Assumptions the LLM made when extracting this step that were not directly stated in captures. Null if none. Used by verification agents to flag risky inferences. Example: [\"Invoices are reviewed within 24 hours of receipt\"]"
- },
- "condition": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Optional precondition that gates this task. Null when the task is unconditional. Example: \"Only when invoice total exceeds $10,000\""
- },
- "confidence": {
- "description": "Confidence in the accuracy of this step given evidence quality and completeness. \"high\" = directly stated by multiple sources, \"medium\" = stated by one source or inferred from strong signals, \"low\" = inferred with significant assumptions.",
- "enum": [
- "low",
- "medium",
- "high"
- ],
- "type": "string"
- },
- "description": {
- "description": "Full prose paragraph describing what happens in this step in natural language. Used for documentation reconstruction. Example: \"Finance reviews the invoice in NetSuite, checking line item accuracy and matching against the purchase order before flagging for approval.\"",
- "minLength": 1,
- "type": "string"
- },
- "exception": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Known exceptions, errors, or failure modes observed in the captures for this step. Null when none were mentioned. Example: \"Customer disputes line items or PO number does not match\""
- },
- "extraCaptureNeeded": {
- "anyOf": [
- {
- "properties": {
- "gap": {
- "description": "Plain-language description of what about this step is unknown or under-specified, blocking automation. One short sentence. Example: \"We don't know which fields the AP analyst copies from the invoice into NetSuite.\"",
- "minLength": 1,
- "type": "string"
- },
- "id": {
- "description": "Id of the `clarity_proposal_extra_capture_request` row this slot points at. Created server-side by the agent after the LLM call; the LLM never produces this value.",
- "format": "uuid",
- "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
- "type": "string"
- },
- "proposal": {
- "anyOf": [
- {
- "minLength": 1,
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "What the new capture should include in order to resolve the gap — concrete actions, screens, or decisions the user should walk through. Optional: omit when no specific proposal can be inferred. Example: \"Walk through reviewing one invoice in NetSuite end-to-end while narrating each field you check.\""
- }
- },
- "required": [
- "id",
- "gap"
- ],
- "type": "object"
- },
- {
- "type": "null"
- }
- ]
- },
- "handling": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "How exceptions or escalations are handled — escalation path, fallback action, or retry strategy. Null when no exception or no handling described. Example: \"Escalate to AP manager via email and pause processing until resolved\""
- },
- "id": {
- "description": "Stable identifier for the step. Referenced by targetSteps[].stepId and by postprocessing agents annotating specific steps. Example: \"step-review-invoice\"",
- "minLength": 1,
- "type": "string"
- },
- "input": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Information or artifacts required to start this step. Null on start events or steps with no preconditions. Example: \"Invoice PDF and matching purchase order number\""
- },
- "nodeSubtype": {
- "description": "BPMN task subtype. \"user\" (human work), \"service\" (automated/API call), \"send\"/\"receive\" (messaging), \"manual\" (offline physical work), \"businessRule\" (rule engine), \"script\" (code execution).",
- "enum": [
- "user",
- "service",
- "send",
- "receive",
- "manual",
- "businessRule",
- "script"
- ],
- "type": "string"
- },
- "nodeType": {
- "const": "task",
- "type": "string"
- },
- "openQuestions": {
- "anyOf": [
- {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- {
- "type": "null"
- }
- ],
- "description": "Specific gaps in understanding that a follow-up capture should address. Null if none. Drives the next interview or document request. Example: [\"Is there a backup approver when the AP manager is out of office?\"]"
- },
- "output": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "What this step produces or updates. Null on pure waits or events that emit nothing. Example: \"Approved invoice record in NetSuite with reviewer signature\""
- },
- "rationale": {
- "description": "Why this step exists in the process — its purpose or business reason. Used by downstream agents to assess whether the step is essential or removable. Example: \"Catches mispriced line items before they reach the customer and prevents downstream credit notes.\"",
- "minLength": 1,
- "type": "string"
- },
- "readiness": {
- "anyOf": [
- {
- "enum": [
- "low",
- "medium",
- "high"
- ],
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Automation-readiness rating for this step. \"high\" = fully automatable today, \"medium\" = partially automatable or needs minor changes, \"low\" = blocked by manual review, judgement, or missing data."
- },
- "readinessRationale": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "One-sentence justification for the readiness rating, citing the specific signals that drove the choice. Example: \"Requires human judgement on edge cases that are not documented in the captures.\""
- },
- "role": {
- "anyOf": [
- {
- "minLength": 1,
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Performer of this step — the specific job title, team, or system. Use \"Duvo\" for automated actions and \"System\" for system-triggered steps. Examples: \"Finance Analyst\", \"Sales Operations\", \"Duvo\", \"System\""
- },
- "sources": {
- "description": "Evidence supporting this step's existence and details. At least one source is required — every step must trace back to something in the captures.",
- "items": {
- "properties": {
- "attribution": {
- "description": "Human-readable source label identifying who or what the evidence comes from. Examples: \"Anna (sales interview)\", \"Onboarding SOP §3.2\", \"Slack #ops 2024-06-12\"",
- "minLength": 1,
- "type": "string"
- },
- "captureId": {
- "description": "Durable clarity_capture id for this source. Use app-owned ids from the evidence index, never sandbox file paths.",
- "minLength": 1,
- "type": "string"
- },
- "evidenceId": {
- "description": "Stable id of the evidence unit from /workspace/captures/evidence-index.json when generation used that index.",
- "minLength": 1,
- "type": "string"
- },
- "excerpt": {
- "description": "Verbatim supporting text quoted from the capture, document, or transcript. Example: \"We always wait for finance to sign off before sending the invoice.\"",
- "minLength": 1,
- "type": "string"
- },
- "locator": {
- "description": "Durable in-capture location for the excerpt. Missing means legacy free-text source; unresolved means a structured citation was attempted but could not be resolved.",
- "oneOf": [
- {
- "properties": {
- "messageIndex": {
- "description": "Zero-based index into the capture transcript message array. This is the durable key; timestampMs is only supplemental.",
- "maximum": 9007199254740991,
- "minimum": 0,
- "type": "integer"
- },
- "timestampMs": {
- "description": "Optional epoch-millisecond timestamp for the transcript message when the capture supplied one.",
- "maximum": 9007199254740991,
- "minimum": 0,
- "type": "integer"
- },
- "type": {
- "const": "transcript_message",
- "type": "string"
- }
- },
- "required": [
- "type",
- "messageIndex"
- ],
- "type": "object"
- },
- {
- "properties": {
- "endLine": {
- "description": "Optional one-based line number where the cited text ends on pageNumber.",
- "exclusiveMinimum": 0,
- "maximum": 9007199254740991,
- "type": "integer"
- },
- "endOffset": {
- "description": "Exclusive character offset into the stored capture text. Must be greater than startOffset.",
- "exclusiveMinimum": 0,
- "maximum": 9007199254740991,
- "type": "integer"
- },
- "pageNumber": {
- "description": "Optional one-based PDF page number when the stored capture has page metadata.",
- "exclusiveMinimum": 0,
- "maximum": 9007199254740991,
- "type": "integer"
- },
- "startLine": {
- "description": "Optional one-based line number where the cited text starts on pageNumber.",
- "exclusiveMinimum": 0,
- "maximum": 9007199254740991,
- "type": "integer"
- },
- "startOffset": {
- "description": "Zero-based character offset into the stored capture text.",
- "maximum": 9007199254740991,
- "minimum": 0,
- "type": "integer"
- },
- "type": {
- "const": "document_text_range",
- "type": "string"
- }
- },
- "required": [
- "type",
- "startOffset",
- "endOffset"
- ],
- "type": "object"
- },
- {
- "properties": {
- "elementId": {
- "description": "BPMN XML element id within an uploaded .bpmn document.",
- "minLength": 1,
- "type": "string"
- },
- "elementType": {
- "description": "Optional BPMN element type as parsed from the XML, for example \"bpmn:UserTask\" or \"bpmn:ExclusiveGateway\".",
- "minLength": 1,
- "type": "string"
- },
- "name": {
- "description": "Optional BPMN element name as parsed from the XML. The element id is the durable key.",
- "minLength": 1,
- "type": "string"
- },
- "type": {
- "const": "bpmn_element",
- "type": "string"
- }
- },
- "required": [
- "type",
- "elementId"
- ],
- "type": "object"
- },
- {
- "properties": {
- "timestampMs": {
- "description": "Epoch-millisecond frame timestamp matching a screenshare frame filename.",
- "maximum": 9007199254740991,
- "minimum": 0,
- "type": "integer"
- },
- "type": {
- "const": "screenshare_frame",
- "type": "string"
- }
- },
- "required": [
- "type",
- "timestampMs"
- ],
- "type": "object"
- },
- {
- "properties": {
- "type": {
- "const": "manual",
- "type": "string"
- }
- },
- "required": [
- "type"
- ],
- "type": "object"
- },
- {
- "properties": {
- "reason": {
- "minLength": 1,
- "type": "string"
- },
- "type": {
- "const": "unresolved",
- "type": "string"
- }
- },
- "required": [
- "type"
- ],
- "type": "object"
- }
- ]
- },
- "resolutionStatus": {
- "description": "Resolution status for the structured source link. Legacy sources may omit this field.",
- "enum": [
- "resolved",
- "unresolved",
- "legacy",
- "manual"
- ],
- "type": "string"
- },
- "sourceConfidence": {
- "description": "Confidence in this individual source citation. \"high\" = direct quote at the locator, \"medium\" = strong nearby evidence, \"low\" = weak or inferred support.",
- "enum": [
- "low",
- "medium",
- "high"
- ],
- "type": "string"
- }
- },
- "required": [
- "attribution",
- "excerpt"
- ],
- "type": "object"
- },
- "minItems": 1,
- "type": "array"
- },
- "system": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "System, tool, or application used to perform this step. Null when the step is purely manual or is a decision/event with no associated tool. Examples: \"NetSuite\", \"Gmail\", \"Excel\", null"
- },
- "targetSteps": {
- "description": "Outgoing BPMN edges from this step. Empty array only on end events. Exclusive and inclusive gateways must have ≥2 entries with exactly one isDefault: true.",
- "items": {
- "properties": {
- "isDefault": {
- "description": "True on exactly one outgoing edge of an exclusive or inclusive gateway, marking the fallback taken when no other condition matches. False on all other edges.",
- "type": "boolean"
- },
- "label": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Human-readable label shown on the BPMN edge. For gateways, the outcome answer; for default flows, \"Otherwise\". Examples: \"Approved\", \"> $5k\", \"Otherwise\""
- },
- "stepId": {
- "description": "Id of the step this edge points to. Must match an existing step.id in the same steps array. Example: \"step-review-invoice\"",
- "minLength": 1,
- "type": "string"
- }
- },
- "required": [
- "stepId",
- "label",
- "isDefault"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "title": {
- "description": "Required node label used in lists and BPMN node labels. Structural markers use defaults such as \"Start\" and \"End\".",
- "minLength": 1,
- "type": "string"
- }
- },
- "required": [
- "id",
- "targetSteps",
- "title",
- "action",
- "role",
- "system",
- "input",
- "output",
- "exception",
- "handling",
- "assumptions",
- "openQuestions",
- "confidence",
- "nodeType",
- "nodeSubtype",
- "description",
- "rationale",
- "sources",
- "condition"
- ],
- "type": "object"
- },
- {
- "properties": {
- "action": {
- "anyOf": [
- {
- "minLength": 1,
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Verb-led one-liner summarizing the concrete action performed. Example: \"Reviews invoice line items in NetSuite against the purchase order.\""
- },
- "assumptions": {
- "anyOf": [
- {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- {
- "type": "null"
- }
- ],
- "description": "Assumptions the LLM made when extracting this step that were not directly stated in captures. Null if none. Used by verification agents to flag risky inferences. Example: [\"Invoices are reviewed within 24 hours of receipt\"]"
- },
- "condition": {
- "description": "Decision criteria evaluated at this gateway. BPMN requires this on every branching gateway. Existing rows persisted with null/empty values parse as \"unknown\" via a read-side preprocess; producers should write a real condition string going forward.",
- "minLength": 1,
- "type": "string"
- },
- "confidence": {
- "description": "Confidence in the accuracy of this step given evidence quality and completeness. \"high\" = directly stated by multiple sources, \"medium\" = stated by one source or inferred from strong signals, \"low\" = inferred with significant assumptions.",
- "enum": [
- "low",
- "medium",
- "high"
- ],
- "type": "string"
- },
- "description": {
- "description": "Full prose describing the decision logic at this gateway.",
- "minLength": 1,
- "type": "string"
- },
- "exception": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Known exceptions, errors, or failure modes observed in the captures for this step. Null when none were mentioned. Example: \"Customer disputes line items or PO number does not match\""
- },
- "extraCaptureNeeded": {
- "anyOf": [
- {
- "properties": {
- "gap": {
- "description": "Plain-language description of what about this step is unknown or under-specified, blocking automation. One short sentence. Example: \"We don't know which fields the AP analyst copies from the invoice into NetSuite.\"",
- "minLength": 1,
- "type": "string"
- },
- "id": {
- "description": "Id of the `clarity_proposal_extra_capture_request` row this slot points at. Created server-side by the agent after the LLM call; the LLM never produces this value.",
- "format": "uuid",
- "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
- "type": "string"
- },
- "proposal": {
- "anyOf": [
- {
- "minLength": 1,
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "What the new capture should include in order to resolve the gap — concrete actions, screens, or decisions the user should walk through. Optional: omit when no specific proposal can be inferred. Example: \"Walk through reviewing one invoice in NetSuite end-to-end while narrating each field you check.\""
- }
- },
- "required": [
- "id",
- "gap"
- ],
- "type": "object"
- },
- {
- "type": "null"
- }
- ]
- },
- "handling": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "How exceptions or escalations are handled — escalation path, fallback action, or retry strategy. Null when no exception or no handling described. Example: \"Escalate to AP manager via email and pause processing until resolved\""
- },
- "id": {
- "description": "Stable identifier for the step. Referenced by targetSteps[].stepId and by postprocessing agents annotating specific steps. Example: \"step-review-invoice\"",
- "minLength": 1,
- "type": "string"
- },
- "input": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Information or artifacts required to start this step. Null on start events or steps with no preconditions. Example: \"Invoice PDF and matching purchase order number\""
- },
- "nodeSubtype": {
- "description": "BPMN gateway subtype. \"exclusive\" (XOR — exactly one branch taken), \"parallel\" (AND — all branches taken), \"inclusive\" (OR — one or more branches taken).",
- "enum": [
- "exclusive",
- "parallel",
- "inclusive"
- ],
- "type": "string"
- },
- "nodeType": {
- "const": "gateway",
- "type": "string"
- },
- "openQuestions": {
- "anyOf": [
- {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- {
- "type": "null"
- }
- ],
- "description": "Specific gaps in understanding that a follow-up capture should address. Null if none. Drives the next interview or document request. Example: [\"Is there a backup approver when the AP manager is out of office?\"]"
- },
- "output": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "What this step produces or updates. Null on pure waits or events that emit nothing. Example: \"Approved invoice record in NetSuite with reviewer signature\""
- },
- "rationale": {
- "description": "Why this branching decision exists in the process.",
- "minLength": 1,
- "type": "string"
- },
- "readiness": {
- "anyOf": [
- {
- "enum": [
- "low",
- "medium",
- "high"
- ],
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Automation-readiness rating for this step. \"high\" = fully automatable today, \"medium\" = partially automatable or needs minor changes, \"low\" = blocked by manual review, judgement, or missing data."
- },
- "readinessRationale": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "One-sentence justification for the readiness rating, citing the specific signals that drove the choice. Example: \"Requires human judgement on edge cases that are not documented in the captures.\""
- },
- "role": {
- "anyOf": [
- {
- "minLength": 1,
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Performer of this step — the specific job title, team, or system. Use \"Duvo\" for automated actions and \"System\" for system-triggered steps. Examples: \"Finance Analyst\", \"Sales Operations\", \"Duvo\", \"System\""
- },
- "sources": {
- "description": "Evidence supporting the decision criteria.",
- "items": {
- "properties": {
- "attribution": {
- "description": "Human-readable source label identifying who or what the evidence comes from. Examples: \"Anna (sales interview)\", \"Onboarding SOP §3.2\", \"Slack #ops 2024-06-12\"",
- "minLength": 1,
- "type": "string"
- },
- "captureId": {
- "description": "Durable clarity_capture id for this source. Use app-owned ids from the evidence index, never sandbox file paths.",
- "minLength": 1,
- "type": "string"
- },
- "evidenceId": {
- "description": "Stable id of the evidence unit from /workspace/captures/evidence-index.json when generation used that index.",
- "minLength": 1,
- "type": "string"
- },
- "excerpt": {
- "description": "Verbatim supporting text quoted from the capture, document, or transcript. Example: \"We always wait for finance to sign off before sending the invoice.\"",
- "minLength": 1,
- "type": "string"
- },
- "locator": {
- "description": "Durable in-capture location for the excerpt. Missing means legacy free-text source; unresolved means a structured citation was attempted but could not be resolved.",
- "oneOf": [
- {
- "properties": {
- "messageIndex": {
- "description": "Zero-based index into the capture transcript message array. This is the durable key; timestampMs is only supplemental.",
- "maximum": 9007199254740991,
- "minimum": 0,
- "type": "integer"
- },
- "timestampMs": {
- "description": "Optional epoch-millisecond timestamp for the transcript message when the capture supplied one.",
- "maximum": 9007199254740991,
- "minimum": 0,
- "type": "integer"
- },
- "type": {
- "const": "transcript_message",
- "type": "string"
- }
- },
- "required": [
- "type",
- "messageIndex"
- ],
- "type": "object"
- },
- {
- "properties": {
- "endLine": {
- "description": "Optional one-based line number where the cited text ends on pageNumber.",
- "exclusiveMinimum": 0,
- "maximum": 9007199254740991,
- "type": "integer"
- },
- "endOffset": {
- "description": "Exclusive character offset into the stored capture text. Must be greater than startOffset.",
- "exclusiveMinimum": 0,
- "maximum": 9007199254740991,
- "type": "integer"
- },
- "pageNumber": {
- "description": "Optional one-based PDF page number when the stored capture has page metadata.",
- "exclusiveMinimum": 0,
- "maximum": 9007199254740991,
- "type": "integer"
- },
- "startLine": {
- "description": "Optional one-based line number where the cited text starts on pageNumber.",
- "exclusiveMinimum": 0,
- "maximum": 9007199254740991,
- "type": "integer"
- },
- "startOffset": {
- "description": "Zero-based character offset into the stored capture text.",
- "maximum": 9007199254740991,
- "minimum": 0,
- "type": "integer"
- },
- "type": {
- "const": "document_text_range",
- "type": "string"
- }
- },
- "required": [
- "type",
- "startOffset",
- "endOffset"
- ],
- "type": "object"
- },
- {
- "properties": {
- "elementId": {
- "description": "BPMN XML element id within an uploaded .bpmn document.",
- "minLength": 1,
- "type": "string"
- },
- "elementType": {
- "description": "Optional BPMN element type as parsed from the XML, for example \"bpmn:UserTask\" or \"bpmn:ExclusiveGateway\".",
- "minLength": 1,
- "type": "string"
- },
- "name": {
- "description": "Optional BPMN element name as parsed from the XML. The element id is the durable key.",
- "minLength": 1,
- "type": "string"
- },
- "type": {
- "const": "bpmn_element",
- "type": "string"
- }
- },
- "required": [
- "type",
- "elementId"
- ],
- "type": "object"
- },
- {
- "properties": {
- "timestampMs": {
- "description": "Epoch-millisecond frame timestamp matching a screenshare frame filename.",
- "maximum": 9007199254740991,
- "minimum": 0,
- "type": "integer"
- },
- "type": {
- "const": "screenshare_frame",
- "type": "string"
- }
- },
- "required": [
- "type",
- "timestampMs"
- ],
- "type": "object"
- },
- {
- "properties": {
- "type": {
- "const": "manual",
- "type": "string"
- }
- },
- "required": [
- "type"
- ],
- "type": "object"
- },
- {
- "properties": {
- "reason": {
- "minLength": 1,
- "type": "string"
- },
- "type": {
- "const": "unresolved",
- "type": "string"
- }
- },
- "required": [
- "type"
- ],
- "type": "object"
- }
- ]
- },
- "resolutionStatus": {
- "description": "Resolution status for the structured source link. Legacy sources may omit this field.",
- "enum": [
- "resolved",
- "unresolved",
- "legacy",
- "manual"
- ],
- "type": "string"
- },
- "sourceConfidence": {
- "description": "Confidence in this individual source citation. \"high\" = direct quote at the locator, \"medium\" = strong nearby evidence, \"low\" = weak or inferred support.",
- "enum": [
- "low",
- "medium",
- "high"
- ],
- "type": "string"
- }
- },
- "required": [
- "attribution",
- "excerpt"
- ],
- "type": "object"
- },
- "minItems": 1,
- "type": "array"
- },
- "system": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "System, tool, or application used to perform this step. Null when the step is purely manual or is a decision/event with no associated tool. Examples: \"NetSuite\", \"Gmail\", \"Excel\", null"
- },
- "targetSteps": {
- "description": "Outgoing BPMN edges from this step. Empty array only on end events. Exclusive and inclusive gateways must have ≥2 entries with exactly one isDefault: true.",
- "items": {
- "properties": {
- "isDefault": {
- "description": "True on exactly one outgoing edge of an exclusive or inclusive gateway, marking the fallback taken when no other condition matches. False on all other edges.",
- "type": "boolean"
- },
- "label": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Human-readable label shown on the BPMN edge. For gateways, the outcome answer; for default flows, \"Otherwise\". Examples: \"Approved\", \"> $5k\", \"Otherwise\""
- },
- "stepId": {
- "description": "Id of the step this edge points to. Must match an existing step.id in the same steps array. Example: \"step-review-invoice\"",
- "minLength": 1,
- "type": "string"
- }
- },
- "required": [
- "stepId",
- "label",
- "isDefault"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "title": {
- "description": "Required node label used in lists and BPMN node labels. Structural markers use defaults such as \"Start\" and \"End\".",
- "minLength": 1,
- "type": "string"
- }
- },
- "required": [
- "id",
- "targetSteps",
- "title",
- "action",
- "role",
- "system",
- "input",
- "output",
- "exception",
- "handling",
- "assumptions",
- "openQuestions",
- "confidence",
- "nodeType",
- "nodeSubtype",
- "description",
- "rationale",
- "sources",
- "condition"
- ],
- "type": "object"
- }
-]New value: +[
+ {
+ "properties": {
+ "action": {
+ "anyOf": [
+ {
+ "minLength": 1,
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Verb-led one-liner summarizing the concrete action performed. Example: \"Reviews invoice line items in NetSuite against the purchase order.\""
+ },
+ "assumptions": {
+ "anyOf": [
+ {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Assumptions the LLM made when extracting this step that were not directly stated in captures. Null if none. Used by verification agents to flag risky inferences. Example: [\"Invoices are reviewed within 24 hours of receipt\"]"
+ },
+ "condition": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Always null on events; included for shape compatibility across variants."
+ },
+ "confidence": {
+ "description": "Confidence in the accuracy of this step given evidence quality and completeness. \"high\" = directly stated by multiple sources, \"medium\" = stated by one source or inferred from strong signals, \"low\" = inferred with significant assumptions.",
+ "enum": [
+ "low",
+ "medium",
+ "high"
+ ],
+ "type": "string"
+ },
+ "description": {
+ "anyOf": [
+ {
+ "minLength": 1,
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Optional prose describing what happens at this event. May be null for structural markers."
+ },
+ "exception": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Known exceptions, errors, or failure modes observed in the captures for this step. Null when none were mentioned. Example: \"Customer disputes line items or PO number does not match\""
+ },
+ "extraCaptureNeeded": {
+ "anyOf": [
+ {
+ "properties": {
+ "gap": {
+ "description": "Plain-language description of what about this step is unknown or under-specified, blocking automation. One short sentence. Example: \"We don't know which fields the AP analyst copies from the invoice into NetSuite.\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "id": {
+ "description": "Id of the `clarity_proposal_extra_capture_request` row this slot points at. Created server-side by the agent after the LLM call; the LLM never produces this value.",
+ "format": "uuid",
+ "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
+ "type": "string"
+ },
+ "proposal": {
+ "anyOf": [
+ {
+ "minLength": 1,
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "What the new capture should include in order to resolve the gap — concrete actions, screens, or decisions the user should walk through. Optional: omit when no specific proposal can be inferred. Example: \"Walk through reviewing one invoice in NetSuite end-to-end while narrating each field you check.\""
+ }
+ },
+ "required": [
+ "id",
+ "gap"
+ ],
+ "type": "object"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "handling": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "How exceptions or escalations are handled — escalation path, fallback action, or retry strategy. Null when no exception or no handling described. Example: \"Escalate to AP manager via email and pause processing until resolved\""
+ },
+ "id": {
+ "description": "Stable identifier for the step. Referenced by targetSteps[].stepId and by postprocessing agents annotating specific steps. Example: \"step-review-invoice\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "input": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Information or artifacts required to start this step. Null on start events or steps with no preconditions. Example: \"Invoice PDF and matching purchase order number\""
+ },
+ "linkedAgentId": {
+ "anyOf": [
+ {
+ "format": "uuid",
+ "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Id of the Duvo Agent that performs this step. Set by a person in edit mode, never by a generating or postprocessing agent; the save route rejects an id that is not a live Agent on the process's team."
+ },
+ "nodeSubtype": {
+ "description": "BPMN event subtype. \"start\" (entry trigger), \"end\" (terminal state), \"timer\" (time-based wait), \"message\" (external communication), \"escalation\" (route to higher authority).",
+ "enum": [
+ "start",
+ "end",
+ "timer",
+ "message",
+ "escalation"
+ ],
+ "type": "string"
+ },
+ "nodeType": {
+ "const": "event",
+ "type": "string"
+ },
+ "openQuestions": {
+ "anyOf": [
+ {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Specific gaps in understanding that a follow-up capture should address. Null if none. Drives the next interview or document request. Example: [\"Is there a backup approver when the AP manager is out of office?\"]"
+ },
+ "output": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "What this step produces or updates. Null on pure waits or events that emit nothing. Example: \"Approved invoice record in NetSuite with reviewer signature\""
+ },
+ "rationale": {
+ "anyOf": [
+ {
+ "minLength": 1,
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Optional reason for the event's existence. May be null for structural markers."
+ },
+ "readiness": {
+ "anyOf": [
+ {
+ "enum": [
+ "low",
+ "medium",
+ "high"
+ ],
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Automation-readiness rating for this step. \"high\" = fully automatable today, \"medium\" = partially automatable or needs minor changes, \"low\" = blocked by manual review, judgement, or missing data."
+ },
+ "readinessRationale": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "One-sentence justification for the readiness rating, citing the specific signals that drove the choice. Example: \"Requires human judgement on edge cases that are not documented in the captures.\""
+ },
+ "role": {
+ "anyOf": [
+ {
+ "minLength": 1,
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Performer of this step — the specific job title, team, or system. Use \"Duvo\" for automated actions and \"System\" for system-triggered steps. Examples: \"Finance Analyst\", \"Sales Operations\", \"Duvo\", \"System\""
+ },
+ "sources": {
+ "description": "Evidence supporting this event. Empty array allowed (structural markers carry no evidence); non-empty values must follow the source schema.",
+ "items": {
+ "properties": {
+ "attribution": {
+ "description": "Human-readable source label identifying who or what the evidence comes from. Examples: \"Anna (sales interview)\", \"Onboarding SOP §3.2\", \"Slack #ops 2024-06-12\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "captureId": {
+ "description": "Durable clarity_capture id for this source. Use app-owned ids from the evidence index, never sandbox file paths.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "evidenceId": {
+ "description": "Stable id of the evidence unit from /workspace/captures/evidence-index.json when generation used that index.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "excerpt": {
+ "description": "Verbatim supporting text quoted from the capture, document, or transcript. Example: \"We always wait for finance to sign off before sending the invoice.\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "locator": {
+ "description": "Durable in-capture location for the excerpt. Missing means legacy free-text source; unresolved means a structured citation was attempted but could not be resolved.",
+ "oneOf": [
+ {
+ "properties": {
+ "messageIndex": {
+ "description": "Zero-based index into the capture transcript message array. This is the durable key; timestampMs is only supplemental.",
+ "maximum": 9007199254740991,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "timestampMs": {
+ "description": "Optional epoch-millisecond timestamp for the transcript message when the capture supplied one.",
+ "maximum": 9007199254740991,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "type": {
+ "const": "transcript_message",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "messageIndex"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "endLine": {
+ "description": "Optional one-based line number where the cited text ends on pageNumber.",
+ "exclusiveMinimum": 0,
+ "maximum": 9007199254740991,
+ "type": "integer"
+ },
+ "endOffset": {
+ "description": "Exclusive character offset into the stored capture text. Must be greater than startOffset.",
+ "exclusiveMinimum": 0,
+ "maximum": 9007199254740991,
+ "type": "integer"
+ },
+ "pageNumber": {
+ "description": "Optional one-based PDF page number when the stored capture has page metadata.",
+ "exclusiveMinimum": 0,
+ "maximum": 9007199254740991,
+ "type": "integer"
+ },
+ "startLine": {
+ "description": "Optional one-based line number where the cited text starts on pageNumber.",
+ "exclusiveMinimum": 0,
+ "maximum": 9007199254740991,
+ "type": "integer"
+ },
+ "startOffset": {
+ "description": "Zero-based character offset into the stored capture text.",
+ "maximum": 9007199254740991,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "type": {
+ "const": "document_text_range",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "startOffset",
+ "endOffset"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "elementId": {
+ "description": "BPMN XML element id within an uploaded .bpmn document.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "elementType": {
+ "description": "Optional BPMN element type as parsed from the XML, for example \"bpmn:UserTask\" or \"bpmn:ExclusiveGateway\".",
+ "minLength": 1,
+ "type": "string"
+ },
+ "name": {
+ "description": "Optional BPMN element name as parsed from the XML. The element id is the durable key.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "type": {
+ "const": "bpmn_element",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "elementId"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "timestampMs": {
+ "description": "Epoch-millisecond frame timestamp matching a screenshare frame filename.",
+ "maximum": 9007199254740991,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "type": {
+ "const": "screenshare_frame",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "timestampMs"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "type": {
+ "const": "manual",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "reason": {
+ "minLength": 1,
+ "type": "string"
+ },
+ "type": {
+ "const": "unresolved",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "resolutionStatus": {
+ "description": "Resolution status for the structured source link. Legacy sources may omit this field.",
+ "enum": [
+ "resolved",
+ "unresolved",
+ "legacy",
+ "manual"
+ ],
+ "type": "string"
+ },
+ "sourceConfidence": {
+ "description": "Confidence in this individual source citation. \"high\" = direct quote at the locator, \"medium\" = strong nearby evidence, \"low\" = weak or inferred support.",
+ "enum": [
+ "low",
+ "medium",
+ "high"
+ ],
+ "type": "string"
+ }
+ },
+ "required": [
+ "attribution",
+ "excerpt"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "system": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "System, tool, or application used to perform this step. Null when the step is purely manual or is a decision/event with no associated tool. Examples: \"NetSuite\", \"Gmail\", \"Excel\", null"
+ },
+ "targetSteps": {
+ "description": "Outgoing BPMN edges from this step. Empty array only on end events. Exclusive and inclusive gateways must have ≥2 entries with exactly one isDefault: true.",
+ "items": {
+ "properties": {
+ "isDefault": {
+ "description": "True on exactly one outgoing edge of an exclusive or inclusive gateway, marking the fallback taken when no other condition matches. False on all other edges.",
+ "type": "boolean"
+ },
+ "label": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Human-readable label shown on the BPMN edge. For gateways, the outcome answer; for default flows, \"Otherwise\". Examples: \"Approved\", \"> $5k\", \"Otherwise\""
+ },
+ "stepId": {
+ "description": "Id of the step this edge points to. Must match an existing step.id in the same steps array. Example: \"step-review-invoice\"",
+ "minLength": 1,
+ "type": "string"
+ }
+ },
+ "required": [
+ "stepId",
+ "label",
+ "isDefault"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "title": {
+ "description": "Required node label used in lists and BPMN node labels. Structural markers use defaults such as \"Start\" and \"End\".",
+ "minLength": 1,
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "targetSteps",
+ "title",
+ "action",
+ "role",
+ "system",
+ "input",
+ "output",
+ "exception",
+ "handling",
+ "assumptions",
+ "openQuestions",
+ "confidence",
+ "nodeType",
+ "nodeSubtype",
+ "description",
+ "rationale",
+ "sources",
+ "condition"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "action": {
+ "anyOf": [
+ {
+ "minLength": 1,
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Verb-led one-liner summarizing the concrete action performed. Example: \"Reviews invoice line items in NetSuite against the purchase order.\""
+ },
+ "assumptions": {
+ "anyOf": [
+ {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Assumptions the LLM made when extracting this step that were not directly stated in captures. Null if none. Used by verification agents to flag risky inferences. Example: [\"Invoices are reviewed within 24 hours of receipt\"]"
+ },
+ "condition": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Optional precondition that gates this task. Null when the task is unconditional. Example: \"Only when invoice total exceeds $10,000\""
+ },
+ "confidence": {
+ "description": "Confidence in the accuracy of this step given evidence quality and completeness. \"high\" = directly stated by multiple sources, \"medium\" = stated by one source or inferred from strong signals, \"low\" = inferred with significant assumptions.",
+ "enum": [
+ "low",
+ "medium",
+ "high"
+ ],
+ "type": "string"
+ },
+ "description": {
+ "description": "Full prose paragraph describing what happens in this step in natural language. Used for documentation reconstruction. Example: \"Finance reviews the invoice in NetSuite, checking line item accuracy and matching against the purchase order before flagging for approval.\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "exception": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Known exceptions, errors, or failure modes observed in the captures for this step. Null when none were mentioned. Example: \"Customer disputes line items or PO number does not match\""
+ },
+ "extraCaptureNeeded": {
+ "anyOf": [
+ {
+ "properties": {
+ "gap": {
+ "description": "Plain-language description of what about this step is unknown or under-specified, blocking automation. One short sentence. Example: \"We don't know which fields the AP analyst copies from the invoice into NetSuite.\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "id": {
+ "description": "Id of the `clarity_proposal_extra_capture_request` row this slot points at. Created server-side by the agent after the LLM call; the LLM never produces this value.",
+ "format": "uuid",
+ "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
+ "type": "string"
+ },
+ "proposal": {
+ "anyOf": [
+ {
+ "minLength": 1,
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "What the new capture should include in order to resolve the gap — concrete actions, screens, or decisions the user should walk through. Optional: omit when no specific proposal can be inferred. Example: \"Walk through reviewing one invoice in NetSuite end-to-end while narrating each field you check.\""
+ }
+ },
+ "required": [
+ "id",
+ "gap"
+ ],
+ "type": "object"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "handling": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "How exceptions or escalations are handled — escalation path, fallback action, or retry strategy. Null when no exception or no handling described. Example: \"Escalate to AP manager via email and pause processing until resolved\""
+ },
+ "id": {
+ "description": "Stable identifier for the step. Referenced by targetSteps[].stepId and by postprocessing agents annotating specific steps. Example: \"step-review-invoice\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "input": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Information or artifacts required to start this step. Null on start events or steps with no preconditions. Example: \"Invoice PDF and matching purchase order number\""
+ },
+ "linkedAgentId": {
+ "anyOf": [
+ {
+ "format": "uuid",
+ "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Id of the Duvo Agent that performs this step. Set by a person in edit mode, never by a generating or postprocessing agent; the save route rejects an id that is not a live Agent on the process's team."
+ },
+ "nodeSubtype": {
+ "description": "BPMN task subtype. \"user\" (human work), \"service\" (automated/API call), \"send\"/\"receive\" (messaging), \"manual\" (offline physical work), \"businessRule\" (rule engine), \"script\" (code execution).",
+ "enum": [
+ "user",
+ "service",
+ "send",
+ "receive",
+ "manual",
+ "businessRule",
+ "script"
+ ],
+ "type": "string"
+ },
+ "nodeType": {
+ "const": "task",
+ "type": "string"
+ },
+ "openQuestions": {
+ "anyOf": [
+ {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Specific gaps in understanding that a follow-up capture should address. Null if none. Drives the next interview or document request. Example: [\"Is there a backup approver when the AP manager is out of office?\"]"
+ },
+ "output": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "What this step produces or updates. Null on pure waits or events that emit nothing. Example: \"Approved invoice record in NetSuite with reviewer signature\""
+ },
+ "rationale": {
+ "description": "Why this step exists in the process — its purpose or business reason. Used by downstream agents to assess whether the step is essential or removable. Example: \"Catches mispriced line items before they reach the customer and prevents downstream credit notes.\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "readiness": {
+ "anyOf": [
+ {
+ "enum": [
+ "low",
+ "medium",
+ "high"
+ ],
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Automation-readiness rating for this step. \"high\" = fully automatable today, \"medium\" = partially automatable or needs minor changes, \"low\" = blocked by manual review, judgement, or missing data."
+ },
+ "readinessRationale": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "One-sentence justification for the readiness rating, citing the specific signals that drove the choice. Example: \"Requires human judgement on edge cases that are not documented in the captures.\""
+ },
+ "role": {
+ "anyOf": [
+ {
+ "minLength": 1,
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Performer of this step — the specific job title, team, or system. Use \"Duvo\" for automated actions and \"System\" for system-triggered steps. Examples: \"Finance Analyst\", \"Sales Operations\", \"Duvo\", \"System\""
+ },
+ "sources": {
+ "description": "Evidence supporting this step's existence and details. At least one source is required — every step must trace back to something in the captures.",
+ "items": {
+ "properties": {
+ "attribution": {
+ "description": "Human-readable source label identifying who or what the evidence comes from. Examples: \"Anna (sales interview)\", \"Onboarding SOP §3.2\", \"Slack #ops 2024-06-12\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "captureId": {
+ "description": "Durable clarity_capture id for this source. Use app-owned ids from the evidence index, never sandbox file paths.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "evidenceId": {
+ "description": "Stable id of the evidence unit from /workspace/captures/evidence-index.json when generation used that index.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "excerpt": {
+ "description": "Verbatim supporting text quoted from the capture, document, or transcript. Example: \"We always wait for finance to sign off before sending the invoice.\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "locator": {
+ "description": "Durable in-capture location for the excerpt. Missing means legacy free-text source; unresolved means a structured citation was attempted but could not be resolved.",
+ "oneOf": [
+ {
+ "properties": {
+ "messageIndex": {
+ "description": "Zero-based index into the capture transcript message array. This is the durable key; timestampMs is only supplemental.",
+ "maximum": 9007199254740991,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "timestampMs": {
+ "description": "Optional epoch-millisecond timestamp for the transcript message when the capture supplied one.",
+ "maximum": 9007199254740991,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "type": {
+ "const": "transcript_message",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "messageIndex"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "endLine": {
+ "description": "Optional one-based line number where the cited text ends on pageNumber.",
+ "exclusiveMinimum": 0,
+ "maximum": 9007199254740991,
+ "type": "integer"
+ },
+ "endOffset": {
+ "description": "Exclusive character offset into the stored capture text. Must be greater than startOffset.",
+ "exclusiveMinimum": 0,
+ "maximum": 9007199254740991,
+ "type": "integer"
+ },
+ "pageNumber": {
+ "description": "Optional one-based PDF page number when the stored capture has page metadata.",
+ "exclusiveMinimum": 0,
+ "maximum": 9007199254740991,
+ "type": "integer"
+ },
+ "startLine": {
+ "description": "Optional one-based line number where the cited text starts on pageNumber.",
+ "exclusiveMinimum": 0,
+ "maximum": 9007199254740991,
+ "type": "integer"
+ },
+ "startOffset": {
+ "description": "Zero-based character offset into the stored capture text.",
+ "maximum": 9007199254740991,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "type": {
+ "const": "document_text_range",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "startOffset",
+ "endOffset"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "elementId": {
+ "description": "BPMN XML element id within an uploaded .bpmn document.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "elementType": {
+ "description": "Optional BPMN element type as parsed from the XML, for example \"bpmn:UserTask\" or \"bpmn:ExclusiveGateway\".",
+ "minLength": 1,
+ "type": "string"
+ },
+ "name": {
+ "description": "Optional BPMN element name as parsed from the XML. The element id is the durable key.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "type": {
+ "const": "bpmn_element",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "elementId"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "timestampMs": {
+ "description": "Epoch-millisecond frame timestamp matching a screenshare frame filename.",
+ "maximum": 9007199254740991,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "type": {
+ "const": "screenshare_frame",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "timestampMs"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "type": {
+ "const": "manual",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "reason": {
+ "minLength": 1,
+ "type": "string"
+ },
+ "type": {
+ "const": "unresolved",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "resolutionStatus": {
+ "description": "Resolution status for the structured source link. Legacy sources may omit this field.",
+ "enum": [
+ "resolved",
+ "unresolved",
+ "legacy",
+ "manual"
+ ],
+ "type": "string"
+ },
+ "sourceConfidence": {
+ "description": "Confidence in this individual source citation. \"high\" = direct quote at the locator, \"medium\" = strong nearby evidence, \"low\" = weak or inferred support.",
+ "enum": [
+ "low",
+ "medium",
+ "high"
+ ],
+ "type": "string"
+ }
+ },
+ "required": [
+ "attribution",
+ "excerpt"
+ ],
+ "type": "object"
+ },
+ "minItems": 1,
+ "type": "array"
+ },
+ "system": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "System, tool, or application used to perform this step. Null when the step is purely manual or is a decision/event with no associated tool. Examples: \"NetSuite\", \"Gmail\", \"Excel\", null"
+ },
+ "targetSteps": {
+ "description": "Outgoing BPMN edges from this step. Empty array only on end events. Exclusive and inclusive gateways must have ≥2 entries with exactly one isDefault: true.",
+ "items": {
+ "properties": {
+ "isDefault": {
+ "description": "True on exactly one outgoing edge of an exclusive or inclusive gateway, marking the fallback taken when no other condition matches. False on all other edges.",
+ "type": "boolean"
+ },
+ "label": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Human-readable label shown on the BPMN edge. For gateways, the outcome answer; for default flows, \"Otherwise\". Examples: \"Approved\", \"> $5k\", \"Otherwise\""
+ },
+ "stepId": {
+ "description": "Id of the step this edge points to. Must match an existing step.id in the same steps array. Example: \"step-review-invoice\"",
+ "minLength": 1,
+ "type": "string"
+ }
+ },
+ "required": [
+ "stepId",
+ "label",
+ "isDefault"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "title": {
+ "description": "Required node label used in lists and BPMN node labels. Structural markers use defaults such as \"Start\" and \"End\".",
+ "minLength": 1,
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "targetSteps",
+ "title",
+ "action",
+ "role",
+ "system",
+ "input",
+ "output",
+ "exception",
+ "handling",
+ "assumptions",
+ "openQuestions",
+ "confidence",
+ "nodeType",
+ "nodeSubtype",
+ "description",
+ "rationale",
+ "sources",
+ "condition"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "action": {
+ "anyOf": [
+ {
+ "minLength": 1,
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Verb-led one-liner summarizing the concrete action performed. Example: \"Reviews invoice line items in NetSuite against the purchase order.\""
+ },
+ "assumptions": {
+ "anyOf": [
+ {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Assumptions the LLM made when extracting this step that were not directly stated in captures. Null if none. Used by verification agents to flag risky inferences. Example: [\"Invoices are reviewed within 24 hours of receipt\"]"
+ },
+ "condition": {
+ "description": "Decision criteria evaluated at this gateway. BPMN requires this on every branching gateway. Existing rows persisted with null/empty values parse as \"unknown\" via a read-side preprocess; producers should write a real condition string going forward.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "confidence": {
+ "description": "Confidence in the accuracy of this step given evidence quality and completeness. \"high\" = directly stated by multiple sources, \"medium\" = stated by one source or inferred from strong signals, \"low\" = inferred with significant assumptions.",
+ "enum": [
+ "low",
+ "medium",
+ "high"
+ ],
+ "type": "string"
+ },
+ "description": {
+ "description": "Full prose describing the decision logic at this gateway.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "exception": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Known exceptions, errors, or failure modes observed in the captures for this step. Null when none were mentioned. Example: \"Customer disputes line items or PO number does not match\""
+ },
+ "extraCaptureNeeded": {
+ "anyOf": [
+ {
+ "properties": {
+ "gap": {
+ "description": "Plain-language description of what about this step is unknown or under-specified, blocking automation. One short sentence. Example: \"We don't know which fields the AP analyst copies from the invoice into NetSuite.\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "id": {
+ "description": "Id of the `clarity_proposal_extra_capture_request` row this slot points at. Created server-side by the agent after the LLM call; the LLM never produces this value.",
+ "format": "uuid",
+ "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
+ "type": "string"
+ },
+ "proposal": {
+ "anyOf": [
+ {
+ "minLength": 1,
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "What the new capture should include in order to resolve the gap — concrete actions, screens, or decisions the user should walk through. Optional: omit when no specific proposal can be inferred. Example: \"Walk through reviewing one invoice in NetSuite end-to-end while narrating each field you check.\""
+ }
+ },
+ "required": [
+ "id",
+ "gap"
+ ],
+ "type": "object"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
+ "handling": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "How exceptions or escalations are handled — escalation path, fallback action, or retry strategy. Null when no exception or no handling described. Example: \"Escalate to AP manager via email and pause processing until resolved\""
+ },
+ "id": {
+ "description": "Stable identifier for the step. Referenced by targetSteps[].stepId and by postprocessing agents annotating specific steps. Example: \"step-review-invoice\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "input": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Information or artifacts required to start this step. Null on start events or steps with no preconditions. Example: \"Invoice PDF and matching purchase order number\""
+ },
+ "linkedAgentId": {
+ "anyOf": [
+ {
+ "format": "uuid",
+ "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Id of the Duvo Agent that performs this step. Set by a person in edit mode, never by a generating or postprocessing agent; the save route rejects an id that is not a live Agent on the process's team."
+ },
+ "nodeSubtype": {
+ "description": "BPMN gateway subtype. \"exclusive\" (XOR — exactly one branch taken), \"parallel\" (AND — all branches taken), \"inclusive\" (OR — one or more branches taken).",
+ "enum": [
+ "exclusive",
+ "parallel",
+ "inclusive"
+ ],
+ "type": "string"
+ },
+ "nodeType": {
+ "const": "gateway",
+ "type": "string"
+ },
+ "openQuestions": {
+ "anyOf": [
+ {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Specific gaps in understanding that a follow-up capture should address. Null if none. Drives the next interview or document request. Example: [\"Is there a backup approver when the AP manager is out of office?\"]"
+ },
+ "output": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "What this step produces or updates. Null on pure waits or events that emit nothing. Example: \"Approved invoice record in NetSuite with reviewer signature\""
+ },
+ "rationale": {
+ "description": "Why this branching decision exists in the process.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "readiness": {
+ "anyOf": [
+ {
+ "enum": [
+ "low",
+ "medium",
+ "high"
+ ],
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Automation-readiness rating for this step. \"high\" = fully automatable today, \"medium\" = partially automatable or needs minor changes, \"low\" = blocked by manual review, judgement, or missing data."
+ },
+ "readinessRationale": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "One-sentence justification for the readiness rating, citing the specific signals that drove the choice. Example: \"Requires human judgement on edge cases that are not documented in the captures.\""
+ },
+ "role": {
+ "anyOf": [
+ {
+ "minLength": 1,
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Performer of this step — the specific job title, team, or system. Use \"Duvo\" for automated actions and \"System\" for system-triggered steps. Examples: \"Finance Analyst\", \"Sales Operations\", \"Duvo\", \"System\""
+ },
+ "sources": {
+ "description": "Evidence supporting the decision criteria.",
+ "items": {
+ "properties": {
+ "attribution": {
+ "description": "Human-readable source label identifying who or what the evidence comes from. Examples: \"Anna (sales interview)\", \"Onboarding SOP §3.2\", \"Slack #ops 2024-06-12\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "captureId": {
+ "description": "Durable clarity_capture id for this source. Use app-owned ids from the evidence index, never sandbox file paths.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "evidenceId": {
+ "description": "Stable id of the evidence unit from /workspace/captures/evidence-index.json when generation used that index.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "excerpt": {
+ "description": "Verbatim supporting text quoted from the capture, document, or transcript. Example: \"We always wait for finance to sign off before sending the invoice.\"",
+ "minLength": 1,
+ "type": "string"
+ },
+ "locator": {
+ "description": "Durable in-capture location for the excerpt. Missing means legacy free-text source; unresolved means a structured citation was attempted but could not be resolved.",
+ "oneOf": [
+ {
+ "properties": {
+ "messageIndex": {
+ "description": "Zero-based index into the capture transcript message array. This is the durable key; timestampMs is only supplemental.",
+ "maximum": 9007199254740991,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "timestampMs": {
+ "description": "Optional epoch-millisecond timestamp for the transcript message when the capture supplied one.",
+ "maximum": 9007199254740991,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "type": {
+ "const": "transcript_message",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "messageIndex"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "endLine": {
+ "description": "Optional one-based line number where the cited text ends on pageNumber.",
+ "exclusiveMinimum": 0,
+ "maximum": 9007199254740991,
+ "type": "integer"
+ },
+ "endOffset": {
+ "description": "Exclusive character offset into the stored capture text. Must be greater than startOffset.",
+ "exclusiveMinimum": 0,
+ "maximum": 9007199254740991,
+ "type": "integer"
+ },
+ "pageNumber": {
+ "description": "Optional one-based PDF page number when the stored capture has page metadata.",
+ "exclusiveMinimum": 0,
+ "maximum": 9007199254740991,
+ "type": "integer"
+ },
+ "startLine": {
+ "description": "Optional one-based line number where the cited text starts on pageNumber.",
+ "exclusiveMinimum": 0,
+ "maximum": 9007199254740991,
+ "type": "integer"
+ },
+ "startOffset": {
+ "description": "Zero-based character offset into the stored capture text.",
+ "maximum": 9007199254740991,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "type": {
+ "const": "document_text_range",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "startOffset",
+ "endOffset"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "elementId": {
+ "description": "BPMN XML element id within an uploaded .bpmn document.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "elementType": {
+ "description": "Optional BPMN element type as parsed from the XML, for example \"bpmn:UserTask\" or \"bpmn:ExclusiveGateway\".",
+ "minLength": 1,
+ "type": "string"
+ },
+ "name": {
+ "description": "Optional BPMN element name as parsed from the XML. The element id is the durable key.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "type": {
+ "const": "bpmn_element",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "elementId"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "timestampMs": {
+ "description": "Epoch-millisecond frame timestamp matching a screenshare frame filename.",
+ "maximum": 9007199254740991,
+ "minimum": 0,
+ "type": "integer"
+ },
+ "type": {
+ "const": "screenshare_frame",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "timestampMs"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "type": {
+ "const": "manual",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "type": "object"
+ },
+ {
+ "properties": {
+ "reason": {
+ "minLength": 1,
+ "type": "string"
+ },
+ "type": {
+ "const": "unresolved",
+ "type": "string"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "resolutionStatus": {
+ "description": "Resolution status for the structured source link. Legacy sources may omit this field.",
+ "enum": [
+ "resolved",
+ "unresolved",
+ "legacy",
+ "manual"
+ ],
+ "type": "string"
+ },
+ "sourceConfidence": {
+ "description": "Confidence in this individual source citation. \"high\" = direct quote at the locator, \"medium\" = strong nearby evidence, \"low\" = weak or inferred support.",
+ "enum": [
+ "low",
+ "medium",
+ "high"
+ ],
+ "type": "string"
+ }
+ },
+ "required": [
+ "attribution",
+ "excerpt"
+ ],
+ "type": "object"
+ },
+ "minItems": 1,
+ "type": "array"
+ },
+ "system": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "System, tool, or application used to perform this step. Null when the step is purely manual or is a decision/event with no associated tool. Examples: \"NetSuite\", \"Gmail\", \"Excel\", null"
+ },
+ "targetSteps": {
+ "description": "Outgoing BPMN edges from this step. Empty array only on end events. Exclusive and inclusive gateways must have ≥2 entries with exactly one isDefault: true.",
+ "items": {
+ "properties": {
+ "isDefault": {
+ "description": "True on exactly one outgoing edge of an exclusive or inclusive gateway, marking the fallback taken when no other condition matches. False on all other edges.",
+ "type": "boolean"
+ },
+ "label": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Human-readable label shown on the BPMN edge. For gateways, the outcome answer; for default flows, \"Otherwise\". Examples: \"Approved\", \"> $5k\", \"Otherwise\""
+ },
+ "stepId": {
+ "description": "Id of the step this edge points to. Must match an existing step.id in the same steps array. Example: \"step-review-invoice\"",
+ "minLength": 1,
+ "type": "string"
+ }
+ },
+ "required": [
+ "stepId",
+ "label",
+ "isDefault"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "title": {
+ "description": "Required node label used in lists and BPMN node labels. Structural markers use defaults such as \"Start\" and \"End\".",
+ "minLength": 1,
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "targetSteps",
+ "title",
+ "action",
+ "role",
+ "system",
+ "input",
+ "output",
+ "exception",
+ "handling",
+ "assumptions",
+ "openQuestions",
+ "confidence",
+ "nodeType",
+ "nodeSubtype",
+ "description",
+ "rationale",
+ "sources",
+ "condition"
+ ],
+ "type": "object"
+ }
+]