diff --git a/Cargo.lock b/Cargo.lock index 1fe2492..9efbed5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -252,6 +252,7 @@ dependencies = [ "rmp-serde", "schemars", "serde", + "serde_json", "sha2", "tempfile", ] diff --git a/crates/huginn-mind/Cargo.toml b/crates/huginn-mind/Cargo.toml index ca01ae8..6074ad0 100644 --- a/crates/huginn-mind/Cargo.toml +++ b/crates/huginn-mind/Cargo.toml @@ -21,4 +21,5 @@ serde = { version = "1", features = ["derive"] } sha2 = "0.10" [dev-dependencies] +serde_json = "1" tempfile = "3" diff --git a/crates/huginn-mind/src/lib.rs b/crates/huginn-mind/src/lib.rs index 20345ee..55d92c6 100644 --- a/crates/huginn-mind/src/lib.rs +++ b/crates/huginn-mind/src/lib.rs @@ -13,6 +13,9 @@ //! The read side derives status, joins the receipts and answers typed queries //! through the same `docs` the rules use; nothing is stored for it. //! +//! The wire vocabulary is here too, so the daemon and the client share one set +//! of types. +//! //! Document shape, bounds, formats and keys are `epiphany-pipeline`'s; the //! organ registers, prepares, decodes and validates through the leaf's four //! doors and never re-derives a key. The store is CultLib's owned redb @@ -27,6 +30,7 @@ pub mod query; pub mod receipt; pub mod refusal; pub mod store; +pub mod wire; #[cfg(test)] pub(crate) mod fixtures; @@ -40,6 +44,10 @@ pub use query::{ pub use receipt::{DocumentVersion, Faculty, HuginnCommitReceipt, PipelineProvenance, RECEIPT_SCHEMA_VERSION}; pub use refusal::MindRefusal; pub use store::{MindStore, OwnedRedbMessagePackBackingStore}; +pub use wire::{ + HuginnMindRequest, HuginnMindResponse, MIND_REQUEST_SCHEMA, MIND_REQUEST_SCHEMA_JSON, MIND_RESPONSE_SCHEMA, + MIND_RESPONSE_SCHEMA_JSON, MIND_SERVICE_ID, MindStatus, +}; /// The leaf, whole, through the one crate that pins its rev: the daemon and /// the client name `Slug`, `PipelineRef` and the document types from here, so diff --git a/crates/huginn-mind/src/wire.rs b/crates/huginn-mind/src/wire.rs new file mode 100644 index 0000000..0b441fb --- /dev/null +++ b/crates/huginn-mind/src/wire.rs @@ -0,0 +1,217 @@ +//! The organ's request and response vocabulary: one operation per `Mind` +//! method and `whoami`. Payloads are the admission and read types unchanged. +//! The daemon carries these in CultNet's operation envelope; the client +//! constructs them. Nothing here validates a document, derives a status or +//! names a transport. + +use cultcache_rs::DatabaseEntry; +use epiphany_pipeline::{PIPELINE_SCHEMA_EPOCH, PipelineKind, PipelineRef, Slug}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::admission::{PipelineAdmissionBatch, PipelineAdmissionOutcome}; +use crate::mind::Mind; +use crate::query::{ + HistoryScope, PipelineDocumentView, PipelineOpenItems, PipelineQuery, PipelineQueryPage, +}; +use crate::receipt::HuginnCommitReceipt; +use crate::refusal::MindRefusal; +use crate::store::MindStore; + +/// The envelope's `service_id`: one service, one mind, whichever mind the +/// process opened. +pub const MIND_SERVICE_ID: &str = "huginn.mind"; +pub const MIND_REQUEST_SCHEMA: &str = "huginn.mind_request.v1"; +pub const MIND_RESPONSE_SCHEMA: &str = "huginn.mind_response.v1"; + +/// The published JSON schema of each wire type, as the catalog advertises it. +/// The files are derived from the types below and pinned byte for byte by +/// `published_wire_schemas_match_derivation`, so the catalog cannot advertise +/// a shape the crate does not speak. +pub const MIND_REQUEST_SCHEMA_JSON: &str = + include_str!("../../../schemas/cultnet/huginn.mind_request.v1.schema.json"); +pub const MIND_RESPONSE_SCHEMA_JSON: &str = + include_str!("../../../schemas/cultnet/huginn.mind_response.v1.schema.json"); + +/// Every operation a mind answers. `Admit` carries the batch whole because the +/// batch already names the instance and the asker; a second `instance` beside +/// it would be two declarations. Every read names the instance because ruling +/// 14 refuses another mind's identity whatever the transport, and a read of +/// the wrong mind is that same collision on the read side. `Whoami` names +/// none: it is how a client learns which mind it reached. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub enum HuginnMindRequest { + Whoami, + Admit(PipelineAdmissionBatch), + View { instance: Slug, id: PipelineRef }, + Query { instance: Slug, query: PipelineQuery }, + OpenItems { instance: Slug, campaign: Slug }, + History { instance: Slug, scope: HistoryScope }, +} + +impl HuginnMindRequest { + /// The envelope's `operation`. + pub fn operation(&self) -> &'static str { + match self { + Self::Whoami => "whoami", + Self::Admit(_) => "admit", + Self::View { .. } => "view", + Self::Query { .. } => "query", + Self::OpenItems { .. } => "open_items", + Self::History { .. } => "history", + } + } + + /// The instance the request declares; `Whoami` declares none. + pub fn instance(&self) -> Option<&Slug> { + match self { + Self::Whoami => None, + Self::Admit(batch) => Some(&batch.instance), + Self::View { instance, .. } + | Self::Query { instance, .. } + | Self::OpenItems { instance, .. } + | Self::History { instance, .. } => Some(instance), + } + } +} + +/// Every answer a mind gives. A refusal is data in the response, never a +/// transport failure: the read side carries `Refused`, the write side carries +/// the outcome's own `Refused`. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub enum HuginnMindResponse { + Whoami(MindStatus), + Admit(PipelineAdmissionOutcome), + View(Option), + Query(PipelineQueryPage), + OpenItems(PipelineOpenItems), + History(Vec), + Refused(MindRefusal), +} + +impl HuginnMindResponse { + /// The envelope's `status`, in the C# reference's vocabulary: `rejected` + /// exactly for a refusal, `accepted` otherwise. `Conflict` and + /// `AlreadyAdmitted` are answers about the mind, not refusals of the + /// request. + pub fn status(&self) -> &'static str { + match self { + Self::Refused(_) | Self::Admit(PipelineAdmissionOutcome::Refused(_)) => "rejected", + _ => "accepted", + } + } +} + +/// What a mind says about itself: the typed state a dashboard projects. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub struct MindStatus { + pub instance: Slug, + pub schema_epoch: String, + /// Pipeline documents in the image; the epoch record and the receipts are + /// not documents and are not counted here. + pub documents: u32, + pub receipts: u32, +} + +impl Mind { + /// `whoami`, derived from the image every time it is asked. Nothing stores + /// a status and no configuration supplies one. + pub fn status(&self) -> MindStatus { + let mut documents = 0_u32; + let mut receipts = 0_u32; + for envelope in self.envelopes() { + if envelope.r#type == HuginnCommitReceipt::TYPE { + receipts += 1; + } else if PipelineKind::ALL.iter().any(|kind| kind.type_id() == envelope.r#type) { + documents += 1; + } + } + MindStatus { + instance: self.instance().clone(), + schema_epoch: PIPELINE_SCHEMA_EPOCH.to_string(), + documents, + receipts, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::fixtures::{CAMPAIGN, INSTANCE, OTHER_INSTANCE, instance, provenance, r, repo, seeded, slug}; + use crate::receipt::Faculty; + + fn requests() -> Vec { + let batch = PipelineAdmissionBatch { + instance: slug(INSTANCE), + provenance: provenance(Faculty::Hands), + documents: vec![instance(INSTANCE)], + }; + vec![ + HuginnMindRequest::Whoami, + HuginnMindRequest::Admit(batch), + HuginnMindRequest::View { instance: slug(INSTANCE), id: r(PipelineKind::Campaign, CAMPAIGN) }, + HuginnMindRequest::Query { instance: slug(INSTANCE), query: PipelineQuery::default() }, + HuginnMindRequest::OpenItems { instance: slug(INSTANCE), campaign: slug(CAMPAIGN) }, + HuginnMindRequest::History { + instance: slug(OTHER_INSTANCE), + scope: HistoryScope::Repo(repo("GameCult/Huginn")), + }, + ] + } + + fn responses() -> Vec { + let refusal = MindRefusal::ForeignInstance { declared: OTHER_INSTANCE.into(), mind: INSTANCE.into() }; + vec![ + HuginnMindResponse::Whoami(seeded().status()), + HuginnMindResponse::Admit(PipelineAdmissionOutcome::AlreadyAdmitted { receipt_id: "r1".into() }), + HuginnMindResponse::Admit(PipelineAdmissionOutcome::Conflict { identities: vec![] }), + HuginnMindResponse::Admit(PipelineAdmissionOutcome::Refused(refusal.clone())), + HuginnMindResponse::View(None), + HuginnMindResponse::Query(PipelineQueryPage { items: vec![], matched: 0 }), + HuginnMindResponse::OpenItems(seeded().open_items(&slug(CAMPAIGN)).unwrap()), + HuginnMindResponse::History(vec![]), + HuginnMindResponse::Refused(refusal), + ] + } + + /// The vocabulary is the mind's methods, the declared instance is on every + /// request that names a mind, and the envelope's status is derived from + /// the response rather than chosen by whoever sends it. + #[test] + fn the_wire_vocabulary_is_the_minds_methods_and_status_is_derived_from_the_response() { + let names: Vec<&str> = requests().iter().map(|request| request.operation()).collect(); + assert_eq!(names, ["whoami", "admit", "view", "query", "open_items", "history"]); + for request in requests() { + let declared = request.instance().is_none(); + assert_eq!(declared, matches!(request, HuginnMindRequest::Whoami), "{request:?}"); + let bytes = rmp_serde::to_vec_named(&request).unwrap(); + assert_eq!(rmp_serde::from_slice::(&bytes).unwrap(), request); + } + assert_eq!( + requests()[5].instance(), + Some(&slug(OTHER_INSTANCE)), + "the request's instance is the one it declares, not the mind's" + ); + + for response in responses() { + let rejected = matches!( + response, + HuginnMindResponse::Refused(_) | HuginnMindResponse::Admit(PipelineAdmissionOutcome::Refused(_)) + ); + assert_eq!(response.status(), if rejected { "rejected" } else { "accepted" }, "{response:?}"); + let bytes = rmp_serde::to_vec_named(&response).unwrap(); + assert_eq!(rmp_serde::from_slice::(&bytes).unwrap(), response); + } + } + + /// The two files the catalog publishes are the derivation of the two + /// types, byte for byte. + #[test] + fn published_wire_schemas_match_derivation() { + let request = serde_json::to_string_pretty(&schemars::schema_for!(HuginnMindRequest)).unwrap(); + let response = serde_json::to_string_pretty(&schemars::schema_for!(HuginnMindResponse)).unwrap(); + assert_eq!(MIND_REQUEST_SCHEMA_JSON.replace("\r\n", "\n"), request); + assert_eq!(MIND_RESPONSE_SCHEMA_JSON.replace("\r\n", "\n"), response); + } +} diff --git a/schemas/cultnet/README.md b/schemas/cultnet/README.md new file mode 100644 index 0000000..f6a34a5 --- /dev/null +++ b/schemas/cultnet/README.md @@ -0,0 +1,11 @@ +# Huginn's CultNet contracts + +`huginn.mind_request.v1` and `huginn.mind_response.v1` are the organ's own wire +schemas, published from here because Huginn owns them. `huginn-daemon` serves +them on a `cultnet.schema_catalog_request.v0`; nothing else reads them. + +Each file is `serde_json::to_string_pretty` of `schemars::schema_for!` over the +type of the same name in `crates/huginn-mind/src/wire.rs`. Regenerate by hand +and the test refuses it: +`cargo test -p huginn-mind --lib -- --exact wire::tests::published_wire_schemas_match_derivation` +compares file to derivation byte for byte. diff --git a/schemas/cultnet/huginn.mind_request.v1.schema.json b/schemas/cultnet/huginn.mind_request.v1.schema.json new file mode 100644 index 0000000..1b39d4a --- /dev/null +++ b/schemas/cultnet/huginn.mind_request.v1.schema.json @@ -0,0 +1,2030 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "HuginnMindRequest", + "description": "Every operation a mind answers. `Admit` carries the batch whole because the\nbatch already names the instance and the asker; a second `instance` beside\nit would be two declarations. Every read names the instance because ruling\n14 refuses another mind's identity whatever the transport, and a read of\nthe wrong mind is that same collision on the read side. `Whoami` names\nnone: it is how a client learns which mind it reached.", + "oneOf": [ + { + "type": "string", + "enum": [ + "Whoami" + ] + }, + { + "type": "object", + "properties": { + "Admit": { + "$ref": "#/$defs/PipelineAdmissionBatch" + } + }, + "additionalProperties": false, + "required": [ + "Admit" + ] + }, + { + "type": "object", + "properties": { + "View": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/PipelineRef" + }, + "instance": { + "$ref": "#/$defs/Slug" + } + }, + "required": [ + "instance", + "id" + ] + } + }, + "additionalProperties": false, + "required": [ + "View" + ] + }, + { + "type": "object", + "properties": { + "Query": { + "type": "object", + "properties": { + "instance": { + "$ref": "#/$defs/Slug" + }, + "query": { + "$ref": "#/$defs/PipelineQuery" + } + }, + "required": [ + "instance", + "query" + ] + } + }, + "additionalProperties": false, + "required": [ + "Query" + ] + }, + { + "type": "object", + "properties": { + "OpenItems": { + "type": "object", + "properties": { + "campaign": { + "$ref": "#/$defs/Slug" + }, + "instance": { + "$ref": "#/$defs/Slug" + } + }, + "required": [ + "instance", + "campaign" + ] + } + }, + "additionalProperties": false, + "required": [ + "OpenItems" + ] + }, + { + "type": "object", + "properties": { + "History": { + "type": "object", + "properties": { + "instance": { + "$ref": "#/$defs/Slug" + }, + "scope": { + "$ref": "#/$defs/HistoryScope" + } + }, + "required": [ + "instance", + "scope" + ] + } + }, + "additionalProperties": false, + "required": [ + "History" + ] + } + ], + "$defs": { + "AuthorityMap": { + "type": "object", + "properties": { + "deletion_line": { + "$ref": "#/$defs/Line" + }, + "derived_state": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + }, + "forbidden_writers": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + }, + "inputs": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + }, + "outputs": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + }, + "owner": { + "$ref": "#/$defs/Line" + }, + "shared_paths": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + } + }, + "required": [ + "owner", + "inputs", + "outputs", + "derived_state", + "forbidden_writers", + "shared_paths", + "deletion_line" + ] + }, + "ClaimOutcome": { + "type": "string", + "enum": [ + "Holds", + "Falsified", + "Unproven" + ] + }, + "CodeLocation": { + "type": "object", + "properties": { + "end_line": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0 + }, + "line": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "path": { + "$ref": "#/$defs/Short" + } + }, + "required": [ + "path", + "line" + ] + }, + "CommitRange": { + "type": "object", + "properties": { + "base": { + "$ref": "#/$defs/Sha" + }, + "head": { + "$ref": "#/$defs/Sha" + } + }, + "required": [ + "base", + "head" + ] + }, + "CutDelete": { + "type": "object", + "properties": { + "lines": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "note": { + "$ref": "#/$defs/Line" + }, + "path": { + "$ref": "#/$defs/Short" + } + }, + "required": [ + "path", + "lines", + "note" + ] + }, + "CutVerification": { + "type": "object", + "properties": { + "builds": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 64 + }, + "negative": { + "type": "array", + "items": { + "$ref": "#/$defs/NegativeCheck" + }, + "maxItems": 64 + }, + "operator": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 64 + }, + "tests": { + "type": "array", + "items": { + "$ref": "#/$defs/VerificationTest" + }, + "maxItems": 64 + } + }, + "required": [ + "builds", + "tests", + "negative", + "operator" + ] + }, + "Date": { + "description": "A calendar date, `YYYY-MM-DD`.", + "type": "string", + "maxLength": 10 + }, + "Deviation": { + "type": "object", + "properties": { + "what": { + "$ref": "#/$defs/Line" + }, + "why": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "what", + "why" + ] + }, + "DocRef": { + "type": "object", + "properties": { + "commit": { + "$ref": "#/$defs/Sha" + }, + "end_line": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "path": { + "$ref": "#/$defs/Short" + }, + "start_line": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "path", + "start_line", + "end_line", + "commit" + ] + }, + "Evidence": { + "type": "object", + "properties": { + "kind": { + "$ref": "#/$defs/EvidenceKind" + }, + "locator": { + "$ref": "#/$defs/Line" + }, + "result": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "kind", + "locator", + "result" + ] + }, + "EvidenceKind": { + "type": "string", + "enum": [ + "Command", + "Test", + "Mutation", + "Probe", + "SourceRead", + "Capture" + ] + }, + "Faculty": { + "description": "Which faculty a batch was admitted as. Attribution, not authority\n(ruling 18): no admission rule trusts it, and Cut 9's views read it back\nfrom the receipt.", + "type": "string", + "enum": [ + "SelfFaculty", + "Imagination", + "Hands", + "Soul", + "MindSteward", + "Eyes", + "Operator" + ] + }, + "FileChange": { + "type": "object", + "properties": { + "change": { + "$ref": "#/$defs/Line" + }, + "location": { + "$ref": "#/$defs/CodeLocation" + } + }, + "required": [ + "location", + "change" + ] + }, + "FindingConfidence": { + "type": "string", + "enum": [ + "Confirmed", + "Plausible" + ] + }, + "FindingOrigin": { + "type": "string", + "enum": [ + "Introduced", + "PreExisting" + ] + }, + "FindingSeverity": { + "type": "string", + "enum": [ + "Blocker", + "High", + "Medium", + "Low" + ] + }, + "ForeignRef": { + "description": "A citation of a document in another repo's pipeline store (D6).", + "type": "object", + "properties": { + "commit": { + "$ref": "#/$defs/FullSha" + }, + "id": { + "$ref": "#/$defs/Short" + }, + "kind": { + "$ref": "#/$defs/PipelineKind" + }, + "payload_sha256": { + "$ref": "#/$defs/Sha256Hex" + }, + "repo": { + "$ref": "#/$defs/OrgRepo" + } + }, + "required": [ + "repo", + "commit", + "kind", + "id", + "payload_sha256" + ] + }, + "FullSha": { + "description": "A full git commit id: exactly 40 lowercase hex characters.", + "type": "string", + "maxLength": 40 + }, + "HistoryScope": { + "description": "What a history is a history of: every resolution one subject ever had, or\nevery assignment of one repo to this mind.", + "oneOf": [ + { + "type": "object", + "properties": { + "Subject": { + "$ref": "#/$defs/PipelineRef" + } + }, + "additionalProperties": false, + "required": [ + "Subject" + ] + }, + { + "type": "object", + "properties": { + "Repo": { + "$ref": "#/$defs/OrgRepo" + } + }, + "additionalProperties": false, + "required": [ + "Repo" + ] + } + ] + }, + "Label": { + "description": "A key label: `[A-Za-z0-9_-]{1,64}`.", + "type": "string", + "maxLength": 64 + }, + "LandedName": { + "description": "A name the cut landed, and where it lives.", + "type": "object", + "properties": { + "name": { + "$ref": "#/$defs/Short" + }, + "path": { + "$ref": "#/$defs/Short" + } + }, + "required": [ + "name", + "path" + ] + }, + "Line": { + "description": "Text of at most 1,000 UTF-8 bytes.", + "type": "string", + "maxLength": 1000 + }, + "MutationRecord": { + "description": "One mutation a report ran: a key-safe label a verdict claim can name,\nthe exact edit, and the tree it was applied to.", + "type": "object", + "properties": { + "after": { + "$ref": "#/$defs/Line" + }, + "before": { + "$ref": "#/$defs/Line" + }, + "commit": { + "$ref": "#/$defs/Sha" + }, + "failed_as_expected": { + "type": "boolean" + }, + "label": { + "$ref": "#/$defs/Label" + }, + "location": { + "$ref": "#/$defs/CodeLocation" + }, + "rule": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "label", + "rule", + "location", + "before", + "after", + "commit", + "failed_as_expected" + ] + }, + "NegativeCheck": { + "type": "object", + "properties": { + "pattern": { + "$ref": "#/$defs/Short" + }, + "scope": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "pattern", + "scope" + ] + }, + "OrgRepo": { + "description": "A GitHub repository as `Org/Repo`.", + "type": "string", + "maxLength": 200 + }, + "Para": { + "description": "Text of at most 4,000 UTF-8 bytes; longer narrative is cited by `DocRef`.", + "type": "string", + "maxLength": 4000 + }, + "PipelineAdmissionBatch": { + "description": "One admission request: the mind it is for, who asks, and the documents.\nRides the wire whole (`wire::HuginnMindRequest::Admit`).", + "type": "object", + "properties": { + "documents": { + "type": "array", + "items": { + "$ref": "#/$defs/PipelineDocument" + } + }, + "instance": { + "$ref": "#/$defs/Slug" + }, + "provenance": { + "$ref": "#/$defs/PipelineProvenance" + } + }, + "required": [ + "instance", + "provenance", + "documents" + ] + }, + "PipelineCampaign": { + "type": "object", + "properties": { + "repos": { + "type": "array", + "items": { + "$ref": "#/$defs/OrgRepo" + }, + "maxItems": 8 + }, + "slug": { + "$ref": "#/$defs/Slug" + }, + "target_doc": { + "$ref": "#/$defs/DocRef" + }, + "title": { + "$ref": "#/$defs/Short" + }, + "working_branch": { + "$ref": "#/$defs/Short" + } + }, + "required": [ + "slug", + "title", + "repos", + "working_branch", + "target_doc" + ] + }, + "PipelineCutReport": { + "type": "object", + "properties": { + "attempt": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "branch": { + "$ref": "#/$defs/Short" + }, + "campaign": { + "$ref": "#/$defs/Slug" + }, + "commits": { + "type": "array", + "items": { + "$ref": "#/$defs/ReportCommit" + }, + "maxItems": 128 + }, + "cut_spec": { + "$ref": "#/$defs/Short" + }, + "deviations": { + "type": "array", + "items": { + "$ref": "#/$defs/Deviation" + }, + "maxItems": 32 + }, + "forks": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 8 + }, + "landed_names": { + "type": "array", + "items": { + "$ref": "#/$defs/LandedName" + }, + "maxItems": 128 + }, + "mutations": { + "type": "array", + "items": { + "$ref": "#/$defs/MutationRecord" + }, + "maxItems": 64 + }, + "promises": { + "type": "array", + "items": { + "$ref": "#/$defs/Promise" + }, + "maxItems": 64 + }, + "range": { + "$ref": "#/$defs/CommitRange" + }, + "repo": { + "$ref": "#/$defs/OrgRepo" + }, + "structural_delta": { + "$ref": "#/$defs/StructuralDelta" + }, + "undone": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 32 + }, + "verification": { + "type": "array", + "items": { + "$ref": "#/$defs/Evidence" + }, + "maxItems": 64 + } + }, + "required": [ + "campaign", + "cut_spec", + "attempt", + "repo", + "branch", + "commits", + "range", + "verification", + "mutations", + "deviations", + "forks", + "structural_delta", + "landed_names", + "undone", + "promises" + ] + }, + "PipelineCutSpec": { + "type": "object", + "properties": { + "adds": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 64 + }, + "authority_map": { + "anyOf": [ + { + "$ref": "#/$defs/AuthorityMap" + }, + { + "type": "null" + } + ] + }, + "base": { + "$ref": "#/$defs/Sha" + }, + "branch": { + "$ref": "#/$defs/Short" + }, + "campaign": { + "$ref": "#/$defs/Slug" + }, + "cut": { + "$ref": "#/$defs/Label" + }, + "deletes": { + "type": "array", + "items": { + "$ref": "#/$defs/CutDelete" + }, + "maxItems": 64 + }, + "depends_on": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 8 + }, + "estimate": { + "$ref": "#/$defs/StructuralDelta" + }, + "file_changes": { + "type": "array", + "items": { + "$ref": "#/$defs/FileChange" + }, + "maxItems": 256 + }, + "first": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + }, + "keeps_moves": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 64 + }, + "questions": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 16 + }, + "repo": { + "$ref": "#/$defs/OrgRepo" + }, + "revision": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "rulings": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 32 + }, + "title": { + "$ref": "#/$defs/Short" + }, + "verification": { + "$ref": "#/$defs/CutVerification" + } + }, + "required": [ + "campaign", + "cut", + "revision", + "title", + "repo", + "branch", + "base", + "depends_on", + "first", + "deletes", + "keeps_moves", + "adds", + "file_changes", + "verification", + "estimate", + "rulings", + "questions" + ] + }, + "PipelineDocument": { + "description": "The envelope enum, adjacently tagged on the kind name: a document\non a wire is `{ kind, value }`, and `kind` is exactly what\n`PipelineKind::name()` returns, so a reader dispatches on the kind\nsegment it already knows from the key and needs no second registry\nmapping variant spellings to kinds. Adjacent rather than internal\nbecause a value is a named map of its own and an internal tag would\nhave to be merged into it; the tag stays beside the value instead.\nThis is not a published schema: `schemas/cultnet` publishes the\nthirteen per-kind value documents, and the envelope is the wire's\nshape, not a document's.", + "oneOf": [ + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "campaign" + }, + "value": { + "$ref": "#/$defs/PipelineCampaign" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "target" + }, + "value": { + "$ref": "#/$defs/PipelineTarget" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "question" + }, + "value": { + "$ref": "#/$defs/PipelineQuestion" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "ruling" + }, + "value": { + "$ref": "#/$defs/PipelineRuling" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "cut_spec" + }, + "value": { + "$ref": "#/$defs/PipelineCutSpec" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "cut_report" + }, + "value": { + "$ref": "#/$defs/PipelineCutReport" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "verdict" + }, + "value": { + "$ref": "#/$defs/PipelineVerdict" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "finding" + }, + "value": { + "$ref": "#/$defs/PipelineFinding" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "follow_up" + }, + "value": { + "$ref": "#/$defs/PipelineFollowUp" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "resolution" + }, + "value": { + "$ref": "#/$defs/PipelineResolution" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "instance" + }, + "value": { + "$ref": "#/$defs/PipelineInstance" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "stewardship" + }, + "value": { + "$ref": "#/$defs/PipelineStewardship" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "hand_off" + }, + "value": { + "$ref": "#/$defs/PipelineHandOff" + } + }, + "required": [ + "kind", + "value" + ] + } + ] + }, + "PipelineFinding": { + "type": "object", + "properties": { + "campaign": { + "$ref": "#/$defs/Slug" + }, + "claim": { + "$ref": "#/$defs/Line" + }, + "confidence": { + "$ref": "#/$defs/FindingConfidence" + }, + "evidence": { + "type": "array", + "items": { + "$ref": "#/$defs/Evidence" + }, + "maxItems": 16 + }, + "failure_scenario": { + "$ref": "#/$defs/Para" + }, + "invariants": { + "type": "array", + "items": { + "$ref": "#/$defs/Label" + }, + "maxItems": 8 + }, + "label": { + "$ref": "#/$defs/Label" + }, + "locations": { + "type": "array", + "items": { + "$ref": "#/$defs/CodeLocation" + }, + "maxItems": 16 + }, + "origin": { + "$ref": "#/$defs/FindingOrigin" + }, + "precedents": { + "type": "array", + "items": { + "$ref": "#/$defs/ForeignRef" + }, + "maxItems": 8 + }, + "range": { + "$ref": "#/$defs/CommitRange" + }, + "severity": { + "$ref": "#/$defs/FindingSeverity" + }, + "verdict": { + "$ref": "#/$defs/Short" + } + }, + "required": [ + "campaign", + "verdict", + "label", + "range", + "confidence", + "severity", + "claim", + "invariants", + "locations", + "failure_scenario", + "evidence", + "precedents", + "origin" + ] + }, + "PipelineFollowUp": { + "type": "object", + "properties": { + "campaign": { + "$ref": "#/$defs/Slug" + }, + "item": { + "$ref": "#/$defs/Line" + }, + "label": { + "$ref": "#/$defs/Label" + }, + "locations": { + "type": "array", + "items": { + "$ref": "#/$defs/CodeLocation" + }, + "maxItems": 16 + }, + "owner": { + "$ref": "#/$defs/Short" + }, + "repo": { + "$ref": "#/$defs/OrgRepo" + }, + "source": { + "$ref": "#/$defs/PipelineRef" + }, + "why_it_can_wait": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "campaign", + "label", + "source", + "repo", + "locations", + "item", + "why_it_can_wait", + "owner" + ] + }, + "PipelineHandOff": { + "description": "A reassignment of stewardship, recorded in both minds. `documents` names\nwhat travels with it.", + "type": "object", + "properties": { + "documents": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 256 + }, + "from_instance": { + "$ref": "#/$defs/Slug" + }, + "handed_on": { + "$ref": "#/$defs/Date" + }, + "reason": { + "$ref": "#/$defs/Para" + }, + "repo": { + "$ref": "#/$defs/OrgRepo" + }, + "to_instance": { + "$ref": "#/$defs/Slug" + } + }, + "required": [ + "from_instance", + "to_instance", + "repo", + "documents", + "reason", + "handed_on" + ] + }, + "PipelineInstance": { + "description": "A mind's identity document. A store is canonical to exactly one\ninstance, and this says which; identity lives in the state, not in a\npath.", + "type": "object", + "properties": { + "created_at": { + "$ref": "#/$defs/Date" + }, + "display_name": { + "$ref": "#/$defs/Short" + }, + "host": { + "$ref": "#/$defs/Short" + }, + "instance": { + "$ref": "#/$defs/Slug" + } + }, + "required": [ + "instance", + "display_name", + "created_at", + "host" + ] + }, + "PipelineKind": { + "type": "string", + "enum": [ + "Campaign", + "Target", + "Question", + "Ruling", + "CutSpec", + "CutReport", + "Verdict", + "Finding", + "FollowUp", + "Resolution", + "Instance", + "Stewardship", + "HandOff" + ] + }, + "PipelineProvenance": { + "description": "Who admitted a batch: the faculty, the agent, its session and the tool.\nA field on the receipt and nothing else; the digest excludes it.", + "type": "object", + "properties": { + "agent": { + "$ref": "#/$defs/Short" + }, + "faculty": { + "$ref": "#/$defs/Faculty" + }, + "session": { + "$ref": "#/$defs/Short" + }, + "tool": { + "$ref": "#/$defs/Short" + } + }, + "required": [ + "faculty", + "agent", + "session", + "tool" + ] + }, + "PipelineQuery": { + "description": "The filters over one mind. Each is one rule, and an unset filter matches\neverything. The mind is the instance, so there is no `instance` field: the\ndaemon picks the mind before it calls here.", + "type": "object", + "properties": { + "admitted_after": { + "description": "Exclusive, compared as a string against `admitted_at`.", + "anyOf": [ + { + "$ref": "#/$defs/Short" + }, + { + "type": "null" + } + ] + }, + "admitted_before": { + "description": "Exclusive, compared as a string against `admitted_at`.", + "anyOf": [ + { + "$ref": "#/$defs/Short" + }, + { + "type": "null" + } + ] + }, + "campaign": { + "description": "The key's root segment: a campaign slug, or an instance for\nstewardships, hand-offs and the identity document.", + "anyOf": [ + { + "$ref": "#/$defs/Slug" + }, + { + "type": "null" + } + ] + }, + "cut": { + "anyOf": [ + { + "$ref": "#/$defs/Label" + }, + { + "type": "null" + } + ] + }, + "faculty": { + "description": "Attribution, ruling 18: it filters, it grants nothing.", + "anyOf": [ + { + "$ref": "#/$defs/Faculty" + }, + { + "type": "null" + } + ] + }, + "in_force": { + "type": [ + "boolean", + "null" + ] + }, + "kinds": { + "description": "Empty matches every kind.", + "type": "array", + "items": { + "$ref": "#/$defs/PipelineKind" + } + }, + "limit": { + "description": "`None` is `QUERY_LIMIT_MAX`; anything else is clamped into\n`1..=QUERY_LIMIT_MAX`.", + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0 + }, + "repo": { + "anyOf": [ + { + "$ref": "#/$defs/OrgRepo" + }, + { + "type": "null" + } + ] + }, + "semantic": { + "anyOf": [ + { + "$ref": "#/$defs/SemanticQuery" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "kinds" + ] + }, + "PipelineQuestion": { + "type": "object", + "properties": { + "asked_on": { + "$ref": "#/$defs/Date" + }, + "campaign": { + "$ref": "#/$defs/Slug" + }, + "depends": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 8 + }, + "label": { + "$ref": "#/$defs/Label" + }, + "options": { + "type": "array", + "items": { + "$ref": "#/$defs/QuestionOption" + }, + "maxItems": 8 + }, + "question": { + "$ref": "#/$defs/Para" + }, + "raised_in": { + "anyOf": [ + { + "$ref": "#/$defs/PipelineRef" + }, + { + "type": "null" + } + ] + }, + "recommended": { + "$ref": "#/$defs/Label" + } + }, + "required": [ + "campaign", + "label", + "question", + "options", + "recommended", + "depends", + "asked_on" + ] + }, + "PipelineRef": { + "description": "A reference to another document. The id is parsed as a full pipeline id of\nthe declared `kind`, so the kind and the id's kind segment cannot disagree.", + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/Short" + }, + "kind": { + "$ref": "#/$defs/PipelineKind" + } + }, + "required": [ + "kind", + "id" + ] + }, + "PipelineResolution": { + "description": "The record of how a subject was closed and by what. `sequence` is per\nsubject and set by the writer, `1` for the first, and it is the last\npart of the key, so a subject's resolutions share a prefix and a\nwithdrawn one is kept under its subject rather than overwritten.\nWhether a sequence is the previous plus one, and whether an earlier\nresolution still stands, are admission's rules: this crate refuses\nneither `0` nor a gap, exactly as it refuses neither `revision: 0` nor\na `revision` with no predecessor.", + "type": "object", + "properties": { + "outcome": { + "$ref": "#/$defs/ResolutionOutcome" + }, + "rationale": { + "$ref": "#/$defs/Para" + }, + "resolved_on": { + "$ref": "#/$defs/Date" + }, + "sequence": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "subject": { + "$ref": "#/$defs/PipelineRef" + } + }, + "required": [ + "subject", + "sequence", + "outcome", + "rationale", + "resolved_on" + ] + }, + "PipelineRuling": { + "type": "object", + "properties": { + "answers": { + "anyOf": [ + { + "$ref": "#/$defs/Short" + }, + { + "type": "null" + } + ] + }, + "authority": { + "$ref": "#/$defs/RulingAuthority" + }, + "campaign": { + "$ref": "#/$defs/Slug" + }, + "choice": { + "anyOf": [ + { + "$ref": "#/$defs/Label" + }, + { + "type": "null" + } + ] + }, + "label": { + "$ref": "#/$defs/Label" + }, + "operator_quote": { + "anyOf": [ + { + "$ref": "#/$defs/Para" + }, + { + "type": "null" + } + ] + }, + "precedents": { + "type": "array", + "items": { + "$ref": "#/$defs/ForeignRef" + }, + "maxItems": 8 + }, + "ruled_on": { + "$ref": "#/$defs/Date" + }, + "ruling": { + "$ref": "#/$defs/Para" + } + }, + "required": [ + "campaign", + "label", + "ruling", + "ruled_on", + "precedents", + "authority" + ] + }, + "PipelineStewardship": { + "description": "Stewardship over a repo, as an assignment recorded in a mind. One\ninstance may steward several repos, so the repo is part of the key.\n`sequence` is per `(instance, repo)`, set by the writer, `1` for the\nfirst, so a repo transferred away and back is two records under one\nprefix rather than one document overwriting the other. `assigned_on`\nis a field, not a key part. As on a resolution, whether the sequence\nis the previous plus one, and which assignment is in force, are\nadmission's rules and not this crate's.", + "type": "object", + "properties": { + "assigned_on": { + "$ref": "#/$defs/Date" + }, + "instance": { + "$ref": "#/$defs/Slug" + }, + "note": { + "$ref": "#/$defs/Line" + }, + "repo": { + "$ref": "#/$defs/OrgRepo" + }, + "sequence": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "instance", + "repo", + "sequence", + "assigned_on", + "note" + ] + }, + "PipelineTarget": { + "type": "object", + "properties": { + "campaign": { + "$ref": "#/$defs/Slug" + }, + "canonical_implementations": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + }, + "doc": { + "$ref": "#/$defs/DocRef" + }, + "invariants": { + "type": "array", + "items": { + "$ref": "#/$defs/TargetInvariant" + }, + "maxItems": 32 + }, + "not_in_scope": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 32 + }, + "revision": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "campaign", + "revision", + "invariants", + "not_in_scope", + "canonical_implementations", + "doc" + ] + }, + "PipelineVerdict": { + "type": "object", + "properties": { + "campaign": { + "$ref": "#/$defs/Slug" + }, + "claims": { + "type": "array", + "items": { + "$ref": "#/$defs/VerdictClaim" + }, + "maxItems": 64 + }, + "cut_report": { + "$ref": "#/$defs/Short" + }, + "pass": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "range": { + "$ref": "#/$defs/CommitRange" + } + }, + "required": [ + "campaign", + "cut_report", + "pass", + "range", + "claims" + ] + }, + "Promise": { + "description": "A promise a report makes about what it landed. Not a document and not\nresolvable: it is identified by its report's id and its label, as a\n`TargetInvariant` is by its target's. Soul measures every one (ruling\nA), and the rule that every one is measured is admission's.", + "type": "object", + "properties": { + "label": { + "$ref": "#/$defs/Label" + }, + "text": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "label", + "text" + ] + }, + "QuestionOption": { + "type": "object", + "properties": { + "label": { + "$ref": "#/$defs/Label" + }, + "text": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "label", + "text" + ] + }, + "ReportCommit": { + "type": "object", + "properties": { + "builds": { + "type": "boolean" + }, + "sha": { + "$ref": "#/$defs/Sha" + }, + "subject": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "sha", + "subject", + "builds" + ] + }, + "ResolutionOutcome": { + "description": "How a subject was resolved. Every referent is a parsed `PipelineRef`, so a\nresolution names its records by ids of the kinds they declare, validated\nwhere every other referent is; a `Fixed` commit is a `Sha` whose referent\nis outside the document set (ruling B). Whether a named document exists,\nand how many may supersede one subject, are admission's rules.", + "oneOf": [ + { + "description": "Overturned, in whole or in part, by later records. The list is bounded\nhere because the enum is outside `value_types!`, the only place a list\nmaximum is emitted automatically.", + "type": "object", + "properties": { + "Superseded": { + "type": "object", + "properties": { + "by": { + "type": "array", + "items": { + "$ref": "#/$defs/PipelineRef" + }, + "maxItems": 8 + } + }, + "required": [ + "by" + ] + } + }, + "additionalProperties": false, + "required": [ + "Superseded" + ] + }, + { + "type": "object", + "properties": { + "Answered": { + "type": "object", + "properties": { + "by": { + "$ref": "#/$defs/PipelineRef" + } + }, + "required": [ + "by" + ] + } + }, + "additionalProperties": false, + "required": [ + "Answered" + ] + }, + { + "type": "object", + "properties": { + "Fixed": { + "type": "object", + "properties": { + "by": { + "anyOf": [ + { + "$ref": "#/$defs/PipelineRef" + }, + { + "type": "null" + } + ] + }, + "commit": { + "$ref": "#/$defs/Sha" + } + }, + "required": [ + "commit" + ] + } + }, + "additionalProperties": false, + "required": [ + "Fixed" + ] + }, + { + "type": "object", + "properties": { + "Deferred": { + "type": "object", + "properties": { + "to": { + "$ref": "#/$defs/PipelineRef" + } + }, + "required": [ + "to" + ] + } + }, + "additionalProperties": false, + "required": [ + "Deferred" + ] + }, + { + "type": "object", + "properties": { + "Recorded": { + "type": "object", + "properties": { + "reason": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "reason" + ] + } + }, + "additionalProperties": false, + "required": [ + "Recorded" + ] + }, + { + "type": "object", + "properties": { + "Withdrawn": { + "type": "object", + "properties": { + "reason": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "reason" + ] + } + }, + "additionalProperties": false, + "required": [ + "Withdrawn" + ] + } + ] + }, + "RulingAuthority": { + "type": "string", + "enum": [ + "Operator", + "Standing", + "Defaulted" + ] + }, + "SemanticQuery": { + "description": "A semantic query, accepted by the type and refused until Cut 11 owns the\nindex. Cut 11 also owns which fields of each kind are text, so no substring\nfilter lives here to become a second answer to that question.", + "type": "object", + "properties": { + "text": { + "$ref": "#/$defs/Line" + }, + "top_k": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "text", + "top_k" + ] + }, + "Sha": { + "description": "A git commit id: 7-40 lowercase hex characters.", + "type": "string", + "maxLength": 40 + }, + "Sha256Hex": { + "description": "A SHA-256 digest: exactly 64 lowercase hex characters.", + "type": "string", + "maxLength": 64 + }, + "Short": { + "description": "Text of at most 200 UTF-8 bytes.", + "type": "string", + "maxLength": 200 + }, + "Slug": { + "description": "A campaign slug or key segment: label parts joined by `.`.", + "type": "string", + "maxLength": 64 + }, + "StructuralDelta": { + "type": "object", + "properties": { + "dependencies_added": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 64 + }, + "dependencies_removed": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 64 + }, + "formats_added": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 64 + }, + "formats_removed": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 64 + }, + "lines_added": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "lines_removed": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "targets_added": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 64 + }, + "targets_removed": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 64 + } + }, + "required": [ + "lines_added", + "lines_removed", + "dependencies_added", + "dependencies_removed", + "formats_added", + "formats_removed", + "targets_added", + "targets_removed" + ] + }, + "TargetInvariant": { + "type": "object", + "properties": { + "label": { + "$ref": "#/$defs/Label" + }, + "statement": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "label", + "statement" + ] + }, + "VerdictClaim": { + "description": "The promise this claim measured, and the report's mutations it ran. An\n`Unproven` claim with a promise is one Soul could not reach.", + "type": "object", + "properties": { + "claim": { + "$ref": "#/$defs/Line" + }, + "evidence": { + "type": "array", + "items": { + "$ref": "#/$defs/Evidence" + }, + "maxItems": 8 + }, + "findings": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 16 + }, + "mutations": { + "type": "array", + "items": { + "$ref": "#/$defs/Label" + }, + "maxItems": 8 + }, + "outcome": { + "$ref": "#/$defs/ClaimOutcome" + }, + "promise": { + "anyOf": [ + { + "$ref": "#/$defs/Label" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "claim", + "outcome", + "evidence", + "findings", + "mutations" + ] + }, + "VerificationTest": { + "type": "object", + "properties": { + "name": { + "$ref": "#/$defs/Short" + }, + "pins": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "name", + "pins" + ] + } + } +} \ No newline at end of file diff --git a/schemas/cultnet/huginn.mind_response.v1.schema.json b/schemas/cultnet/huginn.mind_response.v1.schema.json new file mode 100644 index 0000000..89e5db5 --- /dev/null +++ b/schemas/cultnet/huginn.mind_response.v1.schema.json @@ -0,0 +1,2961 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "HuginnMindResponse", + "description": "Every answer a mind gives. A refusal is data in the response, never a\ntransport failure: the read side carries `Refused`, the write side carries\nthe outcome's own `Refused`.", + "oneOf": [ + { + "type": "object", + "properties": { + "Whoami": { + "$ref": "#/$defs/MindStatus" + } + }, + "additionalProperties": false, + "required": [ + "Whoami" + ] + }, + { + "type": "object", + "properties": { + "Admit": { + "$ref": "#/$defs/PipelineAdmissionOutcome" + } + }, + "additionalProperties": false, + "required": [ + "Admit" + ] + }, + { + "type": "object", + "properties": { + "View": { + "anyOf": [ + { + "$ref": "#/$defs/PipelineDocumentView" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false, + "required": [ + "View" + ] + }, + { + "type": "object", + "properties": { + "Query": { + "$ref": "#/$defs/PipelineQueryPage" + } + }, + "additionalProperties": false, + "required": [ + "Query" + ] + }, + { + "type": "object", + "properties": { + "OpenItems": { + "$ref": "#/$defs/PipelineOpenItems" + } + }, + "additionalProperties": false, + "required": [ + "OpenItems" + ] + }, + { + "type": "object", + "properties": { + "History": { + "type": "array", + "items": { + "$ref": "#/$defs/PipelineDocumentView" + } + } + }, + "additionalProperties": false, + "required": [ + "History" + ] + }, + { + "type": "object", + "properties": { + "Refused": { + "$ref": "#/$defs/MindRefusal" + } + }, + "additionalProperties": false, + "required": [ + "Refused" + ] + } + ], + "$defs": { + "AdmissionFacts": { + "description": "What admission recorded about a document when it landed: the receipt that\nwrote it, the `now` that receipt was taken at, and who asked.", + "type": "object", + "properties": { + "admitted_at": { + "type": "string" + }, + "provenance": { + "$ref": "#/$defs/PipelineProvenance" + }, + "receipt_id": { + "type": "string" + } + }, + "required": [ + "receipt_id", + "admitted_at", + "provenance" + ] + }, + "AuthorityMap": { + "type": "object", + "properties": { + "deletion_line": { + "$ref": "#/$defs/Line" + }, + "derived_state": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + }, + "forbidden_writers": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + }, + "inputs": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + }, + "outputs": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + }, + "owner": { + "$ref": "#/$defs/Line" + }, + "shared_paths": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + } + }, + "required": [ + "owner", + "inputs", + "outputs", + "derived_state", + "forbidden_writers", + "shared_paths", + "deletion_line" + ] + }, + "ClaimOutcome": { + "type": "string", + "enum": [ + "Holds", + "Falsified", + "Unproven" + ] + }, + "CodeLocation": { + "type": "object", + "properties": { + "end_line": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0 + }, + "line": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "path": { + "$ref": "#/$defs/Short" + } + }, + "required": [ + "path", + "line" + ] + }, + "CommitRange": { + "type": "object", + "properties": { + "base": { + "$ref": "#/$defs/Sha" + }, + "head": { + "$ref": "#/$defs/Sha" + } + }, + "required": [ + "base", + "head" + ] + }, + "CutDelete": { + "type": "object", + "properties": { + "lines": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "note": { + "$ref": "#/$defs/Line" + }, + "path": { + "$ref": "#/$defs/Short" + } + }, + "required": [ + "path", + "lines", + "note" + ] + }, + "CutVerification": { + "type": "object", + "properties": { + "builds": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 64 + }, + "negative": { + "type": "array", + "items": { + "$ref": "#/$defs/NegativeCheck" + }, + "maxItems": 64 + }, + "operator": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 64 + }, + "tests": { + "type": "array", + "items": { + "$ref": "#/$defs/VerificationTest" + }, + "maxItems": 64 + } + }, + "required": [ + "builds", + "tests", + "negative", + "operator" + ] + }, + "Date": { + "description": "A calendar date, `YYYY-MM-DD`.", + "type": "string", + "maxLength": 10 + }, + "Deviation": { + "type": "object", + "properties": { + "what": { + "$ref": "#/$defs/Line" + }, + "why": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "what", + "why" + ] + }, + "DocRef": { + "type": "object", + "properties": { + "commit": { + "$ref": "#/$defs/Sha" + }, + "end_line": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "path": { + "$ref": "#/$defs/Short" + }, + "start_line": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "path", + "start_line", + "end_line", + "commit" + ] + }, + "Evidence": { + "type": "object", + "properties": { + "kind": { + "$ref": "#/$defs/EvidenceKind" + }, + "locator": { + "$ref": "#/$defs/Line" + }, + "result": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "kind", + "locator", + "result" + ] + }, + "EvidenceKind": { + "type": "string", + "enum": [ + "Command", + "Test", + "Mutation", + "Probe", + "SourceRead", + "Capture" + ] + }, + "Faculty": { + "description": "Which faculty a batch was admitted as. Attribution, not authority\n(ruling 18): no admission rule trusts it, and Cut 9's views read it back\nfrom the receipt.", + "type": "string", + "enum": [ + "SelfFaculty", + "Imagination", + "Hands", + "Soul", + "MindSteward", + "Eyes", + "Operator" + ] + }, + "FileChange": { + "type": "object", + "properties": { + "change": { + "$ref": "#/$defs/Line" + }, + "location": { + "$ref": "#/$defs/CodeLocation" + } + }, + "required": [ + "location", + "change" + ] + }, + "FindingConfidence": { + "type": "string", + "enum": [ + "Confirmed", + "Plausible" + ] + }, + "FindingOrigin": { + "type": "string", + "enum": [ + "Introduced", + "PreExisting" + ] + }, + "FindingSeverity": { + "type": "string", + "enum": [ + "Blocker", + "High", + "Medium", + "Low" + ] + }, + "ForeignRef": { + "description": "A citation of a document in another repo's pipeline store (D6).", + "type": "object", + "properties": { + "commit": { + "$ref": "#/$defs/FullSha" + }, + "id": { + "$ref": "#/$defs/Short" + }, + "kind": { + "$ref": "#/$defs/PipelineKind" + }, + "payload_sha256": { + "$ref": "#/$defs/Sha256Hex" + }, + "repo": { + "$ref": "#/$defs/OrgRepo" + } + }, + "required": [ + "repo", + "commit", + "kind", + "id", + "payload_sha256" + ] + }, + "FullSha": { + "description": "A full git commit id: exactly 40 lowercase hex characters.", + "type": "string", + "maxLength": 40 + }, + "Label": { + "description": "A key label: `[A-Za-z0-9_-]{1,64}`.", + "type": "string", + "maxLength": 64 + }, + "LandedName": { + "description": "A name the cut landed, and where it lives.", + "type": "object", + "properties": { + "name": { + "$ref": "#/$defs/Short" + }, + "path": { + "$ref": "#/$defs/Short" + } + }, + "required": [ + "name", + "path" + ] + }, + "Line": { + "description": "Text of at most 1,000 UTF-8 bytes.", + "type": "string", + "maxLength": 1000 + }, + "MindRefusal": { + "description": "Every way a mind refuses. `Document` wraps the leaf's four (bounds,\nformats, key identity, foreign type); the rest are the organ's: store\nidentity, epoch, ownership, batch shape, references, and every cross-field\nand cross-document rule of admission.\n\nThe two sequenced kinds refuse in the same pair of shapes: an\n`OutOfSequence` when the writer's `sequence` is not the previous plus one,\nand `AlreadyResolved`/`AlreadyStewarded` when a record of that scope is\nstill in force.", + "oneOf": [ + { + "type": "string", + "enum": [ + "MissingIdentity", + "EmptySupersession", + "FindingWithoutRange", + "FindingWithoutEvidence" + ] + }, + { + "type": "object", + "properties": { + "Document": { + "$ref": "#/$defs/PipelineRefusal" + } + }, + "additionalProperties": false, + "required": [ + "Document" + ] + }, + { + "type": "object", + "properties": { + "ForeignInstance": { + "type": "object", + "properties": { + "declared": { + "type": "string" + }, + "mind": { + "type": "string" + } + }, + "required": [ + "declared", + "mind" + ] + } + }, + "additionalProperties": false, + "required": [ + "ForeignInstance" + ] + }, + { + "type": "object", + "properties": { + "ForeignEpoch": { + "type": "object", + "properties": { + "expected": { + "type": "string" + }, + "found": { + "type": "string" + } + }, + "required": [ + "found", + "expected" + ] + } + }, + "additionalProperties": false, + "required": [ + "ForeignEpoch" + ] + }, + { + "type": "object", + "properties": { + "ForeignStore": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + }, + "additionalProperties": false, + "required": [ + "ForeignStore" + ] + }, + { + "type": "object", + "properties": { + "MindAlreadyOwned": { + "type": "object", + "properties": { + "path": { + "type": "string" + } + }, + "required": [ + "path" + ] + } + }, + "additionalProperties": false, + "required": [ + "MindAlreadyOwned" + ] + }, + { + "type": "object", + "properties": { + "BatchSize": { + "type": "object", + "properties": { + "actual": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "actual" + ] + } + }, + "additionalProperties": false, + "required": [ + "BatchSize" + ] + }, + { + "type": "object", + "properties": { + "IdentityCollision": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "kind": { + "$ref": "#/$defs/PipelineKind" + } + }, + "required": [ + "kind", + "id" + ] + } + }, + "additionalProperties": false, + "required": [ + "IdentityCollision" + ] + }, + { + "type": "object", + "properties": { + "MissingReference": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "kind": { + "$ref": "#/$defs/PipelineKind" + } + }, + "required": [ + "kind", + "id" + ] + } + }, + "additionalProperties": false, + "required": [ + "MissingReference" + ] + }, + { + "type": "object", + "properties": { + "AlreadyResolved": { + "type": "object", + "properties": { + "subject": { + "type": "string" + } + }, + "required": [ + "subject" + ] + } + }, + "additionalProperties": false, + "required": [ + "AlreadyResolved" + ] + }, + { + "type": "object", + "properties": { + "ResolutionOutOfSequence": { + "type": "object", + "properties": { + "actual": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "expected": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "subject": { + "type": "string" + } + }, + "required": [ + "subject", + "expected", + "actual" + ] + } + }, + "additionalProperties": false, + "required": [ + "ResolutionOutOfSequence" + ] + }, + { + "type": "object", + "properties": { + "AlreadyStewarded": { + "type": "object", + "properties": { + "repo": { + "type": "string" + } + }, + "required": [ + "repo" + ] + } + }, + "additionalProperties": false, + "required": [ + "AlreadyStewarded" + ] + }, + { + "type": "object", + "properties": { + "StewardshipOutOfSequence": { + "type": "object", + "properties": { + "actual": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "expected": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "repo": { + "type": "string" + } + }, + "required": [ + "repo", + "expected", + "actual" + ] + } + }, + "additionalProperties": false, + "required": [ + "StewardshipOutOfSequence" + ] + }, + { + "type": "object", + "properties": { + "IncompatibleResolution": { + "type": "object", + "properties": { + "outcome": { + "type": "string" + }, + "subject_kind": { + "$ref": "#/$defs/PipelineKind" + } + }, + "required": [ + "subject_kind", + "outcome" + ] + } + }, + "additionalProperties": false, + "required": [ + "IncompatibleResolution" + ] + }, + { + "type": "object", + "properties": { + "WouldReinstateOverLater": { + "type": "object", + "properties": { + "later": { + "type": "string" + }, + "subject": { + "type": "string" + } + }, + "required": [ + "subject", + "later" + ] + } + }, + "additionalProperties": false, + "required": [ + "WouldReinstateOverLater" + ] + }, + { + "type": "object", + "properties": { + "CitesResolvedDocument": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "kind": { + "$ref": "#/$defs/PipelineKind" + } + }, + "required": [ + "kind", + "id" + ] + } + }, + "additionalProperties": false, + "required": [ + "CitesResolvedDocument" + ] + }, + { + "type": "object", + "properties": { + "UnknownSupersessor": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "required": [ + "id" + ] + } + }, + "additionalProperties": false, + "required": [ + "UnknownSupersessor" + ] + }, + { + "type": "object", + "properties": { + "RevisionWithoutSupersession": { + "type": "object", + "properties": { + "kind": { + "$ref": "#/$defs/PipelineKind" + }, + "revision": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "kind", + "revision" + ] + } + }, + "additionalProperties": false, + "required": [ + "RevisionWithoutSupersession" + ] + }, + { + "type": "object", + "properties": { + "DuplicateLabel": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "label": { + "type": "string" + } + }, + "required": [ + "field", + "label" + ] + } + }, + "additionalProperties": false, + "required": [ + "DuplicateLabel" + ] + }, + { + "type": "object", + "properties": { + "InvalidOptions": { + "type": "object", + "properties": { + "question": { + "type": "string" + } + }, + "required": [ + "question" + ] + } + }, + "additionalProperties": false, + "required": [ + "InvalidOptions" + ] + }, + { + "type": "object", + "properties": { + "InvalidChoice": { + "type": "object", + "properties": { + "choice": { + "type": "string" + }, + "ruling": { + "type": "string" + } + }, + "required": [ + "ruling", + "choice" + ] + } + }, + "additionalProperties": false, + "required": [ + "InvalidChoice" + ] + }, + { + "type": "object", + "properties": { + "QuoteWithoutOperator": { + "type": "object", + "properties": { + "ruling": { + "type": "string" + } + }, + "required": [ + "ruling" + ] + } + }, + "additionalProperties": false, + "required": [ + "QuoteWithoutOperator" + ] + }, + { + "type": "object", + "properties": { + "EmptyRepos": { + "type": "object", + "properties": { + "campaign": { + "type": "string" + } + }, + "required": [ + "campaign" + ] + } + }, + "additionalProperties": false, + "required": [ + "EmptyRepos" + ] + }, + { + "type": "object", + "properties": { + "RepoNotStewarded": { + "type": "object", + "properties": { + "repo": { + "type": "string" + } + }, + "required": [ + "repo" + ] + } + }, + "additionalProperties": false, + "required": [ + "RepoNotStewarded" + ] + }, + { + "type": "object", + "properties": { + "RepoNotInCampaign": { + "type": "object", + "properties": { + "repo": { + "type": "string" + } + }, + "required": [ + "repo" + ] + } + }, + "additionalProperties": false, + "required": [ + "RepoNotInCampaign" + ] + }, + { + "type": "object", + "properties": { + "CutReportWithoutSpec": { + "type": "object", + "properties": { + "report": { + "type": "string" + } + }, + "required": [ + "report" + ] + } + }, + "additionalProperties": false, + "required": [ + "CutReportWithoutSpec" + ] + }, + { + "type": "object", + "properties": { + "SpecMismatch": { + "type": "object", + "properties": { + "field": { + "type": "string" + } + }, + "required": [ + "field" + ] + } + }, + "additionalProperties": false, + "required": [ + "SpecMismatch" + ] + }, + { + "type": "object", + "properties": { + "RangeOutsideCommits": { + "type": "object", + "properties": { + "head": { + "type": "string" + } + }, + "required": [ + "head" + ] + } + }, + "additionalProperties": false, + "required": [ + "RangeOutsideCommits" + ] + }, + { + "type": "object", + "properties": { + "FalsifiedClaimWithoutConfirmedFinding": { + "type": "object", + "properties": { + "claim": { + "type": "string" + } + }, + "required": [ + "claim" + ] + } + }, + "additionalProperties": false, + "required": [ + "FalsifiedClaimWithoutConfirmedFinding" + ] + }, + { + "type": "object", + "properties": { + "UnprovenClaimWithConfirmedFinding": { + "type": "object", + "properties": { + "claim": { + "type": "string" + } + }, + "required": [ + "claim" + ] + } + }, + "additionalProperties": false, + "required": [ + "UnprovenClaimWithConfirmedFinding" + ] + }, + { + "type": "object", + "properties": { + "PromiseWithoutVerdict": { + "type": "object", + "properties": { + "promise": { + "type": "string" + } + }, + "required": [ + "promise" + ] + } + }, + "additionalProperties": false, + "required": [ + "PromiseWithoutVerdict" + ] + }, + { + "type": "object", + "properties": { + "UnknownMutationLabel": { + "type": "object", + "properties": { + "label": { + "type": "string" + } + }, + "required": [ + "label" + ] + } + }, + "additionalProperties": false, + "required": [ + "UnknownMutationLabel" + ] + }, + { + "type": "object", + "properties": { + "UnknownInvariant": { + "type": "object", + "properties": { + "label": { + "type": "string" + } + }, + "required": [ + "label" + ] + } + }, + "additionalProperties": false, + "required": [ + "UnknownInvariant" + ] + }, + { + "type": "object", + "properties": { + "NotStewarded": { + "type": "object", + "properties": { + "repo": { + "type": "string" + } + }, + "required": [ + "repo" + ] + } + }, + "additionalProperties": false, + "required": [ + "NotStewarded" + ] + }, + { + "type": "object", + "properties": { + "Unavailable": { + "type": "object", + "properties": { + "detail": { + "type": "string" + } + }, + "required": [ + "detail" + ] + } + }, + "additionalProperties": false, + "required": [ + "Unavailable" + ] + } + ] + }, + "MindStatus": { + "description": "What a mind says about itself: the typed state a dashboard projects.", + "type": "object", + "properties": { + "documents": { + "description": "Pipeline documents in the image; the epoch record and the receipts are\nnot documents and are not counted here.", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "instance": { + "$ref": "#/$defs/Slug" + }, + "receipts": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "schema_epoch": { + "type": "string" + } + }, + "required": [ + "instance", + "schema_epoch", + "documents", + "receipts" + ] + }, + "MutationRecord": { + "description": "One mutation a report ran: a key-safe label a verdict claim can name,\nthe exact edit, and the tree it was applied to.", + "type": "object", + "properties": { + "after": { + "$ref": "#/$defs/Line" + }, + "before": { + "$ref": "#/$defs/Line" + }, + "commit": { + "$ref": "#/$defs/Sha" + }, + "failed_as_expected": { + "type": "boolean" + }, + "label": { + "$ref": "#/$defs/Label" + }, + "location": { + "$ref": "#/$defs/CodeLocation" + }, + "rule": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "label", + "rule", + "location", + "before", + "after", + "commit", + "failed_as_expected" + ] + }, + "NegativeCheck": { + "type": "object", + "properties": { + "pattern": { + "$ref": "#/$defs/Short" + }, + "scope": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "pattern", + "scope" + ] + }, + "OrgRepo": { + "description": "A GitHub repository as `Org/Repo`.", + "type": "string", + "maxLength": 200 + }, + "Para": { + "description": "Text of at most 4,000 UTF-8 bytes; longer narrative is cited by `DocRef`.", + "type": "string", + "maxLength": 4000 + }, + "PipelineAdmissionOutcome": { + "description": "How admission ended. `Committed.writes` names every document the batch\nlanded, derived writes included; Cut 11 indexes from it after `admit`\nreturns, and never inside it.", + "oneOf": [ + { + "type": "object", + "properties": { + "Committed": { + "type": "object", + "properties": { + "committed_at": { + "type": "string" + }, + "receipt_id": { + "type": "string" + }, + "writes": { + "type": "array", + "items": { + "$ref": "#/$defs/PipelineRef" + } + } + }, + "required": [ + "receipt_id", + "committed_at", + "writes" + ] + } + }, + "additionalProperties": false, + "required": [ + "Committed" + ] + }, + { + "type": "object", + "properties": { + "AlreadyAdmitted": { + "type": "object", + "properties": { + "receipt_id": { + "type": "string" + } + }, + "required": [ + "receipt_id" + ] + } + }, + "additionalProperties": false, + "required": [ + "AlreadyAdmitted" + ] + }, + { + "type": "object", + "properties": { + "Refused": { + "$ref": "#/$defs/MindRefusal" + } + }, + "additionalProperties": false, + "required": [ + "Refused" + ] + }, + { + "type": "object", + "properties": { + "Conflict": { + "type": "object", + "properties": { + "identities": { + "type": "array", + "items": { + "$ref": "#/$defs/PipelineRef" + } + } + }, + "required": [ + "identities" + ] + } + }, + "additionalProperties": false, + "required": [ + "Conflict" + ] + } + ] + }, + "PipelineCampaign": { + "type": "object", + "properties": { + "repos": { + "type": "array", + "items": { + "$ref": "#/$defs/OrgRepo" + }, + "maxItems": 8 + }, + "slug": { + "$ref": "#/$defs/Slug" + }, + "target_doc": { + "$ref": "#/$defs/DocRef" + }, + "title": { + "$ref": "#/$defs/Short" + }, + "working_branch": { + "$ref": "#/$defs/Short" + } + }, + "required": [ + "slug", + "title", + "repos", + "working_branch", + "target_doc" + ] + }, + "PipelineCutReport": { + "type": "object", + "properties": { + "attempt": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "branch": { + "$ref": "#/$defs/Short" + }, + "campaign": { + "$ref": "#/$defs/Slug" + }, + "commits": { + "type": "array", + "items": { + "$ref": "#/$defs/ReportCommit" + }, + "maxItems": 128 + }, + "cut_spec": { + "$ref": "#/$defs/Short" + }, + "deviations": { + "type": "array", + "items": { + "$ref": "#/$defs/Deviation" + }, + "maxItems": 32 + }, + "forks": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 8 + }, + "landed_names": { + "type": "array", + "items": { + "$ref": "#/$defs/LandedName" + }, + "maxItems": 128 + }, + "mutations": { + "type": "array", + "items": { + "$ref": "#/$defs/MutationRecord" + }, + "maxItems": 64 + }, + "promises": { + "type": "array", + "items": { + "$ref": "#/$defs/Promise" + }, + "maxItems": 64 + }, + "range": { + "$ref": "#/$defs/CommitRange" + }, + "repo": { + "$ref": "#/$defs/OrgRepo" + }, + "structural_delta": { + "$ref": "#/$defs/StructuralDelta" + }, + "undone": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 32 + }, + "verification": { + "type": "array", + "items": { + "$ref": "#/$defs/Evidence" + }, + "maxItems": 64 + } + }, + "required": [ + "campaign", + "cut_spec", + "attempt", + "repo", + "branch", + "commits", + "range", + "verification", + "mutations", + "deviations", + "forks", + "structural_delta", + "landed_names", + "undone", + "promises" + ] + }, + "PipelineCutSpec": { + "type": "object", + "properties": { + "adds": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 64 + }, + "authority_map": { + "anyOf": [ + { + "$ref": "#/$defs/AuthorityMap" + }, + { + "type": "null" + } + ] + }, + "base": { + "$ref": "#/$defs/Sha" + }, + "branch": { + "$ref": "#/$defs/Short" + }, + "campaign": { + "$ref": "#/$defs/Slug" + }, + "cut": { + "$ref": "#/$defs/Label" + }, + "deletes": { + "type": "array", + "items": { + "$ref": "#/$defs/CutDelete" + }, + "maxItems": 64 + }, + "depends_on": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 8 + }, + "estimate": { + "$ref": "#/$defs/StructuralDelta" + }, + "file_changes": { + "type": "array", + "items": { + "$ref": "#/$defs/FileChange" + }, + "maxItems": 256 + }, + "first": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + }, + "keeps_moves": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 64 + }, + "questions": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 16 + }, + "repo": { + "$ref": "#/$defs/OrgRepo" + }, + "revision": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "rulings": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 32 + }, + "title": { + "$ref": "#/$defs/Short" + }, + "verification": { + "$ref": "#/$defs/CutVerification" + } + }, + "required": [ + "campaign", + "cut", + "revision", + "title", + "repo", + "branch", + "base", + "depends_on", + "first", + "deletes", + "keeps_moves", + "adds", + "file_changes", + "verification", + "estimate", + "rulings", + "questions" + ] + }, + "PipelineDocument": { + "description": "The envelope enum, adjacently tagged on the kind name: a document\non a wire is `{ kind, value }`, and `kind` is exactly what\n`PipelineKind::name()` returns, so a reader dispatches on the kind\nsegment it already knows from the key and needs no second registry\nmapping variant spellings to kinds. Adjacent rather than internal\nbecause a value is a named map of its own and an internal tag would\nhave to be merged into it; the tag stays beside the value instead.\nThis is not a published schema: `schemas/cultnet` publishes the\nthirteen per-kind value documents, and the envelope is the wire's\nshape, not a document's.", + "oneOf": [ + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "campaign" + }, + "value": { + "$ref": "#/$defs/PipelineCampaign" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "target" + }, + "value": { + "$ref": "#/$defs/PipelineTarget" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "question" + }, + "value": { + "$ref": "#/$defs/PipelineQuestion" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "ruling" + }, + "value": { + "$ref": "#/$defs/PipelineRuling" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "cut_spec" + }, + "value": { + "$ref": "#/$defs/PipelineCutSpec" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "cut_report" + }, + "value": { + "$ref": "#/$defs/PipelineCutReport" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "verdict" + }, + "value": { + "$ref": "#/$defs/PipelineVerdict" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "finding" + }, + "value": { + "$ref": "#/$defs/PipelineFinding" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "follow_up" + }, + "value": { + "$ref": "#/$defs/PipelineFollowUp" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "resolution" + }, + "value": { + "$ref": "#/$defs/PipelineResolution" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "instance" + }, + "value": { + "$ref": "#/$defs/PipelineInstance" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "stewardship" + }, + "value": { + "$ref": "#/$defs/PipelineStewardship" + } + }, + "required": [ + "kind", + "value" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "hand_off" + }, + "value": { + "$ref": "#/$defs/PipelineHandOff" + } + }, + "required": [ + "kind", + "value" + ] + } + ] + }, + "PipelineDocumentView": { + "description": "One document as a reader gets it: its id, the document, the facts of its\nadmission and its status. The id travels with the document because a\n`PipelineDocument` does not carry its key and a client must never derive\none.", + "type": "object", + "properties": { + "admission": { + "$ref": "#/$defs/AdmissionFacts" + }, + "document": { + "$ref": "#/$defs/PipelineDocument" + }, + "id": { + "$ref": "#/$defs/PipelineRef" + }, + "status": { + "$ref": "#/$defs/PipelineStatus" + } + }, + "required": [ + "id", + "document", + "admission", + "status" + ] + }, + "PipelineFinding": { + "type": "object", + "properties": { + "campaign": { + "$ref": "#/$defs/Slug" + }, + "claim": { + "$ref": "#/$defs/Line" + }, + "confidence": { + "$ref": "#/$defs/FindingConfidence" + }, + "evidence": { + "type": "array", + "items": { + "$ref": "#/$defs/Evidence" + }, + "maxItems": 16 + }, + "failure_scenario": { + "$ref": "#/$defs/Para" + }, + "invariants": { + "type": "array", + "items": { + "$ref": "#/$defs/Label" + }, + "maxItems": 8 + }, + "label": { + "$ref": "#/$defs/Label" + }, + "locations": { + "type": "array", + "items": { + "$ref": "#/$defs/CodeLocation" + }, + "maxItems": 16 + }, + "origin": { + "$ref": "#/$defs/FindingOrigin" + }, + "precedents": { + "type": "array", + "items": { + "$ref": "#/$defs/ForeignRef" + }, + "maxItems": 8 + }, + "range": { + "$ref": "#/$defs/CommitRange" + }, + "severity": { + "$ref": "#/$defs/FindingSeverity" + }, + "verdict": { + "$ref": "#/$defs/Short" + } + }, + "required": [ + "campaign", + "verdict", + "label", + "range", + "confidence", + "severity", + "claim", + "invariants", + "locations", + "failure_scenario", + "evidence", + "precedents", + "origin" + ] + }, + "PipelineFollowUp": { + "type": "object", + "properties": { + "campaign": { + "$ref": "#/$defs/Slug" + }, + "item": { + "$ref": "#/$defs/Line" + }, + "label": { + "$ref": "#/$defs/Label" + }, + "locations": { + "type": "array", + "items": { + "$ref": "#/$defs/CodeLocation" + }, + "maxItems": 16 + }, + "owner": { + "$ref": "#/$defs/Short" + }, + "repo": { + "$ref": "#/$defs/OrgRepo" + }, + "source": { + "$ref": "#/$defs/PipelineRef" + }, + "why_it_can_wait": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "campaign", + "label", + "source", + "repo", + "locations", + "item", + "why_it_can_wait", + "owner" + ] + }, + "PipelineHandOff": { + "description": "A reassignment of stewardship, recorded in both minds. `documents` names\nwhat travels with it.", + "type": "object", + "properties": { + "documents": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 256 + }, + "from_instance": { + "$ref": "#/$defs/Slug" + }, + "handed_on": { + "$ref": "#/$defs/Date" + }, + "reason": { + "$ref": "#/$defs/Para" + }, + "repo": { + "$ref": "#/$defs/OrgRepo" + }, + "to_instance": { + "$ref": "#/$defs/Slug" + } + }, + "required": [ + "from_instance", + "to_instance", + "repo", + "documents", + "reason", + "handed_on" + ] + }, + "PipelineInstance": { + "description": "A mind's identity document. A store is canonical to exactly one\ninstance, and this says which; identity lives in the state, not in a\npath.", + "type": "object", + "properties": { + "created_at": { + "$ref": "#/$defs/Date" + }, + "display_name": { + "$ref": "#/$defs/Short" + }, + "host": { + "$ref": "#/$defs/Short" + }, + "instance": { + "$ref": "#/$defs/Slug" + } + }, + "required": [ + "instance", + "display_name", + "created_at", + "host" + ] + }, + "PipelineKind": { + "type": "string", + "enum": [ + "Campaign", + "Target", + "Question", + "Ruling", + "CutSpec", + "CutReport", + "Verdict", + "Finding", + "FollowUp", + "Resolution", + "Instance", + "Stewardship", + "HandOff" + ] + }, + "PipelineOpenItems": { + "description": "One campaign's open work, derived from what is in force and what cites\nwhat. Uncapped: the open set of a campaign is bounded by the campaign, and\ntruncating it would hide work.", + "type": "object", + "properties": { + "findings": { + "type": "array", + "items": { + "$ref": "#/$defs/PipelineDocumentView" + } + }, + "follow_ups": { + "type": "array", + "items": { + "$ref": "#/$defs/PipelineDocumentView" + } + }, + "questions": { + "type": "array", + "items": { + "$ref": "#/$defs/PipelineDocumentView" + } + }, + "reports_without_verdict": { + "type": "array", + "items": { + "$ref": "#/$defs/PipelineDocumentView" + } + }, + "specs_without_report": { + "type": "array", + "items": { + "$ref": "#/$defs/PipelineDocumentView" + } + } + }, + "required": [ + "questions", + "findings", + "follow_ups", + "specs_without_report", + "reports_without_verdict" + ] + }, + "PipelineProvenance": { + "description": "Who admitted a batch: the faculty, the agent, its session and the tool.\nA field on the receipt and nothing else; the digest excludes it.", + "type": "object", + "properties": { + "agent": { + "$ref": "#/$defs/Short" + }, + "faculty": { + "$ref": "#/$defs/Faculty" + }, + "session": { + "$ref": "#/$defs/Short" + }, + "tool": { + "$ref": "#/$defs/Short" + } + }, + "required": [ + "faculty", + "agent", + "session", + "tool" + ] + }, + "PipelineQueryPage": { + "description": "One page of a query, with the number of documents that matched before the\ncap, so a short page is never mistaken for the whole answer.", + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/$defs/PipelineDocumentView" + } + }, + "matched": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "items", + "matched" + ] + }, + "PipelineQuestion": { + "type": "object", + "properties": { + "asked_on": { + "$ref": "#/$defs/Date" + }, + "campaign": { + "$ref": "#/$defs/Slug" + }, + "depends": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 8 + }, + "label": { + "$ref": "#/$defs/Label" + }, + "options": { + "type": "array", + "items": { + "$ref": "#/$defs/QuestionOption" + }, + "maxItems": 8 + }, + "question": { + "$ref": "#/$defs/Para" + }, + "raised_in": { + "anyOf": [ + { + "$ref": "#/$defs/PipelineRef" + }, + { + "type": "null" + } + ] + }, + "recommended": { + "$ref": "#/$defs/Label" + } + }, + "required": [ + "campaign", + "label", + "question", + "options", + "recommended", + "depends", + "asked_on" + ] + }, + "PipelineRef": { + "description": "A reference to another document. The id is parsed as a full pipeline id of\nthe declared `kind`, so the kind and the id's kind segment cannot disagree.", + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/Short" + }, + "kind": { + "$ref": "#/$defs/PipelineKind" + } + }, + "required": [ + "kind", + "id" + ] + }, + "PipelineRefusal": { + "description": "Typed refusals of the pipeline documents: bounds, formats and key identity\n(D2's document half), and `ForeignStore`, raised by `decode` for an\nenvelope of any other type. This is every refusal the leaf decides; a\nstore's identity and its schema epoch are not decided here, since this\ncrate owns no store, and belong to the organ that will admit these\ndocuments.\n\nSerialised externally tagged, serde's default for an enum: each variant is\na one-key map from the variant's name to its named fields, so `field` and\n`value` are on the wire under their own names and a reader of a refusal\ncarried over a wire reads the same parts a local caller matches on. No\nattribute buys that, which is why there is none: an internal or adjacent\ntag would move the fields under a content key without making any of them\nmore visible.", + "oneOf": [ + { + "type": "object", + "properties": { + "FieldBound": { + "type": "object", + "properties": { + "actual": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "field": { + "type": "string" + }, + "limit": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "field", + "limit", + "actual" + ] + } + }, + "additionalProperties": false, + "required": [ + "FieldBound" + ] + }, + { + "type": "object", + "properties": { + "InvalidFormat": { + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "field", + "value" + ] + } + }, + "additionalProperties": false, + "required": [ + "InvalidFormat" + ] + }, + { + "type": "object", + "properties": { + "InvalidIdentity": { + "type": "object", + "properties": { + "expected": { + "type": "string" + }, + "key": { + "type": "string" + }, + "kind": { + "$ref": "#/$defs/PipelineKind" + } + }, + "required": [ + "kind", + "key", + "expected" + ] + } + }, + "additionalProperties": false, + "required": [ + "InvalidIdentity" + ] + }, + { + "type": "object", + "properties": { + "ForeignStore": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + }, + "additionalProperties": false, + "required": [ + "ForeignStore" + ] + } + ] + }, + "PipelineResolution": { + "description": "The record of how a subject was closed and by what. `sequence` is per\nsubject and set by the writer, `1` for the first, and it is the last\npart of the key, so a subject's resolutions share a prefix and a\nwithdrawn one is kept under its subject rather than overwritten.\nWhether a sequence is the previous plus one, and whether an earlier\nresolution still stands, are admission's rules: this crate refuses\nneither `0` nor a gap, exactly as it refuses neither `revision: 0` nor\na `revision` with no predecessor.", + "type": "object", + "properties": { + "outcome": { + "$ref": "#/$defs/ResolutionOutcome" + }, + "rationale": { + "$ref": "#/$defs/Para" + }, + "resolved_on": { + "$ref": "#/$defs/Date" + }, + "sequence": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "subject": { + "$ref": "#/$defs/PipelineRef" + } + }, + "required": [ + "subject", + "sequence", + "outcome", + "rationale", + "resolved_on" + ] + }, + "PipelineRuling": { + "type": "object", + "properties": { + "answers": { + "anyOf": [ + { + "$ref": "#/$defs/Short" + }, + { + "type": "null" + } + ] + }, + "authority": { + "$ref": "#/$defs/RulingAuthority" + }, + "campaign": { + "$ref": "#/$defs/Slug" + }, + "choice": { + "anyOf": [ + { + "$ref": "#/$defs/Label" + }, + { + "type": "null" + } + ] + }, + "label": { + "$ref": "#/$defs/Label" + }, + "operator_quote": { + "anyOf": [ + { + "$ref": "#/$defs/Para" + }, + { + "type": "null" + } + ] + }, + "precedents": { + "type": "array", + "items": { + "$ref": "#/$defs/ForeignRef" + }, + "maxItems": 8 + }, + "ruled_on": { + "$ref": "#/$defs/Date" + }, + "ruling": { + "$ref": "#/$defs/Para" + } + }, + "required": [ + "campaign", + "label", + "ruling", + "ruled_on", + "precedents", + "authority" + ] + }, + "PipelineStatus": { + "description": "Whether a document still stands, and if not, what closed it. Derived at\nread time; no document carries a status field and no admission writes one.\nThe whole closing record travels, not only its outcome, because a reader\nrehydrating wants why.", + "oneOf": [ + { + "type": "string", + "enum": [ + "InForce" + ] + }, + { + "type": "object", + "properties": { + "Resolved": { + "type": "object", + "properties": { + "record": { + "$ref": "#/$defs/PipelineResolution" + }, + "resolution": { + "$ref": "#/$defs/PipelineRef" + } + }, + "required": [ + "resolution", + "record" + ] + } + }, + "additionalProperties": false, + "required": [ + "Resolved" + ] + } + ] + }, + "PipelineStewardship": { + "description": "Stewardship over a repo, as an assignment recorded in a mind. One\ninstance may steward several repos, so the repo is part of the key.\n`sequence` is per `(instance, repo)`, set by the writer, `1` for the\nfirst, so a repo transferred away and back is two records under one\nprefix rather than one document overwriting the other. `assigned_on`\nis a field, not a key part. As on a resolution, whether the sequence\nis the previous plus one, and which assignment is in force, are\nadmission's rules and not this crate's.", + "type": "object", + "properties": { + "assigned_on": { + "$ref": "#/$defs/Date" + }, + "instance": { + "$ref": "#/$defs/Slug" + }, + "note": { + "$ref": "#/$defs/Line" + }, + "repo": { + "$ref": "#/$defs/OrgRepo" + }, + "sequence": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "instance", + "repo", + "sequence", + "assigned_on", + "note" + ] + }, + "PipelineTarget": { + "type": "object", + "properties": { + "campaign": { + "$ref": "#/$defs/Slug" + }, + "canonical_implementations": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 16 + }, + "doc": { + "$ref": "#/$defs/DocRef" + }, + "invariants": { + "type": "array", + "items": { + "$ref": "#/$defs/TargetInvariant" + }, + "maxItems": 32 + }, + "not_in_scope": { + "type": "array", + "items": { + "$ref": "#/$defs/Line" + }, + "maxItems": 32 + }, + "revision": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "campaign", + "revision", + "invariants", + "not_in_scope", + "canonical_implementations", + "doc" + ] + }, + "PipelineVerdict": { + "type": "object", + "properties": { + "campaign": { + "$ref": "#/$defs/Slug" + }, + "claims": { + "type": "array", + "items": { + "$ref": "#/$defs/VerdictClaim" + }, + "maxItems": 64 + }, + "cut_report": { + "$ref": "#/$defs/Short" + }, + "pass": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "range": { + "$ref": "#/$defs/CommitRange" + } + }, + "required": [ + "campaign", + "cut_report", + "pass", + "range", + "claims" + ] + }, + "Promise": { + "description": "A promise a report makes about what it landed. Not a document and not\nresolvable: it is identified by its report's id and its label, as a\n`TargetInvariant` is by its target's. Soul measures every one (ruling\nA), and the rule that every one is measured is admission's.", + "type": "object", + "properties": { + "label": { + "$ref": "#/$defs/Label" + }, + "text": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "label", + "text" + ] + }, + "QuestionOption": { + "type": "object", + "properties": { + "label": { + "$ref": "#/$defs/Label" + }, + "text": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "label", + "text" + ] + }, + "ReportCommit": { + "type": "object", + "properties": { + "builds": { + "type": "boolean" + }, + "sha": { + "$ref": "#/$defs/Sha" + }, + "subject": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "sha", + "subject", + "builds" + ] + }, + "ResolutionOutcome": { + "description": "How a subject was resolved. Every referent is a parsed `PipelineRef`, so a\nresolution names its records by ids of the kinds they declare, validated\nwhere every other referent is; a `Fixed` commit is a `Sha` whose referent\nis outside the document set (ruling B). Whether a named document exists,\nand how many may supersede one subject, are admission's rules.", + "oneOf": [ + { + "description": "Overturned, in whole or in part, by later records. The list is bounded\nhere because the enum is outside `value_types!`, the only place a list\nmaximum is emitted automatically.", + "type": "object", + "properties": { + "Superseded": { + "type": "object", + "properties": { + "by": { + "type": "array", + "items": { + "$ref": "#/$defs/PipelineRef" + }, + "maxItems": 8 + } + }, + "required": [ + "by" + ] + } + }, + "additionalProperties": false, + "required": [ + "Superseded" + ] + }, + { + "type": "object", + "properties": { + "Answered": { + "type": "object", + "properties": { + "by": { + "$ref": "#/$defs/PipelineRef" + } + }, + "required": [ + "by" + ] + } + }, + "additionalProperties": false, + "required": [ + "Answered" + ] + }, + { + "type": "object", + "properties": { + "Fixed": { + "type": "object", + "properties": { + "by": { + "anyOf": [ + { + "$ref": "#/$defs/PipelineRef" + }, + { + "type": "null" + } + ] + }, + "commit": { + "$ref": "#/$defs/Sha" + } + }, + "required": [ + "commit" + ] + } + }, + "additionalProperties": false, + "required": [ + "Fixed" + ] + }, + { + "type": "object", + "properties": { + "Deferred": { + "type": "object", + "properties": { + "to": { + "$ref": "#/$defs/PipelineRef" + } + }, + "required": [ + "to" + ] + } + }, + "additionalProperties": false, + "required": [ + "Deferred" + ] + }, + { + "type": "object", + "properties": { + "Recorded": { + "type": "object", + "properties": { + "reason": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "reason" + ] + } + }, + "additionalProperties": false, + "required": [ + "Recorded" + ] + }, + { + "type": "object", + "properties": { + "Withdrawn": { + "type": "object", + "properties": { + "reason": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "reason" + ] + } + }, + "additionalProperties": false, + "required": [ + "Withdrawn" + ] + } + ] + }, + "RulingAuthority": { + "type": "string", + "enum": [ + "Operator", + "Standing", + "Defaulted" + ] + }, + "Sha": { + "description": "A git commit id: 7-40 lowercase hex characters.", + "type": "string", + "maxLength": 40 + }, + "Sha256Hex": { + "description": "A SHA-256 digest: exactly 64 lowercase hex characters.", + "type": "string", + "maxLength": 64 + }, + "Short": { + "description": "Text of at most 200 UTF-8 bytes.", + "type": "string", + "maxLength": 200 + }, + "Slug": { + "description": "A campaign slug or key segment: label parts joined by `.`.", + "type": "string", + "maxLength": 64 + }, + "StructuralDelta": { + "type": "object", + "properties": { + "dependencies_added": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 64 + }, + "dependencies_removed": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 64 + }, + "formats_added": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 64 + }, + "formats_removed": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 64 + }, + "lines_added": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "lines_removed": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "targets_added": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 64 + }, + "targets_removed": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 64 + } + }, + "required": [ + "lines_added", + "lines_removed", + "dependencies_added", + "dependencies_removed", + "formats_added", + "formats_removed", + "targets_added", + "targets_removed" + ] + }, + "TargetInvariant": { + "type": "object", + "properties": { + "label": { + "$ref": "#/$defs/Label" + }, + "statement": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "label", + "statement" + ] + }, + "VerdictClaim": { + "description": "The promise this claim measured, and the report's mutations it ran. An\n`Unproven` claim with a promise is one Soul could not reach.", + "type": "object", + "properties": { + "claim": { + "$ref": "#/$defs/Line" + }, + "evidence": { + "type": "array", + "items": { + "$ref": "#/$defs/Evidence" + }, + "maxItems": 8 + }, + "findings": { + "type": "array", + "items": { + "$ref": "#/$defs/Short" + }, + "maxItems": 16 + }, + "mutations": { + "type": "array", + "items": { + "$ref": "#/$defs/Label" + }, + "maxItems": 8 + }, + "outcome": { + "$ref": "#/$defs/ClaimOutcome" + }, + "promise": { + "anyOf": [ + { + "$ref": "#/$defs/Label" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "claim", + "outcome", + "evidence", + "findings", + "mutations" + ] + }, + "VerificationTest": { + "type": "object", + "properties": { + "name": { + "$ref": "#/$defs/Short" + }, + "pins": { + "$ref": "#/$defs/Line" + } + }, + "required": [ + "name", + "pins" + ] + } + } +} \ No newline at end of file