Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). Thi

### Added
- Ingestion-Pipeline contract family v0.1 (the parse → chunk → embed seam): `IngestedDocument` (a source parsed to one canonical plaintext offset space, `extractionDigest` RECOMPUTED from the text), `Chunk` (a span of that text with an optional embedding), `ExtractedEntity` (an entity grounded at exact document spans), and `EmbeddingRequest` (the one OpenAI-compatible embed-call shape for the whole estate). Generalizes the Noetica `agent-machine/doc-store` pipeline (`extractText`/`chunkTextWithSpans`/`linkDocGrounds`/`hgPutChunk` + an ollama embedder) into a portable contract, ending the platform-services-not-Noetica-only duplication against `prophet-platform/apps/embeddings`. **Normative invariant — one vector space or none**: `EmbeddingRequest` pins the sovereign model (`nomic-ai/nomic-embed-text-v1.5`) and dimension (`768`) by `const`, and every embedded `Chunk` must name that same model/dimension and carry a vector of exactly that length — a request for another model or a Matryoshka-truncated dimension fails by construction, so two producers cannot write into two silently-incomparable spaces. **Span soundness**: the validator recomputes `documentText[start:end] == chunk.text` and `sha256(text) == contentHash`, so a chunk can never silently misquote the document it cites; grounding soundness holds the same bar for `ExtractedEntity` mentions. Includes measured/pre-embedding chunk examples, seven negative conformance vectors (`fixtures/ingestion-pipeline/conformance.json`), a `validate-ingestion-pipeline-examples` target, and a normative spec note (`specs/ingestion-pipeline-contract.md`). Intended reference implementations: Noetica `doc-store` (rewired to the shared service) as producer, `prophet-platform/apps/embeddings` as service.
- Model Plane inference-provenance contracts v0.1 (Tranche 7 / T7-1, T7-3, T7-4): `InferenceReceipt` (the per-completion provenance primitive — tier, content-addressed base/adapter/tokenizer digests, serving daemon, data-residency class, escalation chain, ledger-bound), `EscalationDecision` (the governed tier / data-residency boundary crossing) and `AdapterPromotionDecision` (human-governed LoRA-adapter promotion). These sit **atop** the existing Agent Machine / Model Carry family and reference `InferenceProvider`, `ModelResidency`, `SourceOSModelCarryRef`, and `ExternalModelProviderProfile` rather than restate them; grant references use the estate's `urn:srcos:lease:` (AgentCapabilityLease), not the spec's illustrative `urn:srcos:grant:`. **The governance gates are schema `if/then` teeth, verified to fire both ways:** an off-device `InferenceReceipt` cannot validate without an authorizing lease and a non-empty escalation chain (SEAM-015); an `EscalationDecision` cannot be `permitted` without an authorizing `capabilityLeaseRef` *and* a passing T0 sensitivity check, with `prompt-unanswered` as the fail-closed resolution for non-interactive workloads (SEAM-015); an `AdapterPromotionDecision` cannot be `promoted` without a verified signature, per-event training consent, all eval gates passing (including an adversarial-poisoning probe), a named human promoter, and a mandatory rollback target (SEAM-016/017). All three carry optional `ledgerPrevHash` (append-only-ledger hash-chaining, so an enumerated contribution list cannot be retroactively rewritten) and the receipt carries optional `confidenceMethod` (the escalation trigger is self-reported — recording the method makes it auditable). Note: `AdapterPromotionDecision` governs *model* (LoRA) adapters and is distinct from `AdapterDescriptor` (connector/actuation adapters). Includes canonical examples (`examples/inference-receipt.json`, `examples/escalation-decision.json`, `examples/adapter-promotion-decision.json`) and `docs/adr/0015-model-plane-inference-provenance.md`, which records the reconciliation and the two deferred T7 decisions — `ModelManifest`/`AdapterManifest` (T7-2, overlaps `SourceOSModelCarryRef` + name collision) and adding `inference_provider` to `AgentPassport.agent_class` (T7-5, a core-ontology change vs the deliberate separate-object `InferenceProvider` modeling).
- DeviceService contract v0.1 (FOG & CITIZEN PLANE W8.7 — the estate's first southbound device abstraction): `DeviceProfile` (what a device IS — protocol, typed protocol binding, and the exact metric set it produces with units, value types, operating ranges and protocol-native source addresses; digest-pinned by a `definitionDigest` the validator RECOMPUTES) and `DeviceReading` (one observation — deviceRef, metric, value, unit, quality, observedAt, carried on the MPCC `ConversationEvent` envelope with byte-identical sub-schemas, parity machine-enforced). EdgeX Foundry's lesson landed as a contract: ONE southbound interface, N protocol drivers — a driver speaks a protocol, it does not invent a vocabulary. **Normative invariant — a reading is ATTRIBUTABLE OR IT IS NOTHING**: `deviceRef`, `deviceProfileRef`, `profileDigest`, `metric`, `sourceAddress` and `unit` are all required, and the validator resolves every one of them across the example set (profile exists, digest matches the recomputed declaration, metric is declared, unit and source address agree, value is of the declared type and inside the declared range, `provenanceLinks` independently name both device and profile). Digest-pinning closes the retroactive-legalisation path — widening a range after the fact produces a new digest and orphans the readings it was meant to legalise, the `UpdateHealthProbe` construct applied to metrology. Quality is closed at five values with `unavailable` schema-bound to a null value plus a `NullAbsenceRecord` reference (the existing 12-kind MPCC absence taxonomy is reused, not re-invented); `stale` and `substituted` are normatively not `ok`. Simulated devices are a first-class labelled member of the protocol taxonomy (`protocol: "virtual"` ⇒ `synthetic:simulated-device`, enforced in both directions) — the `model-generated` admissibility rule applied to sensors. `observedAt`/`receivedAt`/`wallTime` stay distinct because `observedAt` → `receivedAt` is the southbound latency a twin's sync budget is spent on. Read-only at v0.1 (`access` closed to `"read"`): actuation must travel the `EffectRequest` → `EffectDecision` lifecycle. Distinct from `DeviceIdentity` (operator-workstation trust, bound via `identityRef`) and `TelemetryEvent` (agent-session diagnostics). Includes a BLE-GATT and a virtual profile plus measured and typed-absence reading examples, twenty-one negative conformance vectors (`fixtures/device-service/conformance.json`), a `validate-device-service-examples` target, and a normative spec note (`specs/device-service-contract.md`). Reference implementation: `device-service` in `SocioProphet/prophet-platform`.
- A/B fallback update contract v0.1 (TRUST FABRIC W9.2): `UpdateSlot` (one of exactly two slots, carrying the GPT priority-boot attribute triple `bootPriority`/`triesRemaining`/`successful`, the installed payload digest, and a deliberate `role` vs `currentlyRunning` split so the fallback slot stays describable during a trial boot), `UpdateTransaction` (one apply attempt: write target, pinned probe, per-attempt boot record naming where each failure fell back to, terminal `promoted`/`rolled-back`/`refused` outcome with a closed `rollbackReason` set), and `UpdateHealthProbe` (the digest-pinned promotion gate: non-empty check set with at least one blocking check, mandatory hardware+software watchdog pair enforced by two `contains` clauses, `evaluatedIn` closed to post-boot userspace, `onProbeUnavailable` closed to `fail`). **Normative invariant — the currently-good slot is never overwritten by the update being applied** — enforced three ways: by schema within a document (a top-level `not`/`anyOf` enumerating the two illegal `(fromSlot, toSlot)` pairs, plus `UpdateSlot`'s `state: writing` ⇒ `role: candidate`), by schema on the settle path (four if/then clauses pinning `settledOnSlot` to `fromSlot` on rollback/refusal and to `toSlot` on promotion), and across documents by the validator (a settled transaction's `preservedPayloadDigest` still equals the active slot's `payloadDigest`). The attempt budget follows the GPT attribute — decremented by the bootloader *before* control transfers, so a payload that hangs before userspace still consumes an attempt — and `refused` is terminal, which is what ends the boot loop. Includes a refused-update and a promoted-update example set telling two coherent end-to-end stories, fourteen negative conformance vectors (`fixtures/ab-update/conformance.json`), a `validate-ab-update-examples` target whose probe-digest check is *recomputed* rather than read back, and a normative spec note (`specs/ab-fallback-update-contract.md`). Reference implementation: `AbUpdateMachine` in `sourceos-boot`.
- `make validate` now also runs the duplicate schema `$id` guardrail, which previously ran only in CI — a local run could not reproduce the check that gates the PR.
Expand Down
60 changes: 60 additions & 0 deletions docs/adr/0015-model-plane-inference-provenance.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
# ADR-0015: Model Plane inference-provenance schemas (Tranche 7)

**Date:** 2026-08-02
**Status:** `Proposed`

---

## Context

The SourceOS Model Plane spec (SP-SESSION-DOSSIER-20260609, "Tiered On-Device Intelligence with Governed Distillation") introduces Tranche 7 and calls for six sourceos-spec artifacts (T7-1..T7-6): `InferenceReceipt`, `ModelManifest`, `AdapterManifest`, `EscalationDecision`, `AdapterPromotionDecision`, and the addition of an `inference_provider` value to `AgentPassport.agent_class`.

The spec was drafted 2026-06-09 as pre-implementation. Since then the estate has landed an **Agent Machine / Model Carry** family that already covers a substantial part of the intended surface:

- `InferenceProvider` — inference providers modelled as a **separate typed object** (providerClass, endpointMode, executionProfile, `trustPosture`, `supportedModalities`, `requiresNetwork`), *not* as an `AgentPassport` class.
- `ModelResidency` — the spec's `ModelResidencyEvent` (residency state, cache tier, quantization).
- `SourceOSModelCarryRef` — the governed model/adapter reference (`carryPolicy`, `cachePolicy`, `mutableModelState: false`, router/governance refs).
- `ExternalModelProviderProfile` — the T4 external-frontier egress-governance surface (`promptEgressDefault`, `allowTrainingUse`, `promptHashOnly`).
- `AdapterDescriptor` — a **connector/actuation** adapter (api/cli/sdk/event/file), a different sense of "adapter" than a LoRA model adapter.

Authoring the T7 schemas naïvely would fork these canonical types. This ADR records what was added, what was reused, and what was deliberately deferred.

## Decision

Add three new schemas that sit **atop** the existing Model Carry family and reference it rather than restate it:

1. `InferenceReceipt` (T7-1) — the per-completion provenance primitive. References `InferenceProvider`, `ModelResidency`, `SourceOSModelCarryRef`. SEAM-015 teeth: any off-device (`sovereign_cluster`/`external_permitted`) receipt is schema-required to carry an authorizing `capabilityLeaseRef` and a non-empty `escalationChain`; an `on_device_only` receipt cannot have been escalated.
2. `EscalationDecision` (T7-3) — the governed tier / data-residency boundary crossing. SEAM-015 teeth: `verdict: permitted` is schema-impossible without a `capabilityLeaseRef` **and** `sensitivityCheck.result: pass`; a T4 crossing must name an `ExternalModelProviderProfile`; a refusal must state a `refusalReason` (including `prompt-unanswered`, the fail-closed resolution for non-interactive workloads).
3. `AdapterPromotionDecision` (T7-4) — governed LoRA-adapter promotion. SEAM-016/017 teeth: `verdict: promoted` is schema-impossible without `signatureVerified: true`, `allEventsConsented: true`, a named `promotedBy`, all `evalGates` passing (including `adversarialProbePassed`), and it always requires a `rollbackTargetDigest`.

Grant references use the existing `urn:srcos:lease:` (AgentCapabilityLease) prefix, not the spec's illustrative `urn:srcos:grant:`, which does not exist in the estate.

All three carry an optional `ledgerPrevHash` (append-only-ledger hash-chaining) and the receipt carries an optional `confidenceMethod`, both introduced from the design review as low-risk additive hardening.

**Deferred, pending decision (tracked as issues, not authored here):**

- **T7-2 `ModelManifest` / `AdapterManifest`** — a content-addressed store manifest overlaps `SourceOSModelCarryRef`, and "AdapterManifest" collides in name with `AdapterDescriptor`. Needs a decision on whether these are new types or extensions of the carry-ref, and a disambiguated name (e.g. `ModelAdapterManifest`).
- **T7-5 add `inference_provider` to `AgentPassport.agent_class`** — the estate already models inference providers as the separate `InferenceProvider` object, which appears to be a deliberate choice that keeps the five-class host-process model intact. Adding a sixth class is a core-ontology change (it breaks `tools/validate_agent_passport_examples.py` `EXPECTED_CLASSES` and touches ADR-0014's five-class model). This is Michael's call, not a mechanical widening.

## Alternatives considered

| Alternative | Reason not chosen |
|-------------|------------------|
| Author all six T7 schemas verbatim from the spec | Would fork `SourceOSModelCarryRef` / `InferenceProvider` / `ModelResidency` and collide `AdapterManifest` with `AdapterDescriptor` — stranded duplicates. |
| Add `inference_provider` to `AgentPassport` now | The separate `InferenceProvider` object is an apparent deliberate resolution; a sixth host-process class is a core-ontology decision that deserves explicit sign-off. |
| Fold provenance into `AgentMachineReceipt` | `AgentMachineReceipt` records machine-runtime events (probe/placement/model-load); per-completion inference provenance with escalation chains and confidence is a distinct concern. |
| Mint a new `urn:srcos:grant:` prefix per the spec text | The estate's grant primitive is `AgentCapabilityLease` (`urn:srcos:lease:`); a new prefix would fork the capability model. |

## Consequences

- Positive: the three headline properties the Model Plane claims over Apple Intelligence — visible inference provenance, consent-gated escalation, enumerable/governed distillation — are now schema-enforced with `if/then` teeth verified to fire both ways, and reuse the existing Model Carry vocabulary.
- Positive: the schema-level gates encode the design-review findings (∅-grant ⇒ no crossing; signature ≠ safety, so eval gates are also required; fail-closed background escalation; ledger tamper-evidence and confidence-method as optional hardening).
- Negative / follow-up: schema `if/then` cannot express the cross-document invariants (served-count == receipt-count reconciliation; ledger hash-chain continuity; base-model-digest match between promotion and adapter manifest; biometric-never-crosses-the-socket). These are delegated to ontogenesis SHACL (T7-8) and workstation-contracts conformance (T7-19) and are called out there.
- Negative: `ModelManifest`/`AdapterManifest` and the `inference_provider` class remain open, so Tranche 7 is not complete with this change.

## References

- SourceOS Model Plane — Architecture Specification v0.1 (2026-06-09), §VII–§X, §XIV
- ADR-0014 — Agent System domain (the five-class `AgentPassport` model)
- Reused: `schemas/InferenceProvider.json`, `schemas/ModelResidency.json`, `schemas/SourceOSModelCarryRef.json`, `schemas/ExternalModelProviderProfile.json`, `schemas/AgentMachineReceipt.json`
- SEAM-011 (non-local ledger), SEAM-014..017 (Model Plane seam registry, source-os T7-20)
30 changes: 30 additions & 0 deletions examples/adapter-promotion-decision.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
{
"id": "urn:srcos:adapter-promotion-decision:2026-06-10-summ-v3",
"type": "AdapterPromotionDecision",
"specVersion": "2.1.0",
"decidedAt": "2026-06-10T09:15:00Z",
"candidateAdapterDigest": "sha256:8888888888888888888888888888888888888888888888888888888888888888",
"replacesAdapterDigest": "sha256:9999999999999999999999999999999999999999999999999999999999999999",
"baseModelDigest": "sha256:1111111111111111111111111111111111111111111111111111111111111111",
"task": "summarization",
"evalReportDigest": "sha256:6666666666666666666666666666666666666666666666666666666666666666",
"evalGates": {
"regressionPassed": true,
"taskImprovementPassed": true,
"safetyPassed": true,
"determinismPassed": true,
"adversarialProbePassed": true
},
"signatureVerified": true,
"contributingOverrideEvents": [4471, 4488, 4512],
"contributingEventCount": 3,
"allEventsConsented": true,
"promotedBy": "michael@socioprophet.ai",
"verdict": "promoted",
"rejectionReason": null,
"rollbackTargetDigest": "sha256:7777777777777777777777777777777777777777777777777777777777777777",
"ledgerSeq": 9001,
"ledgerPrevHash": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"evidenceHash": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"evidenceRefs": ["urn:srcos:decision:promote-summ-v3"]
}
30 changes: 30 additions & 0 deletions examples/escalation-decision.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
{
"id": "urn:srcos:escalation-decision:2026-06-09-4471",
"type": "EscalationDecision",
"specVersion": "2.1.0",
"decidedAt": "2026-06-09T21:59:58Z",
"machineRef": "urn:srcos:agent-machine:workstation-01",
"task": "agent_classification",
"fromTier": "T1",
"toTier": "T3",
"fromResidencyClass": "on_device_only",
"toResidencyClass": "sovereign_cluster",
"trigger": "low-confidence",
"sensitivityCheck": {
"performed": true,
"result": "pass",
"classifierDigest": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"sensitiveCategories": []
},
"capabilityLeaseRef": "urn:srcos:lease:noetica-t3-escalation-9f2a",
"targetProviderRef": "urn:srcos:inference-provider:sovereign-cluster-teacher-70b",
"targetExternalProviderRef": null,
"inputHash": "sha256:4444444444444444444444444444444444444444444444444444444444444444",
"verdict": "permitted",
"refusalReason": null,
"policyDecisionRef": "urn:srcos:decision:escalate-4471",
"ledgerSeq": 4471,
"ledgerPrevHash": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
"evidenceHash": "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"evidenceRefs": []
}
33 changes: 33 additions & 0 deletions examples/inference-receipt.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
{
"id": "urn:srcos:inference-receipt:2026-06-09-8823",
"type": "InferenceReceipt",
"specVersion": "2.1.0",
"issuedAt": "2026-06-09T22:00:00Z",
"requestingAgentRef": "urn:srcos:agent-passport:com.socioprophet.noetica",
"requestingAgentClass": "third_party",
"capabilityLeaseRef": "urn:srcos:lease:noetica-t3-escalation-9f2a",
"providerDaemon": "inferenced",
"providerRef": "urn:srcos:inference-provider:sovereign-cluster-teacher-70b",
"tier": "T3",
"baseModelDigest": "sha256:1111111111111111111111111111111111111111111111111111111111111111",
"adapterDigest": null,
"tokenizerDigest": "sha256:3333333333333333333333333333333333333333333333333333333333333333",
"modelCarryRef": "urn:srcos:model-carry-ref:teacher-70b-q4k",
"modelResidencyRef": "urn:srcos:model-residency:cluster-node-01-teacher-70b",
"task": "agent_classification",
"inputHash": "sha256:4444444444444444444444444444444444444444444444444444444444444444",
"inputTokenCount": 1840,
"outputHash": "sha256:5555555555555555555555555555555555555555555555555555555555555555",
"outputTokenCount": 210,
"confidence": 0.94,
"confidenceMethod": "logit-entropy",
"latencyMs": 1240,
"escalatedFrom": "T1",
"escalationChain": ["urn:srcos:escalation-decision:2026-06-09-4471"],
"dataResidencyClass": "sovereign_cluster",
"computeDevice": "remote",
"ledgerSeq": 8823,
"ledgerPrevHash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"evidenceHash": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"evidenceRefs": ["urn:srcos:decision:route-8823"]
}
Loading
Loading