Releases and migration safety for agents

Read rehearsal evidence, confirm parked releases, and steer the release safety dial. This page is written for an AI agent. It extends the deployment protocol at https://app.tokay.io/llms.txt. Everything here is an escape hatch. The happy path needs none of it, so act on an explicit user request or a named readiness action, not on your own initiative.

Last updated

The release model

  • Tokay rehearses every managed database migration against a disposable clone of the production data before anything touches production. The evidence from that rehearsal, not the SQL text, is what release policy judges.
  • Two evidence channels ride each release execution. impactAssessment carries observed facts, including the planRollup with schema diffs and the policy result. releaseAnalysis carries AI verdicts, liveSafe (can the currently live code survive the migration), deployOk (will the new code work after it), and dataSafety (safe, risky, or uncertain).
  • releaseSafetyMode decides how much of that authority is automatic. MANUAL parks everything, including rollbacks. STRICT applies only deterministically additive changes automatically. NORMAL, the default, adds changes the AI judged safe. UNRESTRICTED applies everything automatically, still snapshotting managed databases first. Deploy calls accept an optional releaseSafetyMode where the strictest value wins, so a request can narrow authority for one deploy but never widen it.
  • A parked release is not a failure. deployReadiness.action: CONFIRM_RELEASE means evidence is waiting for a human decision. Your job is to read it, summarize it faithfully, and confirm only after the user agrees.
  • External databases that Tokay does not host get no rehearsal and no snapshot, and park under every mode except UNRESTRICTED.

What to call

To Use
Detect a park deployReadiness { action targetDeployment { id } }
Read the evidence targetDeployment.releaseExecutions
Apply the parked plan confirmDeploymentRelease
Change the dial updateProject / updateService patch releaseSafetyMode
Review a proposed migration command service.serviceReleaseActionOverrides, updateServiceReleaseActionOverride
Recover a maintenance hold recoverServiceMaintenanceHold

Read a parked release

When deployReadiness.action is CONFIRM_RELEASE, read deployReadiness.targetDeployment. Do not assume the newest deployment row is the parked one.

query ReleaseConfirmation($serviceId: ID!) {
  service(id: $serviceId) {
    deployReadiness {
      state reason action message
      targetDeployment {
        id deployState deployWaitReason releaseSafetyMode releaseStrategy
        releaseExecutions(orderBy: ACTION_INDEX_ASC) {
          nodes {
            id actionName command releaseExecutionPhase releaseExecutionState
            impactAssessment releaseAnalysis
            projectResource { id resourceType runtimeName }
          }
        }
      }
    }
  }
}

impactAssessment and releaseAnalysis are JSON with camelCase keys. Each database's final REHEARSAL row carries impactAssessment.planRollup with diffAtCutover and diffFinal schema diffs (changes entries like {"type": "ADD_COLUMN", ...}) and the policy object. policy.reasons is an array of {reason, message} objects, such as {"reason": "MANUAL_MODE", "message": "This project applies release actions only after explicit confirmation."}. Other reason codes include DATA_SAFETY_RISKY, EXTERNAL_DATABASE_UNVERIFIED, and HARD_STOP_EXCEEDS_AUTO_WINDOW. Summarize the reasons, the diffs, and the releaseAnalysis verdicts to the user before confirming.

Confirm

mutation Confirm($deployment: ID!) {
  confirmDeploymentRelease(input: { deployment: $deployment }) {
    deployment { id deployState }
  }
}

Confirming runs the rehearsed plan against production. Tokay snapshots each managed database immediately before mutating it. After confirming, poll the service back to deployState: DEPLOYED with deployReadiness.state: UP_TO_DATE. A release that applied automatically shows the same evidence trail afterward, a REHEARSAL row and then a PRODUCTION row per action, so you can always answer what ran and why it was allowed.

The safety dial

releaseSafetyMode lives on the project (project.releaseSafetyMode) and services inherit it. A service can override with its own value, where null means inherit. Change it through the generated update mutations, for example updateProject(input: { id: $id, patch: { releaseSafetyMode: MANUAL } }). Under NORMAL, do not expect every statement that looks destructive to park. The rehearsal runs against real data, and a drop that loses nothing observable can be judged safe and apply on its own. Change the dial only when the user asks for it. If the user wants a guaranteed gate, set MANUAL and treat CONFIRM_RELEASE as the routine path. wontRunBypass: true on a deploy call overrides only an AI "new code won't work" prediction. Rehearsal failures always block.

Migration command overrides

UNCONFIRMED_RELEASE_ACTION as a deploy blocker means Tokay found migration machinery it cannot run automatically and proposed a command. List the service's serviceReleaseActionOverrides and review commandArgv, workingDirectory, and releaseActionTiming. Enable with updateServiceReleaseActionOverride(input: { id: $id, patch: { enabled: true } }), editing commandArgv in the same patch when the proposal is wrong, or dismiss with patch: { dismissedAt: "<now ISO8601>" }. Never enable a command you have not shown the user.

Maintenance holds

deployReadiness.action: RECOVER_MAINTENANCE_HOLD means a release left the runtime in a state Tokay will not touch without a human assertion, and the app may be serving a maintenance response. After the user verifies the runtime target is safe, call recoverServiceMaintenanceHold(input: { service: $service, safetyAssertion: "..." }) with a sentence recording what was verified, then poll readiness.

Error shapes

You see It means Do this
deployReadiness.action: CONFIRM_RELEASE Evidence is parked for a decision Read targetDeployment, summarize, confirm only with user agreement
deployWaitReason: AWAITING_RELEASE_CONFIRMATION Same park, seen from the deployment row Follow the readiness action, not this field alone
A rollback parks at CONFIRM_RELEASE The project is in MANUAL mode Confirm it like any release. It runs no migrations
releaseExecutionState: FAILED on a REHEARSAL row The migration failed against the clone Fix the migration and push again. Rehearsal failures never reach production
policy.reasons contains EXTERNAL_DATABASE_UNVERIFIED Tokay cannot rehearse a database it does not host Warn the user there is no rehearsal or snapshot behind this confirm