The versioning promise
- The
ocpfield is a scalar version string of the form0.x. - A reader accepts every published version (0.1, 0.2 and 0.3) and MUST ignore fields it does not know at any level of the document: the top level, and the run, node, attempt, artifact, edge, event and
extobjects. - 0.3 is a strict superset of 0.2: every field 0.3 adds is optional, so a valid 0.2 document stays valid when its
ocpvalue is changed to0.3, unless it uses a name that 0.3 defines as an unknown field of its own (for example a string inrun.task, which 0.3 defines as an object). 0.2 is not a superset of 0.1: 0.2 requirestieron every edge, so 0.1 documents needloopmath ocp migrate, which writes the 0.3 form. - A field is never removed without a deprecation notice that names its replacement and stays in the specification for at least two minor versions.
- Extension namespaces use reverse-domain identifiers. The specification’s own namespace begins
io.orchestrationcontextprotocol.; see Extensions.
Versions and schemas
Each version has its own JSON Schema, and a document is validated against the schema itsocp value names.
A reader MUST accept 0.1, 0.2 and 0.3 documents, and reads each one by the schema and rules of the version it declares. Rules added in a version apply to documents at that version or later: the numbered 0.3 rules do not apply to a 0.2 document.
Accepting an older document does not mean keeping it in its old form. loopmath’s run store, for example, keeps only 0.3 documents:
loopmath run import migrates a 0.1 or 0.2 document before storing it, and a document that reaches the store in an older version any other way is refused with E005, a store rule rather than an OCP rule.
Migration
loopmath ocp migrate FILE... [--out DIR] upgrades 0.1 and 0.2 documents to 0.3. Raising the ocp value by hand is not a migration for a 0.1 document, which fails once its edges lack a tier. The command never changes or overwrites its input, and running it on its own output returns that output unchanged. It adds a field only when the field is absent:
ocpbecomes0.3, andrun.ext["dev.loopmath.migration"]records{"from": <version>}.- A 0.1 edge without a tier gets
reported. run.taskcomes from the run’stask,typeandrepolabels (the id from thetasklabel, else the run id), marked{how: inferred, tier: heuristic}.node.vertexcomes from its attempts’role.valuewhen they agree on one value.run.provenancebecomes{kind: logged, chooser: habit}, the migration’s default for a run whose choice is not recorded.run.configurationbecomes{source: habit}, plus the inferred workflow and settings when loopmath can infer them, with the confidence inext["dev.loopmath.inferred"]at tierheuristic.