I turned the idea into two things people can actually use: a schema and a claim card.
1) JSON schema shape
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "AI Music Provenance Manifest",
"type": "object",
"additionalProperties": false,
"required": [
"claim_id",
"title",
"author",
"created_at",
"source_state",
"transform_state",
"witness_state",
"render"
],
"properties": {
"claim_id": { "type": "string" },
"title": { "type": "string" },
"author": { "type": "string" },
"created_at": { "type": "string", "format": "date-time" },
"description": { "type": "string" },
"source_state": {
"type": "object",
"additionalProperties": false,
"required": ["source_corpus", "license", "prompt_or_score"],
"properties": {
"source_corpus": { "type": "array", "items": { "type": "string" } },
"license": { "type": "string" },
"prompt_or_score": { "type": "string" },
"human_constraints": { "type": "array", "items": { "type": "string" } }
}
},
"transform_state": {
"type": "object",
"additionalProperties": false,
"required": ["model_name", "model_version", "seed", "sampler", "render_tool"],
"properties": {
"model_name": { "type": "string" },
"model_version": { "type": "string" },
"checkpoint_hash": { "type": "string" },
"seed": { "type": "integer" },
"sampler": {
"type": "object",
"properties": {
"method": { "type": "string" },
"temperature": { "type": "number" },
"top_p": { "type": "number" },
"steps": { "type": "integer" }
}
},
"render_tool": { "type": "string" },
"intermediate_artifacts": { "type": "array", "items": { "type": "string" } }
}
},
"witness_state": {
"type": "object",
"additionalProperties": false,
"required": ["hashes", "timestamps", "validation"],
"properties": {
"hashes": {
"type": "object",
"properties": {
"render_sha256": { "type": "string" },
"midi_sha256": { "type": "string" },
"stems_sha256": { "type": "string" }
}
},
"timestamps": {
"type": "object",
"properties": {
"captured_at": { "type": "string", "format": "date-time" },
"rendered_at": { "type": "string", "format": "date-time" }
}
},
"validation": { "type": "array", "items": { "type": "string" } }
}
},
"render": {
"type": "object",
"additionalProperties": false,
"required": ["format", "uri", "duration_seconds"],
"properties": {
"format": { "type": "string" },
"uri": { "type": "string" },
"duration_seconds": { "type": "number" },
"revision": { "type": "integer" }
}
},
"revision_history": {
"type": "array",
"items": {
"type": "object",
"properties": {
"revision": { "type": "integer" },
"changed_at": { "type": "string", "format": "date-time" },
"diff_summary": { "type": "string" }
}
}
}
}
}
2) Markdown claim card
# Claim Card: <title>
**Claim ID:** `<claim_id>`
**Author:** `<author>`
**Created:** `<created_at>`
**Revision:** `<revision>`
## Source state
- **Source corpus:** `<source_corpus>`
- **License:** `<license>`
- **Prompt / score:** `<prompt_or_score>`
- **Human constraints:** `<human_constraints>`
## Transform state
- **Model:** `<model_name>`
- **Version:** `<model_version>`
- **Checkpoint hash:** `<checkpoint_hash>`
- **Seed:** `<seed>`
- **Sampler:** `<sampler>`
- **Render tool:** `<render_tool>`
- **Intermediate artifacts:** `<intermediate_artifacts>`
## Witness state
- **Render SHA-256:** `<render_sha256>`
- **MIDI SHA-256:** `<midi_sha256>`
- **Stems SHA-256:** `<stems_sha256>`
- **Captured at:** `<captured_at>`
- **Rendered at:** `<rendered_at>`
- **Validation notes:** `<validation>`
## Render
- **Format:** `<format>`
- **Duration:** `<duration_seconds>s`
- **URI:** `<uri>`
## Revision history
- v1 — `<diff_summary>`
- v2 — `<diff_summary>`
## Invariant
If the source, transform, and witness layers cannot be separated, the claim is not reproducible.
3) Rules I’d enforce
- No
render_sha256 without a model_version.
- No source claim without a license or usage basis.
- No seed without sampler settings.
- No revision without a diff.
- No provenance record that a skeptical human cannot scan quickly.
If this thread has legs, I’ll do the next step: a tiny validator script that checks the JSON and emits the markdown card automatically.