Skip to content

Add manual/auto trigger and rework event and action transitions#412

Merged
jakub-id merged 1 commit intomainfrom
state-model-schema-update
Feb 20, 2026
Merged

Add manual/auto trigger and rework event and action transitions#412
jakub-id merged 1 commit intomainfrom
state-model-schema-update

Conversation

@jakub-id
Copy link
Contributor

No description provided.

Copilot AI review requested due to automatic review settings February 19, 2026 14:34
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors the state model schema to improve the clarity and expressiveness of action and event transitions. It changes the transition structure from arrays of possible target states to a more explicit format that distinguishes between success and failure outcomes for actions, and simplifies events to have a single transition target.

Changes:

  • Modified state model JSON schema to change Action transitions from an array to an object with success and failure properties, and added a trigger field
  • Modified state model JSON schema to change Event transitions from a plural array field to a singular string field
  • Updated the returnables YAML data file to conform to the new schema structure

Reviewed changes

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

File Description
misc/state-model.json Updates Action schema to use object-based transitions with success/failure outcomes and adds trigger field; changes Event schema to use singular transition string
misc/returnables.yaml Converts all action transitions from array format to object format with success keys; converts all event transitions from plural transitions arrays to singular transition strings
Comments suppressed due to low confidence (1)

misc/state-model.json:177

  • The schema changes in this file will break compatibility with the existing codebase. The OpenAPI schema file broker/oapi/open-api.yaml (lines 611-641) defines ModelAction and ModelEvent with the old array-based transitions structure, which is used to generate Go types in broker/patron_request/proapi/pr-openapi_gen.go. Additionally, the embedded JSON state model file broker/patron_request/service/statemodels/returnables.json still uses the old schema format.

These files need to be updated in the same PR to maintain consistency:

  1. broker/oapi/open-api.yaml - Update ModelAction and ModelEvent schemas to match the new structure
  2. broker/patron_request/service/statemodels/returnables.json - Regenerate from the updated YAML to use the new schema

Without these updates, the code will fail at runtime when trying to unmarshal the state model JSON because the Go struct types won't match the actual JSON structure.

        "Action": {
            "type": "object",
            "additionalProperties": false,
            "description": "Declares an action available while in this state.",
            "properties": {
                "name": {
                    "type": "string",
                    "description": "Name of the action"
                },
                "desc": {
                    "type": "string",
                    "description": "Description of the action"
                },
                "trigger": {
                    "type": "string",
                    "description": "Trigger for the action",
                    "enum": [
                        "auto",
                        "manual"
                    ],
                    "default": "manual"
                },
                "transitions": {
                    "type": "object",
                    "description": "Action outcome to state transition mapping. When no transition is defined, the action is considered to be non-state-changing.",
                    "additionalProperties": false,
                    "properties": {
                        "success": {
                            "type": "string",
                            "description": "Target state when the action succeeds."
                        },
                        "failure": {
                            "type": "string",
                            "description": "Target state when the action fails."
                        }
                    }
                }
            },
            "required": [
                "name"
            ],
            "title": "Action"
        },
        "Event": {
            "type": "object",
            "additionalProperties": false,
            "description": "Declares an event considered for transition while in this state.",
            "properties": {
                "name": {
                    "type": "string",
                    "description": "Name of the event"
                },
                "desc": {
                    "type": "string",
                    "description": "Description of the event"
                },
                "transition": {
                    "type": "string",
                    "description": "State transition after event has occurred. When no transition is defined, the event is considered to be non-state-changing."
                }
            },
            "required": [
                "name"
            ],
            "title": "Event"
        }

Comment on lines +131 to +132
],
"default": "manual"
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The trigger field in the Action schema has a default value of "manual", but JSON Schema's default keyword is only advisory for documentation purposes - it doesn't actually set default values during validation or parsing.

If you want actions to have a default trigger of "manual", you'll need to handle this in the application code that reads the state model. Alternatively, if the trigger field should be required, add it to the required array on line 150.

Suggested change
],
"default": "manual"
]

Copilot uses AI. Check for mistakes.
Comment on lines 13 to 300
@@ -21,7 +22,8 @@ states:
actions:
- name: send-request
desc: Send ISO18626 request to the supplier or broker
transitions: [SENT]
transitions:
success: SENT

- name: SENT
display: Sent
@@ -30,19 +32,19 @@ states:
events:
- name: expect-to-supply
desc: Supplier indicates an intention to supply (ISO18626 ExpectToSupply)
transitions: [SUPPLIER_LOCATED]
transition: SUPPLIER_LOCATED
- name: will-supply
desc: Supplier will supply without conditions (ISO18626 WillSupply)
transitions: [WILL_SUPPLY]
transition: WILL_SUPPLY
- name: will-supply-conditional
desc: Supplier will supply with conditions (ISO18626 WillSupply with conditions)
transitions: [CONDITION_PENDING]
transition: CONDITION_PENDING
- name: loaned
desc: Supplier shipped the item (ISO18626 Loaned)
transitions: [SHIPPED]
transition: SHIPPED
- name: unfilled
desc: Supplier cannot supply (ISO18626 Unfilled)
transitions: [UNFILLED]
transition: UNFILLED

- name: SUPPLIER_LOCATED
display: Supplier Located
@@ -51,17 +53,18 @@ states:
actions:
- name: cancel-request
desc: Send ISO18626 Cancel request to supplier
transitions: [CANCEL_PENDING]
transitions:
success: CANCEL_PENDING
events:
- name: will-supply
desc: Supplier will supply without conditions (ISO18626 WillSupply)
transitions: [WILL_SUPPLY]
transition: WILL_SUPPLY
- name: will-supply-conditional
desc: Supplier will supply with conditions (ISO18626 WillSupply with conditions)
transitions: [CONDITION_PENDING]
transition: CONDITION_PENDING
- name: unfilled
desc: Supplier cannot supply (ISO18626 Unfilled)
transitions: [UNFILLED]
transition: UNFILLED

- name: CONDITION_PENDING
display: Condition Pending
@@ -70,10 +73,12 @@ states:
actions:
- name: accept-condition
desc: Accept supplier conditions (ISO18626 Notification)
transitions: [WILL_SUPPLY]
transitions:
success: WILL_SUPPLY
- name: reject-condition
desc: Reject supplier conditions (ISO18626 Cancel)
transitions: [CANCEL_PENDING]
transitions:
success: CANCEL_PENDING

- name: WILL_SUPPLY
display: Will Supply
@@ -82,14 +87,15 @@ states:
actions:
- name: cancel-request
desc: Send ISO18626 Cancel to supplier
transitions: [CANCEL_PENDING]
transitions:
success: CANCEL_PENDING
events:
- name: loaned
desc: Supplier shipped the item (ISO18626 Loaned)
transitions: [SHIPPED]
transition: SHIPPED
- name: unfilled
desc: Supplier cannot supply (ISO18626 Unfilled)
transitions: [UNFILLED]
transition: UNFILLED

- name: SHIPPED
display: Shipped
@@ -98,7 +104,8 @@ states:
actions:
- name: receive
desc: Receive and accept item in local ILS (via NCIP AcceptItem if enabled); send ISO18626 Received
transitions: [RECEIVED]
transitions:
success: RECEIVED

- name: RECEIVED
display: Received
@@ -107,7 +114,8 @@ states:
actions:
- name: check-out
desc: Check out item to patron (NCIP CheckOutItem)
transitions: [CHECKED_OUT]
transitions:
success: CHECKED_OUT

- name: CHECKED_OUT
display: Checked Out
@@ -116,7 +124,8 @@ states:
actions:
- name: check-in
desc: Check the item back-in (NCIP CheckInItem)
transitions: [CHECKED_IN]
transitions:
success: CHECKED_IN

- name: CHECKED_IN
display: Checked In
@@ -125,7 +134,8 @@ states:
actions:
- name: ship-return
desc: Send ISO18626 ShippedReturn and delete the temporary item (NCIP DeleteItem)
transitions: [SHIPPED_RETURNED]
transitions:
success: SHIPPED_RETURNED

- name: SHIPPED_RETURNED
display: Shipped Returned
@@ -134,7 +144,7 @@ states:
events:
- name: completed
desc: Supplier/broker signals loan/copy completion
transitions: [COMPLETED]
transition: COMPLETED

- name: CANCEL_PENDING
display: Cancel Pending
@@ -143,7 +153,7 @@ states:
events:
- name: cancel-accepted
desc: Supplier accepts cancellation
transitions: [CANCELLED]
transition: CANCELLED

- name: COMPLETED
display: Completed
@@ -171,7 +181,8 @@ states:
actions:
- name: validate
desc: Validate the request, e.g institutional patron via NCIP LookupUser, if enabled
transitions: [VALIDATED]
transitions:
success: VALIDATED

- name: VALIDATED
display: Validated
@@ -180,17 +191,20 @@ states:
actions:
- name: will-supply
desc: Indicate supplier will supply and send ISO18626 WillSupply
transitions: [WILL_SUPPLY]
transitions:
success: WILL_SUPPLY
- name: cannot-supply
desc: Indicate cannot supply and send ISO18626 Unfilled
transitions: [UNFILLED]
transitions:
success: UNFILLED
- name: add-condition
desc: Indicate will supply with conditions and send ISO18626 WillSupply
transitions: [CONDITION_PENDING]
transitions:
success: CONDITION_PENDING
events:
- name: cancel-request
desc: Requester sent ISO18626 Cancel
transitions: [CANCEL_REQUESTED]
transition: CANCEL_REQUESTED

- name: WILL_SUPPLY
display: Will Supply
@@ -199,17 +213,20 @@ states:
actions:
- name: add-condition
desc: Add conditions and notify requester
transitions: [CONDITION_PENDING]
transitions:
success: CONDITION_PENDING
- name: ship
desc: Mark shipped; send ISO Loaned; NCIP CheckOutItem
transitions: [SHIPPED]
transitions:
success: SHIPPED
- name: cannot-supply
desc: Indicate cannot supply
transitions: [UNFILLED]
transitions:
success: UNFILLED
events:
- name: cancel-request
desc: Requester sends ISO Cancel
transitions: [CANCEL_REQUESTED]
transition: CANCEL_REQUESTED

- name: CONDITION_PENDING
display: Condition Pending
@@ -218,17 +235,18 @@ states:
actions:
- name: cannot-supply
desc: Indicate cannot supply
transitions: [UNFILLED]
transitions:
success: UNFILLED
events:
- name: conditions-accepted
desc: Requester accepts conditions
transitions: [CONDITION_ACCEPTED]
transition: CONDITION_ACCEPTED
- name: condition-rejected
desc: Requester rejects conditions (auto-responder may mark unfilled)
transitions: [UNFILLED]
transition: UNFILLED
- name: cancel-request
desc: Requester sends ISO Cancel
transitions: [CANCEL_REQUESTED]
transition: CANCEL_REQUESTED

- name: CONDITION_ACCEPTED
display: Condition Accepted
@@ -237,14 +255,16 @@ states:
actions:
- name: ship
desc: Mark shipped; send ISO Loaned; NCIP CheckOutItem
transitions: [SHIPPED]
transitions:
success: SHIPPED
- name: cannot-supply
desc: Indicate cannot supply
transitions: [UNFILLED]
transitions:
success: UNFILLED
events:
- name: cancel-request
desc: Requester sends ISO Cancel
transitions: [CANCEL_REQUESTED]
transition: CANCEL_REQUESTED

- name: SHIPPED
display: Shipped
@@ -253,7 +273,7 @@ states:
events:
- name: shipped-return
desc: Requester sends ISO ShippedReturn
transitions: [SHIPPED_RETURN]
transition: SHIPPED_RETURN

- name: SHIPPED_RETURN
display: Shipped Return
@@ -262,7 +282,8 @@ states:
actions:
- name: mark-received
desc: Mark returned item received and complete (CheckInItem if configured)
transitions: [COMPLETED]
transitions:
success: COMPLETED

- name: CANCEL_REQUESTED
display: Cancel Requested
@@ -271,10 +292,12 @@ states:
actions:
- name: mark-cancelled
desc: Confirm cancellation
transitions: [CANCELLED]
transitions:
success: CANCELLED
- name: will-supply
desc: Resume supplying despite cancel request
transitions: [WILL_SUPPLY]
transitions:
success: WILL_SUPPLY
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

All actions in the YAML file only use the success transition, with no actions using the failure transition. This suggests that failure handling might not be fully designed yet. Consider whether:

  1. Actions can actually fail and transition to different states (e.g., validation failure, network errors during send-request)
  2. If failures should be handled differently (e.g., staying in the same state, transitioning to an error state)
  3. Whether the schema should require at least one of success or failure to be present if transitions are defined

This is worth reviewing to ensure the new schema fully supports the intended workflow model.

Copilot uses AI. Check for mistakes.
Comment on lines +125 to +133
"trigger": {
"type": "string",
"description": "Trigger for the action",
"enum": [
"auto",
"manual"
],
"default": "manual"
},
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The new trigger field is added to the Action schema but is not currently used anywhere in the codebase. The field distinguishes between "auto" (automatically triggered) and "manual" (manually triggered by a user) actions.

Since this field is not currently utilized, consider:

  1. Adding documentation or comments explaining the intended use case for this field
  2. Ensuring that when this field is eventually used, the default value of "manual" is properly applied in the code that reads the state model (as JSON Schema defaults are not automatically enforced during deserialization)
  3. Whether any existing actions should be marked as "auto" to reflect their intended behavior

If this is being added for future functionality, that's fine, but it should be clearly documented.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@adamdickmeiss adamdickmeiss left a comment

Choose a reason for hiding this comment

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

LGTM

@jakub-id jakub-id merged commit 4bcdee5 into main Feb 20, 2026
6 checks passed
@jakub-id jakub-id deleted the state-model-schema-update branch February 20, 2026 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments