{
  "name": "prepare_qualification",
  "title": "Prepare the one-time qualification setup for one promise",
  "description": "Mint the one-time qualification setup for a promise whose meaning a named person has agreed and which has no qualified Balladeer verifier yet, so you can build its verifier and get it protected. You need no sign-off and no code for this: agreeing the meaning was the person's act, and building the check that proves it is yours. Qualification proves itself in CI, so nobody activates anything. What comes back is the same packet the promise page downloads: write `packet.qualificationMetadata` byte for byte to `metadataPath` with no other keys, author the acceptance package at `packagePath` from `packet.revision.meaning` without changing its digest, build and seal the verifier, and push to the default branch. Build it in the shape your instructions describe under \"The shape of a check that lasts\": against the behavior at the boundary the promise names, through the product's own entry point, asserting only what the agreed cases say, with a refactor control that is a genuine restructuring and a known-bad control that is the failure the owner named. A check that copies the product's logic or pins its exact output goes red on the next rewrite and catches nothing. The packet carries no credential and grants no access. It is one-time: while an unspent packet exists this refuses and names who prepared it and when, and `again` mints a replacement that INVALIDATES the earlier one, so a run publishing the earlier identities afterwards is refused. Both are written into the promise's history with you as the actor and the person who connected you as the carrier.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "promiseId": {
        "type": "string",
        "pattern": "^prom_[a-z0-9]{8,64}$"
      },
      "again": {
        "description": "Prepare a replacement even though an unspent packet exists, invalidating that earlier packet. Only when the person asked for one, or the earlier packet is genuinely lost: an agent that sets this to get past a refusal invalidates a packet somebody may be halfway through using.",
        "default": false,
        "type": "boolean"
      }
    },
    "required": [
      "promiseId"
    ],
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "additionalProperties": false
  },
  "annotations": {
    "readOnlyHint": false,
    "destructiveHint": true,
    "idempotentHint": false,
    "openWorldHint": false
  },
  "execution": {
    "taskSupport": "forbidden"
  }
}