{
	"Comment": "Apple Style Guide Validator step function",
	"StartAt": "asgv-prepare-payload",
	"States": {
		"asgv-prepare-payload": {
			"Type": "Task",
			"Resource": "arn:aws:states:::lambda:invoke",
			"Parameters": {
				"FunctionName": "${PREPARE_PAYLOAD_LAMBDA_ARN}",
				"Payload.$": "$"
			},
			"ResultSelector": {
              	"ExecutedVersion.$": "$.ExecutedVersion",
              	"StatusCode.$": "$.StatusCode",
              	"Payload.$": "$.Payload",
              	"Error": null
            },
			"ResultPath": "$.PreparePayloadTaskResponse",
			"Retry": [
				{
					"ErrorEquals": [
						"States.ALL"
					],
					"IntervalSeconds": 3,
					"MaxAttempts": 3,
					"BackoffRate": 2
				}
			],
			"Catch": [
				{
					"ErrorEquals": [
						"States.ALL"
					],
					"Next": "execution-failed",
					"ResultPath": "$.TaskError"
				}
			],
			"Next": "invoke-bedrock-model"
		},
		"invoke-bedrock-model": {
			"Type": "Task",
			"Resource": "arn:aws:states:::bedrock:invokeModel",
			"Parameters": {
				"ModelId": "arn:aws:bedrock:${REGION}:${ACCOUNT_ID}:inference-profile/us.anthropic.claude-sonnet-4-6",
				"Body": {
					"anthropic_version": "bedrock-2023-05-31",
					"temperature": 0,
					"max_tokens": 8192,
					"system": [
						{
							"type": "text",
							"text": "${SYSTEM_PROMPT}",
							"cache_control": {
								"type": "ephemeral",
								"ttl": "1h"
							}
						}
					],
					"messages": [
						{
							"role": "user",
							"content.$": "States.Format('Validate the following music product metadata against all Apple Music Style Guide rules defined in your instructions.\n\nFor each rule:\n- If FAIL or WARNING: add a full entry to `issues` with ruleId, scope, status, fieldName (no array indexes), message, and affectedInstances where applicable\n- If PASS: add the rule ID only (e.g. \"2.1\") to `passedRuleIds`\n- If NOT_APPLICABLE: add the rule ID only to `notApplicableRuleIds`\n\nGroup violations: one issue per ruleId + scope combination. List multiple affected tracks in affectedInstances — do not split into separate issues.\n\nAssign a holistic `score` (0–100) and a `rationale` explaining the score.\n\nSet `decision` to \"REJECT\" if any FAIL exists on a non-auto-corrected rule, otherwise \"ACCEPT\".\n\nProduct metadata:\n\n<product>\n{}\n</product>', $.PreparePayloadTaskResponse.Payload.product_metadata)"
						}
					],
					"output_config": {
						"format": {
							"type": "json_schema",
							"schema": {
								"type": "object",
								"properties": {
									"passedRuleIds": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"notApplicableRuleIds": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"issues": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"ruleId": {
													"type": "string"
												},
												"scope": {
													"type": "string",
													"enum": [
														"release",
														"track"
													]
												},
												"status": {
													"type": "string",
													"enum": [
														"FAIL",
														"WARNING"
													]
												},
												"fieldName": {
													"type": "string"
												},
												"affectedInstances": {
													"type": "array",
													"items": {
														"type": "object",
														"properties": {
															"trackNumber": {
																"type": "integer"
															},
															"volumeNumber": {
																"type": "integer"
															}
														},
														"required": [
															"trackNumber",
															"volumeNumber"
														],
														"additionalProperties": false
													}
												},
												"message": {
													"type": "string"
												}
											},
											"required": [
												"ruleId",
												"status",
												"scope",
												"fieldName",
												"affectedInstances",
												"message"
											],
											"additionalProperties": false
										}
									},
									"score": {
										"type": "integer"
									},
									"rationale": {
										"type": "string"
									},
									"decision": {
										"type": "string",
										"enum": [
											"ACCEPT",
											"REJECT"
										]
									}
								},
								"required": [
									"issues",
									"passedRuleIds",
									"notApplicableRuleIds",
									"score",
									"rationale",
									"decision"
								],
								"additionalProperties": false
							}
						}
					}
				},
				"ContentType": "application/json",
				"Accept": "application/json",
				"Output": {
					"S3Uri.$": "States.Format('s3://${RESULTS_BUCKET}/bedrock-model-output/{}.json', $.PreparePayloadTaskResponse.Payload.output_s3_path)"
				}
			},
			"ResultSelector": {
				"Payload.$": "$.Body"
			},
			"ResultPath": "$.InvokeBedrockModelTaskResponse",
			"Retry": [
				{
					"ErrorEquals": [
						"States.ALL"
					],
					"IntervalSeconds": 3,
					"MaxAttempts": 3,
					"BackoffRate": 2
				}
			],
			"Catch": [
				{
					"ErrorEquals": [
						"States.ALL"
					],
					"Next": "execution-failed",
					"ResultPath": "$.TaskError"
				}
			],
			"End": true
		},
		"execution-failed": {
			"Type": "Fail"
		}
	}
}
