goal-request-upload
PREFERRED path to attach a LARGE binary evidence file (screenshot, log dump, PDF, session transcript — anything > ~1 KB) to an acceptance criterion. Returns a one-time {uploadUrl, expiresAt} scoped to this criterion. Then STREAM the raw file to it with a single PUT — no base64, no token:
curl -sS --fail --upload-file "/abs/path/to/file.png" ""
Optionally pass the hex SHA-256 of the file so the server fast-fails on any in-flight corruption: curl -sS --fail -H "X-Content-Sha256: " --upload-file "/abs/path/to/file.png" ""
The PUT response is the same evidence JSON that goal-attach-evidence returns (evidence id, serverSha256, judge verdict, criterion evidenceCount). A non-2xx PUT means the upload was rejected (expired/already-used/wrong-criterion/hash-mismatch) and NO evidence was created — request a fresh URL and retry.
Use this instead of goal-attach-evidence for any non-trivial file. Use goal-add-evidence-text only for byte-less context (external URLs, manual repro notes) — it does NOT cover an AC.
GOAL ATTACHMENTS (description illustrations, NOT evidence): pass goalId INSTEAD of criterionId. The PUT then creates a goal attachment and returns {attachment.url, attachment.markdown} — paste markdown into the goal description and the web UI renders images inline. Such a file is not bound to any AC and never counts toward closing the goal.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Optional evidence kind override. Only accepted value is `session_history` (goal-level transcript artifact; does NOT cover an AC). | |
| goalId | No | UUID of a goal — issues a ticket for a DESCRIPTION ATTACHMENT (not evidence); mutually exclusive with criterionId | |
| caption | No | Optional human-readable description, stored on the evidence | |
| createdBy | No | Identifier of the uploading agent | |
| criterionId | No | UUID acceptance criterion the file will be evidence for (omit when goalId is given) |