diff --git a/Makefile b/Makefile index ca53060..acea857 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,12 @@ -.PHONY: validate validate-control-plane-examples validate-nlboot-examples validate-lattice-data-governai-examples validate-ops-history-examples validate-runtime-observability-examples validate-interpretability-examples validate-lifecycle-boundary-examples validate-svf-contracts validate-sync-cycle-receipts validate-onboarding-examples validate-runtime-causality-examples validate-agentic-os-examples validate-triparty-examples validate-labor-market-examples validate-supply-chain-risk-examples validate-reasoning-examples +.PHONY: validate validate-control-plane-examples validate-nlboot-examples validate-lattice-data-governai-examples validate-ops-history-examples validate-runtime-observability-examples validate-interpretability-examples validate-lifecycle-boundary-examples validate-svf-contracts validate-sync-cycle-receipts validate-onboarding-examples validate-runtime-causality-examples validate-agentic-os-examples validate-triparty-examples validate-labor-market-examples validate-supply-chain-risk-examples validate-reasoning-examples validate-pattern-warrant-examples -validate: validate-control-plane-examples validate-nlboot-examples validate-lattice-data-governai-examples validate-ops-history-examples validate-runtime-observability-examples validate-interpretability-examples validate-lifecycle-boundary-examples validate-svf-contracts validate-sync-cycle-receipts validate-onboarding-examples validate-runtime-causality-examples validate-agentic-os-examples validate-triparty-examples validate-labor-market-examples validate-supply-chain-risk-examples validate-reasoning-examples +validate: validate-control-plane-examples validate-nlboot-examples validate-lattice-data-governai-examples validate-ops-history-examples validate-runtime-observability-examples validate-interpretability-examples validate-lifecycle-boundary-examples validate-svf-contracts validate-sync-cycle-receipts validate-onboarding-examples validate-runtime-causality-examples validate-agentic-os-examples validate-triparty-examples validate-labor-market-examples validate-supply-chain-risk-examples validate-reasoning-examples validate-pattern-warrant-examples @echo "OK: validate" +validate-pattern-warrant-examples: + python3 -m pip install --user jsonschema >/dev/null + python3 tools/validate_pattern_warrant_examples.py + validate-reasoning-examples: python3 -m pip install --user jsonschema >/dev/null python3 tools/validate_reasoning_examples.py diff --git a/examples/candidate-manifest.c2.json b/examples/candidate-manifest.c2.json new file mode 100644 index 0000000..a099fb5 --- /dev/null +++ b/examples/candidate-manifest.c2.json @@ -0,0 +1,69 @@ +{ + "id": "urn:srcos:manifest:reconcile-invoices-c2-001", + "type": "CandidateManifest", + "specVersion": "SP-PATT-WARR-001/0.1.0", + "patternRef": "urn:srcos:pattern:invoice-reconciliation-request", + "consequenceClass": "C2", + "capabilities": [ + { + "capability": "ledger.read", + "scope": { "namespace": "finance/ledger" }, + "minConsequenceClass": "C0" + }, + { + "capability": "ledger.reconcile", + "scope": { "namespace": "finance/ledger", "reversible": true }, + "minConsequenceClass": "C2" + } + ], + "evidenceSetDigest": "sha256:2f0c9d1a6b4e8c7f5a3b2d1e0f9c8b7a6d5e4c3b2a1908f7e6d5c4b3a2f1e0d9c", + "warrantAtDeclaration": { + "epistemicLevel": "BOUNDED", + "H": 0.31, + "k": 6, + "computedAt": "2026-07-21T09:00:00Z" + }, + "falsificationRecord": { + "wouldFalsifyIf": [ + "reconciliation applied to a non-matching invoice/ledger pair", + "a reconciled entry that is not internally reversible within the SoR" + ], + "testsRun": [ + { "testId": "urn:srcos:test:recon-match-precondition", "verdict": "POS" }, + { "testId": "urn:srcos:test:recon-reversibility", "verdict": "POS" }, + { "testId": "urn:srcos:test:recon-cross-tenant-leak", "verdict": "ZERO" } + ], + "nearMisses": [ + "duplicate invoice id across two vendors nearly matched the wrong ledger row" + ] + }, + "consentExposure": { + "tokenCount": 41, + "revocableFraction": 0.62, + "maxSingleTokenContribution": 0.09 + }, + "attestations": [ + { + "id": "urn:srcos:attestation:owner-sig-001", + "type": "AttestationAtom", + "specVersion": "SP-PATT-WARR-001/0.1.0", + "attestor": "urn:srcos:principal:mdheller", + "quorumRole": "owner", + "manifestRef": "urn:srcos:manifest:reconcile-invoices-c2-001", + "evidenceSetDigest": "sha256:2f0c9d1a6b4e8c7f5a3b2d1e0f9c8b7a6d5e4c3b2a1908f7e6d5c4b3a2f1e0d9c", + "signature": "ed25519:PLACEHOLDER_SIGNATURE_OWNER", + "attestedAt": "2026-07-21T09:15:00Z" + }, + { + "id": "urn:srcos:attestation:reviewer-sig-001", + "type": "AttestationAtom", + "specVersion": "SP-PATT-WARR-001/0.1.0", + "attestor": "urn:srcos:principal:reviewer-a", + "quorumRole": "reviewer", + "manifestRef": "urn:srcos:manifest:reconcile-invoices-c2-001", + "evidenceSetDigest": "sha256:2f0c9d1a6b4e8c7f5a3b2d1e0f9c8b7a6d5e4c3b2a1908f7e6d5c4b3a2f1e0d9c", + "signature": "ed25519:PLACEHOLDER_SIGNATURE_REVIEWER", + "attestedAt": "2026-07-21T09:40:00Z" + } + ] +} diff --git a/examples/warrant-lattice.default.json b/examples/warrant-lattice.default.json new file mode 100644 index 0000000..86be456 --- /dev/null +++ b/examples/warrant-lattice.default.json @@ -0,0 +1,47 @@ +{ + "id": "urn:srcos:warrantlattice:default-v1", + "type": "WarrantLattice", + "specVersion": "SP-PATT-WARR-001/0.1.0", + "minW": { + "C0": "SPECULATIVE", + "C1": "EMPIRICAL", + "C2": "BOUNDED", + "C3": "PROVED" + }, + "quorum": { + "C0": { "minAttestors": 1, "roles": ["owner"] }, + "C1": { "minAttestors": 1, "roles": ["owner"] }, + "C2": { "minAttestors": 2, "roles": ["owner", "reviewer"] }, + "C3": { "minAttestors": 3, "roles": ["owner", "reviewer", "control"] } + }, + "decayHalfLifeDays": { + "C0": 180, + "C1": 90, + "C2": 30, + "C3": 14 + }, + "hysteresis": { + "dwellUpDays": 7, + "dwellDownDays": 2, + "thetaUp": {}, + "thetaDown": {} + }, + "concentrationCaps": [ + { + "ceiling": "EMPIRICAL", + "maxHerfindahl": null, + "minDistinctPrincipals": null + }, + { + "ceiling": "BOUNDED", + "maxHerfindahl": 0.5, + "minDistinctPrincipals": 3 + }, + { + "ceiling": "PROVED", + "maxHerfindahl": 0.25, + "minDistinctPrincipals": 8, + "machineDerivedExempt": true + } + ] +} diff --git a/fixtures/pattern-warrant/conformance.json b/fixtures/pattern-warrant/conformance.json new file mode 100644 index 0000000..1919ae3 --- /dev/null +++ b/fixtures/pattern-warrant/conformance.json @@ -0,0 +1,98 @@ +{ + "spec": "SP-PATT-WARR-001", + "specVersion": "0.1.0", + "description": "§9 conformance vectors. Every implementing layer (L1-L7) MUST pass the vectors applicable to it. 'appliesTo' names the layers that must exercise the vector.", + "vectors": [ + { + "id": "T1", + "title": "PROVED warrant without attestation does not grant", + "appliesTo": ["L2", "L4"], + "given": { + "warrant": "PROVED", + "consequenceClass": "C3", + "attestations": [] + }, + "expect": { "grant": false, "reason": "SP-PW-I1: no score authorizes; quorum unmet" } + }, + { + "id": "T2", + "title": "Single-principal evidence capped at EMPIRICAL", + "appliesTo": ["L2"], + "given": { + "evidence": { "distinctPrincipals": 1, "volume": 100000, "H": 1.0 } + }, + "expect": { "warrantCeiling": "EMPIRICAL", "reason": "§2.2 concentration cap" } + }, + { + "id": "T3", + "title": "Consent revocation recomputes in O(1) token stats", + "appliesTo": ["L2", "L7"], + "given": { + "revoke": "topContributingToken", + "scorer": "decomposableAggregate" + }, + "expect": { + "recomputeTouches": "O(revokedTokens)", + "withinSLA": true, + "reason": "SP-PW-R2 incremental sufficient statistics" + } + }, + { + "id": "T4", + "title": "Decay past minW(C2) reduces ceiling to C1, abstains on C2 ops", + "appliesTo": ["L2", "L5", "L6"], + "given": { + "consequenceClass": "C2", + "warrantDecaysTo": "EMPIRICAL", + "operationRequires": "C2" + }, + "expect": { + "ternary": "ZERO", + "ceilingClass": "C1", + "response": "AbstentionEvent", + "suspended": false, + "errorClass": false, + "reason": "§3.3 per-capability ceiling reduction, not suspension" + } + }, + { + "id": "T5", + "title": "Attested NEG suspends and returns to declaration gate; attestations retained", + "appliesTo": ["L2", "L4", "L5"], + "given": { + "attestedVerdict": "NEG" + }, + "expect": { + "suspended": true, + "returnedToDeclarationGate": true, + "attestationsDeleted": false, + "reason": "§3.3 NEG; §9 T5 monotone attestations" + } + }, + { + "id": "T6", + "title": "Oscillating evidence at theta boundary does not flap the ceiling", + "appliesTo": ["L2"], + "given": { + "evidence": "oscillatingAtThetaBoundary" + }, + "expect": { + "ceilingFlapping": false, + "reason": "§3.2 hysteresis dwell (d_up=7d, d_down=2d) honored" + } + }, + { + "id": "T7", + "title": "ZERO is never serialized as NEG at PEP, log, or UI", + "appliesTo": ["L4", "L5", "L6"], + "given": { + "ternary": "ZERO" + }, + "expect": { + "serializedAs": "ZERO", + "neverRenderedAs": "NEG", + "reason": "INVARIANT SP-PW-I2" + } + } + ] +} diff --git a/schemas/AbstentionEvent.json b/schemas/AbstentionEvent.json new file mode 100644 index 0000000..f795789 --- /dev/null +++ b/schemas/AbstentionEvent.json @@ -0,0 +1,62 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/AbstentionEvent.json", + "title": "AbstentionEvent", + "description": "SP-PATT-WARR-001 §3.3 corollary. Emitted when an operation requires a consequence class above the manifest's current ceiling. An abstention is NOT an error and NOT a denial: it is reduced authority under live uncertainty (ternary ZERO). INVARIANT SP-PW-I2: this event must never be serialized or surfaced as NEG/deny. It carries the W_p value and evidence-set digest that produced the abstention.", + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "type", + "specVersion", + "manifestRef", + "capability", + "requestedClass", + "ceilingClass", + "warrantAtDecision", + "ternary", + "evidenceSetDigest", + "decidedAt" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^urn:srcos:abstention:[A-Za-z0-9._~-]+$" + }, + "type": { + "const": "AbstentionEvent" + }, + "specVersion": { + "type": "string" + }, + "manifestRef": { + "type": "string", + "pattern": "^urn:srcos:manifest:[A-Za-z0-9._~-]+$" + }, + "capability": { + "type": "string", + "description": "The specific capability abstained on; ceiling reduction is per-capability (§4)." + }, + "requestedClass": { + "enum": ["C0", "C1", "C2", "C3"] + }, + "ceilingClass": { + "enum": ["C0", "C1", "C2", "C3"], + "description": "max{ c : minW(c) <= W_p } at decision time." + }, + "warrantAtDecision": { + "enum": ["SPECULATIVE", "EMPIRICAL", "BOUNDED", "PROVED"] + }, + "ternary": { + "const": "ZERO", + "description": "Abstention is the ZERO response by construction; never POS, never NEG." + }, + "evidenceSetDigest": { + "type": "string" + }, + "decidedAt": { + "type": "string", + "format": "date-time" + } + } +} diff --git a/schemas/AttestationAtom.json b/schemas/AttestationAtom.json new file mode 100644 index 0000000..da1171a --- /dev/null +++ b/schemas/AttestationAtom.json @@ -0,0 +1,54 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/AttestationAtom.json", + "title": "AttestationAtom", + "description": "SP-PATT-WARR-001 §5. A signed reviewer attestation contributing to the quorum Q(C). Monotone and never deleted: on NEG suspension (§3.3) prior attestations are retained, not removed (§9 T5). The signature binds evidenceSetDigest so evidence cannot be substituted post-attestation.", + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "type", + "specVersion", + "attestor", + "quorumRole", + "manifestRef", + "evidenceSetDigest", + "signature", + "attestedAt" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^urn:srcos:attestation:[A-Za-z0-9._~-]+$" + }, + "type": { + "const": "AttestationAtom" + }, + "specVersion": { + "type": "string" + }, + "attestor": { + "type": "string", + "description": "PrincipalId of the reviewer." + }, + "quorumRole": { + "type": "string", + "description": "Role slot this attestation fills within the required quorum Q(C)." + }, + "manifestRef": { + "type": "string", + "pattern": "^urn:srcos:manifest:[A-Za-z0-9._~-]+$" + }, + "evidenceSetDigest": { + "type": "string", + "description": "Digest of the evidence set as presented to the attestor; bound into the signed payload (threat: evidence-set substitution)." + }, + "signature": { + "type": "string" + }, + "attestedAt": { + "type": "string", + "format": "date-time" + } + } +} diff --git a/schemas/CandidateManifest.json b/schemas/CandidateManifest.json new file mode 100644 index 0000000..3b6539b --- /dev/null +++ b/schemas/CandidateManifest.json @@ -0,0 +1,192 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/CandidateManifest.json", + "title": "CandidateManifest", + "description": "SP-PATT-WARR-001 §4 (the ManifestAtom of §5). A proposed agent authority. INVARIANT SP-PW-I1: no evidence-derived score in this document grants authority; evidence determines only whether the manifest may be proposed and which quorum is required. Authority is granted exclusively by signed attestations meeting Q(C). consequenceClass is immutable post-declaration (anti warrant-laundering).", + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "type", + "specVersion", + "patternRef", + "consequenceClass", + "capabilities", + "evidenceSetDigest", + "warrantAtDeclaration", + "falsificationRecord", + "consentExposure", + "attestations" + ], + "properties": { + "id": { + "type": "string", + "description": "manifestId (§4).", + "pattern": "^urn:srcos:manifest:[A-Za-z0-9._~-]+$" + }, + "type": { + "const": "CandidateManifest" + }, + "specVersion": { + "type": "string" + }, + "patternRef": { + "type": "string", + "description": "HellGraph PatternAtom id.", + "pattern": "^urn:srcos:pattern:[A-Za-z0-9._~-]+$" + }, + "consequenceClass": { + "description": "Axis B. Property of the manifest, not the pattern. Assigned at declaration, immutable thereafter; a class change requires a new manifest and a new quorum.", + "enum": [ + "C0", + "C1", + "C2", + "C3" + ] + }, + "capabilities": { + "type": "array", + "description": "Per-capability class allows partial ceiling reduction under ZERO — the manifest degrades gracefully rather than wholesale.", + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "capability", + "scope", + "minConsequenceClass" + ], + "properties": { + "capability": { + "type": "string" + }, + "scope": { + "type": "object" + }, + "minConsequenceClass": { + "enum": [ + "C0", + "C1", + "C2", + "C3" + ] + } + } + } + }, + "evidenceSetDigest": { + "type": "string" + }, + "warrantAtDeclaration": { + "type": "object", + "additionalProperties": false, + "required": [ + "epistemicLevel", + "H", + "k", + "computedAt" + ], + "properties": { + "epistemicLevel": { + "enum": [ + "SPECULATIVE", + "EMPIRICAL", + "BOUNDED", + "PROVED" + ] + }, + "H": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "k": { + "type": "integer", + "minimum": 0 + }, + "computedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "falsificationRecord": { + "type": "object", + "additionalProperties": false, + "required": [ + "wouldFalsifyIf", + "testsRun", + "nearMisses" + ], + "properties": { + "wouldFalsifyIf": { + "type": "array", + "items": { + "type": "string" + } + }, + "testsRun": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "testId", + "verdict" + ], + "properties": { + "testId": { + "type": "string" + }, + "verdict": { + "enum": [ + "POS", + "ZERO", + "NEG" + ] + } + } + } + }, + "nearMisses": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "consentExposure": { + "type": "object", + "additionalProperties": false, + "description": "What this manifest loses if consent is withdrawn.", + "required": [ + "tokenCount", + "revocableFraction", + "maxSingleTokenContribution" + ], + "properties": { + "tokenCount": { + "type": "integer", + "minimum": 0 + }, + "revocableFraction": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "maxSingleTokenContribution": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + } + }, + "attestations": { + "type": "array", + "description": "AttestationAtom references meeting the quorum Q(consequenceClass). Q is independent of W_p: high warrant reduces neither the requirement nor the quorum.", + "items": { + "$ref": "https://schemas.srcos.ai/v2/AttestationAtom.json" + } + } + } +} diff --git a/schemas/ConsentAtom.json b/schemas/ConsentAtom.json new file mode 100644 index 0000000..99128c3 --- /dev/null +++ b/schemas/ConsentAtom.json @@ -0,0 +1,56 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/ConsentAtom.json", + "title": "ConsentAtom", + "description": "SP-PATT-WARR-001 §5. Consent grant governing admissibility of evidence. Revocation flips status to 'revoked'; edges bearing this token become inadmissible and W_p is recomputed (§2.3, P-04 binding).", + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "type", + "specVersion", + "token", + "grantor", + "scope", + "status" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^urn:srcos:consent:[A-Za-z0-9._~-]+$" + }, + "type": { + "const": "ConsentAtom" + }, + "specVersion": { + "type": "string" + }, + "token": { + "type": "string", + "description": "ConsentTokenId referenced by EvidenceAtom.consentToken." + }, + "grantor": { + "type": "string", + "description": "PrincipalId that granted the consent." + }, + "scope": { + "type": "object", + "description": "Bounds of the grant (channels, purposes, expiry)." + }, + "status": { + "type": "string", + "enum": [ + "active", + "revoked", + "expired" + ] + }, + "revokedAt": { + "type": [ + "string", + "null" + ], + "format": "date-time" + } + } +} diff --git a/schemas/EvidenceAtom.json b/schemas/EvidenceAtom.json new file mode 100644 index 0000000..7473812 --- /dev/null +++ b/schemas/EvidenceAtom.json @@ -0,0 +1,70 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/EvidenceAtom.json", + "title": "EvidenceAtom", + "description": "SP-PATT-WARR-001 §2.1. A provenance-addressed observation contributing to a pattern warrant. An observation is an addressable atom, never a counter increment. Every contribution to W_p (SP-PW-R1) must be traceable to a set of these.", + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "type", + "specVersion", + "patternRef", + "principal", + "observedAt", + "channel", + "payloadDigest" + ], + "properties": { + "id": { + "type": "string", + "description": "Content-hash / provenance address of this observation.", + "pattern": "^urn:srcos:evidence:[A-Za-z0-9._~-]+$" + }, + "type": { + "const": "EvidenceAtom" + }, + "specVersion": { + "type": "string" + }, + "patternRef": { + "type": "string", + "description": "PatternAtom.id this evidence addresses.", + "pattern": "^urn:srcos:pattern:[A-Za-z0-9._~-]+$" + }, + "principal": { + "type": "string", + "description": "PrincipalId that generated the observation. Drives the §2.2 concentration cap." + }, + "consentToken": { + "type": [ + "string", + "null" + ], + "description": "ConsentAtom token, or null for non-consent-derived system telemetry. Revocation (§2.3) removes all evidence bearing a revoked token." + }, + "observedAt": { + "type": "string", + "format": "date-time" + }, + "channel": { + "type": "string", + "enum": [ + "query", + "workflow", + "doc_access", + "tool_call", + "system_telemetry" + ] + }, + "payloadDigest": { + "type": "string", + "description": "Hash of the underlying payload; the payload itself is not carried." + }, + "weightAtObservation": { + "type": "number", + "description": "Optional pre-decay weight; decay (§3.1) is applied by the scorer as a function of manifest class, not stored here.", + "minimum": 0 + } + } +} diff --git a/schemas/PatternAtom.json b/schemas/PatternAtom.json new file mode 100644 index 0000000..de7195c --- /dev/null +++ b/schemas/PatternAtom.json @@ -0,0 +1,55 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/PatternAtom.json", + "title": "PatternAtom", + "description": "SP-PATT-WARR-001 §5. The claim, in Mellumwork terms. A pattern is a falsifiable assertion over an evidence stream; its warrant W_p is a function of time, never a stored attribute.", + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "type", + "specVersion", + "signature", + "channelSet", + "firstSeen" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^urn:srcos:pattern:[A-Za-z0-9._~-]+$" + }, + "type": { + "const": "PatternAtom" + }, + "specVersion": { + "type": "string" + }, + "signature": { + "type": "string", + "description": "Structural signature identifying the pattern claim." + }, + "channelSet": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "query", + "workflow", + "doc_access", + "tool_call", + "system_telemetry" + ] + }, + "minItems": 1 + }, + "firstSeen": { + "type": "string", + "format": "date-time" + }, + "machineDerived": { + "type": "boolean", + "default": false, + "description": "True when the pattern's invariant is machine-checkable and evidence-independent (§2.2 PROVED escape hatch): behavioral diversity is not required because no behavior is required." + } + } +} diff --git a/schemas/WarrantEdge.json b/schemas/WarrantEdge.json new file mode 100644 index 0000000..d22b21e --- /dev/null +++ b/schemas/WarrantEdge.json @@ -0,0 +1,98 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/WarrantEdge.json", + "title": "WarrantEdge", + "description": "SP-PATT-WARR-001 §5. Time-indexed edge (PatternAtom -> ManifestAtom) recording W_p(t), the Mellumwork ternary verdict, and the operating ceiling. Full history is retained, making 'was this agent warranted at time t, and on whose data' answerable by traversal rather than log reconstruction.", + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "type", + "specVersion", + "patternRef", + "manifestRef", + "computedAt", + "warrant", + "ternary", + "ceiling", + "evidenceSetDigest" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^urn:srcos:warrantedge:[A-Za-z0-9._~-]+$" + }, + "type": { + "const": "WarrantEdge" + }, + "specVersion": { + "type": "string" + }, + "patternRef": { + "type": "string", + "pattern": "^urn:srcos:pattern:[A-Za-z0-9._~-]+$" + }, + "manifestRef": { + "type": "string", + "pattern": "^urn:srcos:manifest:[A-Za-z0-9._~-]+$" + }, + "computedAt": { + "type": "string", + "format": "date-time" + }, + "warrant": { + "type": "string", + "description": "W_p at computedAt, on the SCOPE-D epistemicLevel ordinal (Axis A).", + "enum": [ + "SPECULATIVE", + "EMPIRICAL", + "BOUNDED", + "PROVED" + ] + }, + "ternary": { + "type": "string", + "description": "Mellumwork verdict at computedAt. INVARIANT SP-PW-I2: ZERO must never be serialized or rendered as NEG at any surface (§9 T7). ZERO is reduced authority under live uncertainty; NEG is a falsifying test.", + "enum": [ + "POS", + "ZERO", + "NEG" + ] + }, + "ceiling": { + "type": "string", + "description": "The consequence class the manifest may operate at given warrant. Under ZERO this is max{ c : minW(c) <= W_p } (ceiling reduction, never suspension).", + "enum": [ + "C0", + "C1", + "C2", + "C3" + ] + }, + "evidenceSetDigest": { + "type": "string", + "description": "Digest of the admissible evidence set that produced this warrant value." + }, + "concentration": { + "type": "object", + "additionalProperties": false, + "description": "§2.2 anti-Goodhart concentration state at computedAt.", + "properties": { + "H": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "k": { + "type": "integer", + "minimum": 0 + }, + "topPrincipalShare": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + } + } + } +} diff --git a/schemas/WarrantLattice.json b/schemas/WarrantLattice.json new file mode 100644 index 0000000..0b1a7bd --- /dev/null +++ b/schemas/WarrantLattice.json @@ -0,0 +1,126 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/WarrantLattice.json", + "title": "WarrantLattice", + "description": "SP-PATT-WARR-001 §1.3, §2.2, §3.1-3.2. The normative lattice binding consequence class C to the warrant floor minW(C), the attestation quorum Q(C), the evidence decay half-life, the hysteresis thresholds, and the concentration caps. Q is monotone non-decreasing in C and independent of W_p. Decay half-life shortens with C: higher consequence must be more freshly re-earned.", + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "type", + "specVersion", + "minW", + "quorum", + "decayHalfLifeDays", + "hysteresis", + "concentrationCaps" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^urn:srcos:warrantlattice:[A-Za-z0-9._~-]+$" + }, + "type": { + "const": "WarrantLattice" + }, + "specVersion": { + "type": "string" + }, + "minW": { + "type": "object", + "additionalProperties": false, + "description": "Floor on W_p required for a manifest at class C to remain live (Grant conjunct W_p >= minW(C)).", + "required": ["C0", "C1", "C2", "C3"], + "properties": { + "C0": { "const": "SPECULATIVE" }, + "C1": { "const": "EMPIRICAL" }, + "C2": { "const": "BOUNDED" }, + "C3": { "const": "PROVED" } + } + }, + "quorum": { + "type": "object", + "additionalProperties": false, + "description": "Attestation quorum required at declaration per class. Monotone non-decreasing in C; independent of W_p.", + "required": ["C0", "C1", "C2", "C3"], + "properties": { + "C0": { "$ref": "#/$defs/quorumSpec" }, + "C1": { "$ref": "#/$defs/quorumSpec" }, + "C2": { "$ref": "#/$defs/quorumSpec" }, + "C3": { "$ref": "#/$defs/quorumSpec" } + } + }, + "decayHalfLifeDays": { + "type": "object", + "additionalProperties": false, + "description": "§3.1 tau_C. Evidence weight decays with half-life dependent on the manifest's class.", + "required": ["C0", "C1", "C2", "C3"], + "properties": { + "C0": { "type": "number", "exclusiveMinimum": 0 }, + "C1": { "type": "number", "exclusiveMinimum": 0 }, + "C2": { "type": "number", "exclusiveMinimum": 0 }, + "C3": { "type": "number", "exclusiveMinimum": 0 } + } + }, + "hysteresis": { + "type": "object", + "additionalProperties": false, + "description": "§3.2 asymmetric promote/demote with dwell. theta_up(L) > theta_down(L) for all L; d_down < d_up by design.", + "required": ["dwellUpDays", "dwellDownDays"], + "properties": { + "dwellUpDays": { "type": "number", "exclusiveMinimum": 0 }, + "dwellDownDays": { "type": "number", "exclusiveMinimum": 0 }, + "thetaUp": { + "type": "object", + "description": "Promotion thresholds per target level. Placeholders pending scoring-function choice (OI-1)." + }, + "thetaDown": { + "type": "object", + "description": "Demotion thresholds per level. Placeholders pending scoring-function choice (OI-1)." + } + } + }, + "concentrationCaps": { + "type": "array", + "description": "§2.2 principal-concentration cap on W_p. A single principal or compromised session must not synthesize enough repetition to reach C2/C3 eligibility.", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["ceiling"], + "properties": { + "ceiling": { + "enum": ["SPECULATIVE", "EMPIRICAL", "BOUNDED", "PROVED"] + }, + "maxHerfindahl": { + "type": ["number", "null"], + "minimum": 0, + "maximum": 1 + }, + "minDistinctPrincipals": { + "type": ["integer", "null"], + "minimum": 0 + }, + "machineDerivedExempt": { + "type": "boolean", + "default": false, + "description": "When true, a machine-derived evidence-independent pattern satisfies this ceiling with no behavioral diversity." + } + } + } + } + }, + "$defs": { + "quorumSpec": { + "type": "object", + "additionalProperties": false, + "required": ["minAttestors", "roles"], + "properties": { + "minAttestors": { "type": "integer", "minimum": 0 }, + "roles": { + "type": "array", + "items": { "type": "string" } + } + } + } + } +} diff --git a/specs/pattern-warranted-manifest.md b/specs/pattern-warranted-manifest.md new file mode 100644 index 0000000..020ab33 --- /dev/null +++ b/specs/pattern-warranted-manifest.md @@ -0,0 +1,101 @@ +# SP-PATT-WARR-001 — Pattern-Warranted Agent Manifest Pipeline + +**Status:** DRAFT v0.1.0 · normative artifacts landed in `sourceos-spec` +**Owner:** SocioProphet / Platform Architecture +**Depends on:** SCOPE-D (`epistemicLevel`), Mellumwork (ternary falsification), HellGraph (typed-atom kernel), PolicyFabric (PEP), AgentPlane (execution binding), agent-registry (declaration surface) +**Patent adjacency:** P-02/agentplane, P-04/consent-bound revocation + +This document is the spec-repo home of SP-PATT-WARR-001. It binds the design to concrete +JSON Schemas under `schemas/` and to conformance fixtures under `fixtures/pattern-warrant/`. +Implementations across the estate conform to these artifacts; they do not re-derive them. + +## `$id` normalization (spec-first) + +The design draft used `https://schema.socioprophet.ai/...` URIs. The canonical +`sourceos-spec` convention is `https://schemas.srcos.ai/v2/.json` with a `type` +const discriminator, a `specVersion` string, and `additionalProperties: false`. All +artifacts below follow the repo convention, not the draft URIs. + +| Draft entity | Schema | +|---|---| +| `CandidateManifest/v1` (§4) / `ManifestAtom` (§5) | `schemas/CandidateManifest.json` | +| `EvidenceAtom` (§2.1) | `schemas/EvidenceAtom.json` | +| `PatternAtom` (§5) | `schemas/PatternAtom.json` | +| `ConsentAtom` (§5) | `schemas/ConsentAtom.json` | +| `AttestationAtom` (§5) | `schemas/AttestationAtom.json` | +| `WarrantEdge` (§5) | `schemas/WarrantEdge.json` | +| warrant lattice (§1.3, §2.2, §3) | `schemas/WarrantLattice.json` + `examples/warrant-lattice.default.json` | +| abstention event (§3.3 corollary) | `schemas/AbstentionEvent.json` | + +## Invariants (conformance-tested at every layer) + +- **SP-PW-I1 — evidence-informed, never evidence-authorized.** No value of any + evidence-derived score grants execution authority. Evidence determines only (i) whether a + manifest may be *proposed* and (ii) which attestation quorum is *required*. Authority is + granted exclusively by signed attestations meeting `Q(C)`. +- **SP-PW-I2 — no collapse.** `ZERO` is never rendered as `NEG` at any surface (enforcement, + logging, approver UI). A decayed warrant is reduced authority under live uncertainty, not a + failure. Collapsing `ZERO → deny` reintroduces the binary-threshold pathology this pipeline + exists to remove. + +## Grant predicate (§1.4) + +``` +Grant(m, t) ⟺ Declared(m) + ∧ Attested(m, Q(C(m))) + ∧ W_p(pattern(m), t) ≥ minW(C(m)) + ∧ ¬Revoked(evidence(m), t) +``` + +`Declared` and `Attested` are one-shot, monotone. The last two conjuncts are evaluated +continuously; their falsification lowers the operating **ceiling** (per capability), it does +not revoke the declaration. + +## Response mapping (§3.3) + +| Ternary | Condition | Response | +|---|---|---| +| `POS` | `W_p ≥ minW(C)` | operate at declared class `C` | +| `ZERO` | `W_p < minW(C)`, no NEG | ceiling reduction to `C' = max{ c : minW(c) ≤ W_p }`; over-ceiling ops return an `AbstentionEvent`, not an error; flag for re-attestation | +| `NEG` | falsifying test attested | suspend; return to declaration gate; prior attestations retained | + +## Repo placement (build order) + +| Layer | Repo | Delivers | +|---|---|---| +| L0 | `sourceos-spec` | these normative schemas + fixtures (this document) | +| L1 | `hellgraph` | atom types + `WarrantEdge` (decoupled module; no kernel edits) | +| L2 | `scope-d` | decomposable-aggregate scorer, concentration cap, decay, hysteresis, ternary map | +| L3 | `mellumwork` (new) | ternary falsification harness — POS/ZERO/NEG source | +| L4 | `agent-registry` | declaration + attestation quorum gate; approver surface (§8) | +| L5 | `policyfabric` (new) | PEP: live `W_p` consult, per-capability ceiling, abstention path | +| L6 | `agentplane` | execution binding, honors per-capability ceiling | +| L7 | `prophet-mesh`/`noetica` | evidence capture consumer over existing provenance stream | + +## Open items (resolutions carried into build) + +- **OI-1** `θ_up`/`θ_down` and `quorum.minAttestors` in `examples/warrant-lattice.default.json` + are placeholders pending a scoring-function choice. The lattice schema treats `thetaUp`/ + `thetaDown` as open objects until L2 fixes the scorer. Dwell values (`d_up=7d`, `d_down=2d`) + and decay half-lives are normative now. +- **OI-2** `C3` retains the `PROVED` requirement. `C3` automation is rare by construction; the + `machineDerivedExempt` cap is the only path to `PROVED` without behavioral diversity. +- **OI-3** No cross-tenant evidence aggregation without an explicit grant. Deferred to its own + work order; the `principal`/`consentToken` fields carry enough to gate it later. +- **OI-4** ZERO/abstention rates feed the SP-EVAL-CRF-001 abstention-calibration headline + metric. `AbstentionEvent` is the emission surface for that feed. + +## Threat model (§7) — schema-enforced points + +- Synthetic usage manufactures warrant → `WarrantLattice.concentrationCaps` (§2.2). +- Warrant laundering (promote under C0, re-declare at C3) → `consequenceClass` immutable + post-declaration; a class change is a new manifest with a new quorum. +- Evidence-set substitution post-attestation → `evidenceSetDigest` bound into the signed + `AttestationAtom` payload. +- Consent revocation used to infer participation → SP-PW-R3: revocation-induced demotion is + indistinguishable from decay-induced demotion at the enforcement surface. + +## Conformance + +See `fixtures/pattern-warrant/conformance.json` for the §9 test vectors T1–T7. Every +implementing layer runs them; T7 (ZERO never serialized as NEG) is mandatory at L4/L5/L6. diff --git a/tools/validate_pattern_warrant_examples.py b/tools/validate_pattern_warrant_examples.py new file mode 100644 index 0000000..9d9fe01 --- /dev/null +++ b/tools/validate_pattern_warrant_examples.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +"""Validate the SP-PATT-WARR-001 pattern-warranted-manifest contract family. + +Two checks, not one: + 1. schema conformance — every schema is a valid draft, and every example + validates against its schema (cross-$ref resolved from a local registry + so it works offline); + 2. projection soundness — the §9 conformance vectors are recomputed from the + reference ceiling()/grant() projections over the default WarrantLattice and + must match their recorded expectations. This keeps the warrant readout an + *executable* projection of (W_p, C, quorum) rather than a stored opinion, + and mechanically enforces SP-PW-I1 (no score authorizes) and SP-PW-I2 + (ZERO is never NEG). +""" +from __future__ import annotations + +import json +from pathlib import Path + +import jsonschema +from referencing import Registry, Resource + +ROOT = Path(__file__).resolve().parents[1] + +WARRANT_ORD = {"SPECULATIVE": 0, "EMPIRICAL": 1, "BOUNDED": 2, "PROVED": 3} +CLASS_ORD = {"C0": 0, "C1": 1, "C2": 2, "C3": 3} +ORD_CLASS = {v: k for k, v in CLASS_ORD.items()} + +PAIRS = [ + (ROOT / "schemas" / "WarrantLattice.json", ROOT / "examples" / "warrant-lattice.default.json"), + (ROOT / "schemas" / "CandidateManifest.json", ROOT / "examples" / "candidate-manifest.c2.json"), +] + +SCHEMAS = [ + "EvidenceAtom.json", + "PatternAtom.json", + "ConsentAtom.json", + "AttestationAtom.json", + "WarrantEdge.json", + "CandidateManifest.json", + "WarrantLattice.json", + "AbstentionEvent.json", +] + + +def build_registry() -> Registry: + """Register every schema by its $id so cross-$ref (e.g. CandidateManifest -> + AttestationAtom) resolves without network access.""" + resources = [] + for name in SCHEMAS: + schema = json.loads((ROOT / "schemas" / name).read_text(encoding="utf-8")) + resources.append((schema["$id"], Resource.from_contents(schema))) + return Registry().with_resources(resources) + + +def ceiling(warrant: str, lattice: dict) -> str: + """§3.3: C' = max{ c : minW(c) <= W_p }. The operating ceiling under any + warrant; identical shape whether the warrant is at declaration or decayed.""" + w = WARRANT_ORD[warrant] + admissible = [ + CLASS_ORD[c] + for c, floor in lattice["minW"].items() + if WARRANT_ORD[floor] <= w + ] + return ORD_CLASS[max(admissible)] if admissible else "C0" + + +def quorum_met(consequence_class: str, attestations: list, lattice: dict) -> bool: + """Attested(m, Q(C)): distinct attestors meeting the required roles and count. + Independent of W_p — high warrant never reduces the quorum.""" + q = lattice["quorum"][consequence_class] + roles_present = {a.get("quorumRole") for a in attestations} + return ( + len(attestations) >= q["minAttestors"] + and set(q["roles"]).issubset(roles_present) + ) + + +def grant(warrant: str, consequence_class: str, attestations: list, + revoked: bool, lattice: dict) -> bool: + """§1.4 Grant predicate. SP-PW-I1: no value of `warrant` alone flips this true; + the quorum conjunct is necessary regardless of warrant level.""" + return ( + quorum_met(consequence_class, attestations, lattice) + and WARRANT_ORD[warrant] >= WARRANT_ORD[lattice["minW"][consequence_class]] + and not revoked + ) + + +def check_vectors(lattice: dict) -> dict[str, bool]: + """Recompute the computable §9 vectors from the reference projections.""" + checks: dict[str, bool] = {} + + # T1: PROVED + C3 + no attestation => grant false (I1). + checks["T1"] = grant("PROVED", "C3", [], False, lattice) is False + + # T4: warrant decayed to EMPIRICAL on a C2 manifest => ceiling C1, ZERO abstain. + c = ceiling("EMPIRICAL", lattice) + ternary = "ZERO" if WARRANT_ORD["EMPIRICAL"] < WARRANT_ORD[lattice["minW"]["C2"]] else "POS" + checks["T4"] = (c == "C1" and ternary == "ZERO") + + # T7 (structural): the ZERO response must never be representable as NEG. The + # AbstentionEvent schema pins ternary to const ZERO; assert that here. + abst = json.loads((ROOT / "schemas" / "AbstentionEvent.json").read_text(encoding="utf-8")) + checks["T7"] = abst["properties"]["ternary"].get("const") == "ZERO" + + # Full grant path: the C2 example should grant with its two attestations. + manifest = json.loads((ROOT / "examples" / "candidate-manifest.c2.json").read_text(encoding="utf-8")) + checks["grant:c2-example"] = grant( + manifest["warrantAtDeclaration"]["epistemicLevel"], + manifest["consequenceClass"], + manifest["attestations"], + False, + lattice, + ) is True + + # I1 negative control: strip attestations from the granting example -> no grant. + checks["I1:strip-attestations"] = grant( + manifest["warrantAtDeclaration"]["epistemicLevel"], + manifest["consequenceClass"], + [], + False, + lattice, + ) is False + + return checks + + +def main() -> int: + registry = build_registry() + checks: dict[str, bool] = {} + + # (1) schema conformance + for name in SCHEMAS: + schema = json.loads((ROOT / "schemas" / name).read_text(encoding="utf-8")) + jsonschema.Draft202012Validator.check_schema(schema) + checks[f"schema:{name}"] = True + + for schema_path, example_path in PAIRS: + schema = json.loads(schema_path.read_text(encoding="utf-8")) + example = json.loads(example_path.read_text(encoding="utf-8")) + jsonschema.Draft202012Validator(schema, registry=registry).validate(example) + checks[f"example:{example_path.name}"] = True + + # (2) projection soundness + lattice = json.loads((ROOT / "examples" / "warrant-lattice.default.json").read_text(encoding="utf-8")) + vector_checks = check_vectors(lattice) + for k, v in vector_checks.items(): + if not v: + raise SystemExit(f"conformance vector failed: {k}") + checks[f"vector:{k}"] = True + + print(json.dumps({"ok": all(checks.values()), "checks": checks}, indent=2, sort_keys=True)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())