(module examples.change_approval
  (capsule "0")
  (profile agentic persistence.surrealdb external.mcp external.a2a ui.a2ui)

  (store operational
    (backend surrealdb)
    (authority runtime-state))

  (store knowledge
    (backend typedb)
    (authority semantic-facts))

  (port ci
    (protocol mcp)
    (tool deploy)
    (tool rollback))

  (agent security_reviewer
    (protocol a2a)
    (skill review_change))

  (surface change_status
    (title "Deployment change status")
    (route "/changes/status")
    (bind ChangeApproval)
    (event SubmitChange RiskReviewed SecurityApprove ManagerApprove Reject Deploy Rollback))

  (surface change_approval
    (title "Deployment change approval")
    (route "/changes/approval")
    (bind ChangeApproval)
    (event SecurityApprove ManagerApprove Reject))

  (surface change_deployment
    (title "Deployment execution")
    (route "/changes/deploy")
    (bind ChangeApproval)
    (event Deploy Rollback))

  (machine ChangeApproval
    (version "0.1.0")
    (context
      (change_id U64)
      (risk_score U32)
      (security_approved Bool)
      (manager_approved Bool)
      (deployed Bool))
    (event SubmitChange
      (change_id U64))
    (event RiskReviewed
      (risk_score U32))
    (event SecurityApprove)
    (event ManagerApprove)
    (event Reject)
    (event Deploy)
    (event Rollback)
    (initial idle)
    (persistence
      (store operational)
      (event-log authoritative)
      (snapshot every-transition)
      (replay true))

    (state idle
      (on SubmitChange
        (target awaiting_risk_review)
        (assign
          (change_id event.change_id)
          (risk_score 0)
          (security_approved false)
          (manager_approved false)
          (deployed false))
        (effects
          (db.write operational.change_requests)
          (a2a.task security_reviewer.review_change)
          (a2ui.emit change_status))))

    (state awaiting_risk_review
      (on RiskReviewed
        (target awaiting_approvals)
        (assign
          (risk_score event.risk_score))
        (effects
          (db.write operational.change_reviews)
          (a2ui.emit change_approval))))

    (state awaiting_approvals
      (on SecurityApprove
        (target awaiting_approvals)
        (assign
          (security_approved true))
        (effects
          (db.write operational.approvals)
          (a2ui.emit change_approval)))
      (on ManagerApprove
        (target ready_to_deploy)
        (guard security_approved)
        (assign
          (manager_approved true))
        (effects
          (db.write operational.approvals)
          (a2ui.emit change_deployment)))
      (on Reject
        (target rejected)
        (effects
          (db.write operational.approvals)
          (a2ui.emit change_status))))

    (state ready_to_deploy
      (on Deploy
        (guard (and security_approved manager_approved (<= risk_score 40)))
        (target deployed)
        (assign
          (deployed true))
        (effects
          (db.write operational.deployments)
          (mcp.call ci.deploy)
          (a2ui.emit change_deployment)))
      (on Reject
        (target rejected)
        (effects
          (db.write operational.approvals)
          (a2ui.emit change_status))))

    (state deployed
      (on Rollback
        (target rolled_back)
        (assign
          (deployed false))
        (effects
          (db.write operational.deployments)
          (mcp.call ci.rollback)
          (a2ui.emit change_deployment))))

    (state rolled_back (type final))
    (state rejected (type final))))
