Proposal 045: Sensorium as a Local Enaction Stratum¶
Based on:
doc/normative/20-vision/VISION.mddoc/normative/40-constitution/CONSTITUTION.mddoc/normative/50-constitutional-ops/AUTONOMY-LEVELS.mddoc/normative/50-constitutional-ops/EMERGENCY-ACTIVATION-CRITERIA.mddoc/project/20-memos/orbiplex-monus.mddoc/project/20-memos/emergency-signal-v1-invariants.mddoc/project/30-stories/story-009-bielik-blog-arca.mddoc/project/40-proposals/013-whisper-social-signal-exchange.mddoc/project/40-proposals/019-supervised-local-http-json-middleware-executor.mddoc/project/40-proposals/022-monus-as-host-granted-local-observation-middleware.mddoc/project/40-proposals/078-weak-signal-harvester.mddoc/project/60-solutions/000-node/000-node.mddoc/project/60-solutions/009-monus/009-monus.md
Related configuration work (proposed):
Proposal 091: File-backed Configuration and Explainable Composition. P091 inventories Sensorium's module-local configuration sources and plans shared, owner-validated consumption. Observation/directive admission and signed action authority remain Sensorium responsibilities; an editable setting cannot replace them. Broader adoption is tracked by P091-001b/010a/015, not a reopened hard-MVP gate.
Related connector work (proposed):
Proposal 096: Sensorium BrainFlow Connector
defines one reusable acquisition package, versioned model profiles and independently
supervised device instances. P096-003 creation/restoration and P096-004's pinned
catalogue/private binding path are implemented; acquisition lifecycle, consent
and hardware qualification retain their gates. Its class is health-wearable: non-invasive
physiological measurement with sensitive-personal data. "Invasive" in the
connector policy taxonomy refers to privacy/access, not an implanted EEG device;
this proposal does not promote that connector class's implementation status.
Status¶
Accepted / hard-MVP implemented.
The current implementation status is owned by
doc/project/60-solutions/030-sensorium/030-sensorium.md. The hard-MVP slice is
complete for Sensorium Core admission/query, directive invocation, audit-only
outcomes, internal connector dispatch, the supervised Sensorium OS reference
connector, action-catalog sidecar authorization, and deferred Sensorium actions.
The remaining local Agora observation publication/subscription bus is a
post-MVP integration layer. The runtime already records publish_topics
metadata and exposes read surfaces; Sensorium MVP does not require Sensorium to
become a public or federated publication authority. Deliberate local and
cross-node exposure of bounded enacted representations is implemented
separately by Proposal 082 and Solution 046; it does not federate Sensorium's
local observation topics.
The local device discovery continuation is a planned, post-MVP extension. It does not reopen the completed directive or connector-dispatch slice, register available actions, or qualify device access.
Date¶
2026-04-18
Executive Summary¶
Sensorium already appears in the Orbiplex corpus as the Node's layer of contact with reality. The Vision describes it as the layer of adapters to the world: public-network readers, environmental sensors, microphones, cameras, GPS, weather, energy, safety signals, and other signal sources. The Constitution defines it as the organ that provides signals grounding intelligence in reality and limiting narrative or model drift.
Other documents already assume this role:
- emergency operations describe a
sensorium -> evaluation -> activationpipeline, - autonomy levels treat sensorium event logging and aggregation as routine bounded node activities,
emergency-signal.v1acceptssource/type = sensorium,- Monus can consume Sensorium-derived summaries when preparing local concern drafts,
- Whisper preserves
monus-sensorium-derivedprovenance when local observations materially shaped an outgoing social signal, - story 009 treats Sensorium as connector access to external sources such as arXiv, GitHub repositories, mailing lists, and news feeds,
- the Node solution already allows a sensorium provider to attach as a Node-scoped role through explicit protocol and API contracts.
This proposal makes that implied layer explicit, while widening the name of the layer from observation to enaction: Sensorium admits observations, but it also mediates intentional directives and the audit/outcome records through which a node acts in the world without losing policy, traceability, or consent.
The core maxim is:
Sensorium is not a grand connector specification. It is a thin stratum for local enaction, where complexity lives in connectors and Sensorium normalizes only the minimal exchange contract for observations, directives, diagnostics, and artifacts.
Sensorium should therefore be implemented first as a supervised local module or Node-attached component in the spirit of proposal 019. It should expose boring, bounded host-granted capabilities for observation submission, directive invocation, query, summary, status, and audit. It should not become a universal ontology of the outside world, a transport authority, a surveillance platform, or a replacement for domain modules such as Monus, Whisper, Arca, or emergency evaluation.
Problem¶
The system needs contact with external reality, but "connectors to the world" can become an unbounded design sink. If every connector type forces a new global protocol, Sensorium becomes too large before the Node can use it. If every consumer speaks directly to each connector, Monus, Arca, emergency evaluation, and future modules all acquire duplicated adapter logic and uneven policy checks.
The design tension is:
- connectors are necessarily messy because the outside world is messy,
- consumers need stable local observations, not raw connector-specific chaos,
- the Node must retain consent, minimization, audit, and capability boundaries,
- the protocol core should not absorb every sensor, API, OS integration, or data feed shape.
Without a thin Sensorium stratum, the system is pulled toward one of two bad forms:
- a large
SENSORIUM-CONNECTOR-SPECthat tries to standardize every possible connector class too early; - ad-hoc side channels where each module reads local files, shells out, calls external APIs, or watches devices under its own private policy.
Both forms complect connector mechanics with domain reasoning.
Decision¶
Ontological Preamble¶
Sensorium is the node's organ of contact with reality. Contact is not
unidirectional: every act of observation has a physical and informational
footprint (a camera indicator LED, a Bluetooth presence beacon, a network
probe, a disk access timestamp), and every directive has an observational
aspect (the result of a git push is itself news about the world). The four
lanes defined below — directive, observation, diagnostic, artifact — are a
classification of intent and grant class, not a claim about causality
or directionality. A single connector may legitimately span several lanes;
a purely observational grant still commits the operator to whatever
incidental effects the connector declares it cannot avoid.
This proposal explicitly rejects the input-organ / output-organ split. Treating perception and action as two separate sub-systems is a Cartesian relic that enactivist cognitive science (Varela, Thompson, Rosch) has repeatedly shown to misdescribe how organisms actually engage with the world. An organism's sensorimotor surface is one coupled loop, not two plumbing systems meeting in the middle. Orbiplex Sensorium honors this: it is a sensorimotor organ, where perception and action form a single contact surface with the world.
Intentional action is therefore a first-class Sensorium function, not
a concession, not an escape hatch, and not a secondary lane bolted onto a
primarily perceptual component. A connector that performs a git push,
emits a Bluetooth beacon, toggles a GPIO pin, or executes an allowed shell
command is exercising the same organ as a connector that reads GitHub
releases or watches a file — the organ of contact with the world.
Story-009 should therefore be read in two layers: its Phase 1 research
path is observation-only Sensorium consumption, while commit/push belongs
to an explicit Arca-mediated OS directive path with narrower grants.
What the directive lane buys is not raw capacity to affect the world: capacity-to-act is inherent to an organ of contact; permission-to-act is always grant-bound and policy-mediated. The directive lane therefore provides a sharper grant and audit regime: directive grants are narrower than observation grants, require explicit allowlist entries, and every directive emits a corresponding audit outcome. Successful directives that produce facts about the world may also emit linked observations that close the sensorimotor loop — the act itself becomes news about the world.
This framing follows the project's broader commitment to honoring the mechanics of the world rather than pretending processes are cleanly separable, while still holding contract boundaries firm where they protect the operator.
Stratum Definition¶
Define Sensorium v1 as a local enaction stratum:
- connectors own adaptation from concrete external systems into local observations,
- Sensorium owns admission, minimal normalization, local policy enforcement, traceability, and queryable read models,
- consumers such as Monus, Arca, emergency evaluation, and local agents consume host-granted Sensorium capabilities,
- network publication remains outside Sensorium and is handled by the appropriate protocol layer.
The implementation architecture is:
sensorium-coreis the Node-attached Sensorium Core component that owns admission, normalization, policy, read models, and the consumer-facing capability surface; in the current Node implementation this core is a Rust organ integrated into the daemon, while older Pythonsensorium-corecode is only a retired reference,- every Sensorium connector is a separate middleware module registered with the
host as
module_role: "sensorium-connector", - connectors communicate through the standard middleware init/report,
host-capability,
local-input-invoke.v1, andpeer-message-invoke.v1envelopes, - Sensorium does not define or own a second plugin API for connectors.
Nomenclature: Core, Connector, Action, Package¶
Sensorium terminology intentionally separates the stable organ from the replaceable adapters around it.
| Term | Meaning |
|---|---|
| Sensorium organ | The node's local sensorimotor contact surface with the world: observation, directive mediation, diagnostics, artifacts, policy, audit, and minimal normalization. |
Sensorium Core / sensorium-core |
The mediator and contract boundary of the organ. It exposes public Sensorium capabilities such as sensorium.directive.invoke, admits observations, resolves action ids, selects connectors, records outcomes, and hides connector implementation details from consumers. |
| Sensorium connector | A separate middleware module that adapts one class of external contact to Sensorium. It is not a plugin loaded by sensorium-core; it is a daemon-hosted middleware participant reached through the standard host capability dispatch layer. |
Sensorium OS connector / sensorium-os |
One concrete connector middleware for allowlisted operating-system actions. A deployment may replace it or create another connector with a different module_id, connector_id, action catalog, and implementation. |
| Connector action | A declarative entry in a connector's action catalog, for example story009.review.publish. An action is not a middleware module; it is an operation exposed by a connector and mediated by sensorium-core. |
| Middleware package | An installable artifact that may carry connector code, scripts, action declarations, UI fragments, and config fragments. A package can extend a connector without becoming the organ itself. |
This naming matters for authority. Consumers such as Arca, Dator, Monus, or a
role module do not depend on "the OS connector" as an object. They depend on a
Sensorium capability and an action contract. sensorium-core maps that contract
to a concrete connector under operator policy. That lets an operator replace
sensorium-os with another connector implementation, or run several connector
modules with different names and grants, without changing consumer code.
This is also distinct from json_e / json_e_flow. JSON-e Flow is an executor
backend and a concrete flow config is treated as one operational middleware
component. It is not a Sensorium organ and it does not mediate connector
selection. A JSON-e Flow may call sensorium.directive.invoke, but then it is
just another consumer of the Sensorium Core boundary.
This is not a compromise. It follows the same stratification Orbiplex already uses for autonomous units of local work: supervised middleware, explicit grants, module reports, readiness, shutdown, restart counters, and audit traces. Connector isolation is a feature, not overhead to be hidden.
Sensorium composition uses two existing Orbiplex primitives rather than a new pipeline engine:
- Point-to-point capability invocation for connector ->
sensorium-coreadmission. This is request/response and pull-shaped: a connector submits a candidate observation, orsensorium-coreinvokes a reactive connector with a directive. - Local Agora topic publication for
sensorium-core-> consumers distribution. This is push-shaped: after admission,sensorium-corerepublishes the normalized observation to a local Agora topic such aslocal/sensorium/observations/{signal-kind}so Monus, Arca, emergency evaluation, UI, and future consumers can subscribe without coupling to the connector.
This makes Sensorium a mediated bus, not a Rack/Express/Ring-style interceptor chain. The daemon's middleware "chains" are request lifecycle stages inside the daemon; domain composition is explicit and capability-routed. A pipeline exists only when a module intentionally builds one, as Arca does for workflow steps.
Topology summary:
Connector middleware modules
sensorium.github.releases
sensorium.arxiv.search
sensorium.os.action
|
| directive/result lanes over middleware invoke envelopes
| observation submit over host capability bridge
v
+---------------------------------------------------------------+
| sensorium-core middleware |
| |
| mediated admission pipeline |
| validate -> redact -> policy-gate -> admit/quarantine/reject |
| -> store -> publish |
+---------------------------------------------------------------+
|
| admitted observations only
v
+---------------------------------------------------------------+
| local Agora bus |
| local/sensorium/observations/{signal-kind} |
| local ACL + retention + SSE subscription |
+---------------------------------------------------------------+
|
| pull query or push subscription
v
Monus Arca emergency-eval UI future consumers
Invariant: consumers never call connector modules directly.
Goals¶
- Keep Sensorium local-first and capability-bound.
- Put connector complexity at the edge, not in the core Sensorium contract.
- Provide a small common observation shape usable by multiple local consumers.
- Preserve provenance: connector id, source reference, confidence, sensitivity, and policy.
- Make observation ingestion and query auditable.
- Support both human-facing summaries and machine-facing structured observations.
- Allow generalized connectors where useful, including an OS connector, without giving them ambient unrestricted power.
Non-Goals¶
- Define a full taxonomy of all connector types.
- Define a network-wide Sensorium federation protocol in v1.
- Make Sensorium a transport or publication authority.
- Let Sensorium directly publish
whisper-signal.v1,agora-record.v1, or emergency activation artifacts. - Replace Monus signal weighting, Whisper publication, Arca orchestration, or emergency evaluation.
- Give connectors unrestricted shell, filesystem, camera, microphone, network, or memory access.
- Freeze one global ontology for external reality.
- Define a Sensorium-specific plugin API parallel to the existing middleware extension surface.
Out of Scope for v1¶
The following items are intentionally outside the v1 acceptance boundary:
- mandatory OS connector support on every node,
- invasive connector classes such as microphone, camera, health/wearable, location, private inbox, or browser-history readers,
- federated Sensorium read-through to a neighboring node,
- a Seed Directory-backed connector class registry,
- streaming transport as a requirement,
- an in-process plugin system for Sensorium connectors,
- runtime addition of OS allowlist entries without an operator-signed configuration change,
- and treating the v1 schemas as immutable forever; additive evolution remains possible through explicit versioning and compatibility rules.
Proposed Model¶
1. Layer Split¶
The v1 stack is:
External world
-> Connector middleware module
-> Standard middleware invoke / host capability envelopes
-> Sensorium admission and minimal normalization
-> Local Agora topic publication
-> Local Sensorium observation store/read model
-> Pull queries and push subscriptions for Monus / Arca / emergency evaluation / UI
-> Optional downstream protocol layer
The key boundary is between connector and Sensorium:
- the connector knows how to talk to arXiv, GitHub, a local microphone, an OS command allowlist, a wearable, a weather endpoint, or a local file watcher;
- Sensorium only knows that an admitted observation has a source, time, kind, confidence, sensitivity, provenance, and policy, with subject and summary present when they carry useful meaning.
- consumers never route to connectors directly; they route to
sensorium-core, which selects and invokes connector modules when active observation is needed.
2. Connector Responsibility¶
A connector is responsible for:
- concrete integration with one external source or source family,
- authentication to that source if needed,
- polling, streaming, scraping, shelling out, device reading, or API calling,
- transforming raw source output into a small observation candidate,
- attaching connector-local evidence references,
- classifying sensitivity before submission,
- applying source-specific pre-redaction before Sensorium admission when possible,
- surfacing health and last-observed status,
- registering itself through middleware init/report as
module_role: "sensorium-connector"with connector metadata.
Connector-side redaction is useful but never authoritative. It is a source adapter optimization: the connector may know that one source field is always unsafe to emit. Sensorium still owns admission-time redaction, quarantine, rejection, and the final policy visible to consumers.
A connector module report should declare at least:
module_role: "sensorium-connector",connector_class,connector_sensitivity_baseline,- offered
action_idvalues for action-oriented connectors, - offered
signal_kindvalues for source-specific observation connectors, - the connector-facing capability names the host may grant,
- and
connector_incidental_effects: a declared, operator-visible list of footprint effects that the connector cannot avoid while active, even when only an observation-lane grant is in use. Typical entries arecamera-indicator-led,bluetooth-presence-beacon,network-probe-traffic,disk-access-timestamp-update, andradio-emission. This field makes the ontological preamble concrete: it is the connector's honest declaration that contact is not free. The host UI surfaces these effects at grant time, and admission audit records retain them for after-the-fact review.
The role marker is for discovery and routing. Capability names remain the unit of grant and authorization. Incidental-effect declarations are neither a grant nor a capability — they are a transparency contract that binds the host UI and the audit trail.
Connectors MAY be specialized, for example:
sensorium.github.releases,sensorium.arxiv.search,sensorium.weather.local,sensorium.microphone.alarm,sensorium.wearable.heart-rate.
Connectors MAY also be generalized when the operator can define a safe bounded dictionary of actions. The primary example is an OS connector.
3. Connector I/O Lanes¶
The Unix stdin / stdout / stderr split is a useful inspiration for
connector design, but the Sensorium contract should model logical lanes, not
process streams. A connector may run as a process, local HTTP service, in-process
adapter, queue consumer, or future streaming worker. The common contract is the
shape of exchange, not the transport mechanics.
These lanes are carried by the standard middleware peer/local-input envelopes and host-capability calls. They are not a new Sensorium transport.
A reactive connector SHOULD expose up to four logical lanes:
- Directive lane — host or Sensorium instructions to the connector. This is
the
stdin-inspired lane: action id, filters, query, observation window, timeout, byte budget, redaction profile, and policy constraints. - Observation lane — normal structured output. This is the
stdout-inspired lane: JSON observations, summaries, timelines, or other data that can be represented as text-shaped JSON. - Diagnostic lane — structured errors, warnings, partial-failure notices,
retry hints, and degradation reports. This is the
stderr-inspired lane, but it remains JSON and is not mixed with observations. - Artifact lane — optional raw or binary outputs, such as audio snippets, images, raw telemetry, HTML captures, dumps, or source payloads. These SHOULD be returned by reference rather than inline when they are large, sensitive, or not naturally JSON-shaped.
This split keeps three facts separate:
- what the connector was asked to do,
- what it observed about the world,
- and what happened inside the connector while trying to observe it.
For example:
{
"schema": "sensorium-connector-directive.v1",
"invocation/id": "inv:local:01J...",
"connector/id": "sensorium.os.action",
"action/id": "git_recent_commits",
"params": {
"limit": 20
},
"budget": {
"timeout_ms": 5000,
"max_output_bytes": 65536
},
"policy": {
"allow_artifacts": false,
"redaction_profile": "default"
}
}
A connector response may contain observations, diagnostics, artifacts, or a combination of those lanes:
{
"schema": "sensorium-connector-result.v1",
"invocation/id": "inv:local:01J...",
"status": "partial",
"observations": [
{
"schema": "sensorium-observation.v1",
"schema/v": 1,
"connector/id": "sensorium.github.releases",
"signal/kind": "release",
"subject/kind": "github-repository",
"subject/id": "speakleash/bielik",
"summary": {
"lang": "en",
"text": "A new Bielik release candidate was observed."
}
}
],
"diagnostics": [
{
"level": "warning",
"kind": "rate-limit-near",
"message": "GitHub API budget is close to exhaustion.",
"retry_after_sec": 900
}
],
"artifacts": [
{
"artifact/ref": "orbiplex:blob:sha256:...",
"media_type": "application/json",
"role": "raw-source-response",
"sensitivity/class": "public"
}
]
}
The lane-level invariants are:
- diagnostics are not observations,
- raw artifacts are evidence or source material, not normalized observations by default,
- every directive should carry an invocation id, timeout, and output budget,
- every directive action must be finite and timeout-governed; Sensorium connectors, including the OS connector, must not use directive execution to host long-lived daemons, watchers, subscriptions, model workers, or open-ended streams. Long-running behavior belongs in a separately supervised middleware module or connector; a directive may only invoke a bounded command that samples, checks, transforms, or triggers one action and then returns. Asynchrony, threads, watchers, queues, caches, and streaming are allowed behind the invoked script boundary, but the directive boundary must linearize them into one bounded invocation result,
- a directive that needs longer work may use the explicit deferred-operation extension from Proposal 055: the initial invocation still returns quickly with an operation handle, while the host owns retry cadence, expiry, cancellation, and final timeout policy. Deferred mode is not the default sync contract,
- every artifact should carry media type, sensitivity class, and preferably a content-addressed reference,
- partial success is valid: observations may coexist with diagnostics,
- a connector may emit an operational observation that a submitted action result
was invalid, but that observation must be a normal admitted world/control fact
(for example
ai.orbiplex.sensorium/action-invalid), not a replacement for the structured diagnostic or the directive outcome, - the directive lane never bypasses host-granted capability policy.
The v1 lane mapping is:
- directive lane:
local-input-invoke.v1orpeer-message-invoke.v1dispatched bysensorium-coreto a connector module, - observation lane:
sensorium.observe.submithost capability call from the connector tosensorium-core, - diagnostic lane: a structured field in the same invoke or submit response, never mixed into the observation list,
- artifact lane: reference to a host-owned artifact store entry, such as the
existing module artifact write surface (
POST /v1/module/artifact/write).
The lane mapping covers connector -> sensorium-core communication. It does not
define consumer fan-out. Consumer fan-out is handled after admission through
pull queries and local Agora topic subscriptions.
4. Generalized OS Connector¶
An OS connector MAY expose a whitelist such as:
{
"actions": {
"git_recent_commits": {
"argv": ["git", "log", "--oneline", "-n", "{limit}"],
"cwd_policy": "configured-repository",
"params": {
"limit": { "type": "integer", "minimum": 1, "maximum": 50 }
}
},
"disk_free": {
"argv": ["df", "-h", "{path}"],
"params": {
"path": { "type": "string", "enum": ["/", "/var", "/tmp"] }
}
}
}
}
The connector MUST treat this as action -> argv, not as raw arbitrary shell
strings. A safe OS connector should enforce:
- an explicit action allowlist,
- typed parameter validation,
- no shell interpolation by default,
- timeout,
- output byte cap,
- stderr capture policy,
- working-directory allowlist,
- environment allowlist,
- redaction rules,
- per-consumer capability grants,
- and audit events for every invocation.
No action may be added, removed, or changed at runtime without an operator-signed configuration change. A distribution may ship a reference OS connector, but it remains an optional concrete connector to the local operating system, not a built-in Sensorium privilege and not a requirement for Sensorium MVP.
This gives operators a practical adapter to local reality without turning Sensorium into ambient shell access.
Directive Invocation Contract¶
Consumers such as Arca, Dator, or local agents that need to use a Sensorium
connector for intentional action do not address connectors directly and do
not hold connector-level capabilities. They address sensorium-core through
one mediated capability, by action_id, with typed parameters.
Invocation path¶
consumer (Arca / Dator / agent)
│ capability: sensorium.directive.invoke
▼
sensorium-core
│ grant check, parameter schema validation, allowlist resolution
│ (local-input-invoke or peer-message-invoke)
▼
target connector (e.g. sensorium.connector.os,
sensorium.connector.git)
│ typed execution
▼
sensorium-core
│ emits audit outcome; optionally emits world-fact observation
▼
result to caller, carrying outcome/id and observation/ids
sensorium-core mediates every directive. Consumers never talk to a
specific connector module and never discover connector_id values. This
keeps policy enforcement, audit, and outcome/observation linkage in one place, and
lets the operator replace a connector implementation without touching any
consumer.
Addressing model¶
action_idis a flat, globally enumerable string managed by the operator in the signed allowlist configuration (dotted notation recommended:os.process.spawn-read-only,git.push,bluetooth.beacon.emit),connector_idis implementation metadata held bysensorium-coreand never exposed to consumers,- the allowlist entry binds an
action_idto aconnector_id, a typed parameter schema, and execution limits, - consumers discover available actions through
sensorium.directive.list, which returns only those the caller may invoke together with their parameter schemas (a HATEOAS-shaped discovery surface).
Consumer-side capability grants are scoped against action_id patterns
(for example sensorium.directive.invoke scoped to os.process.* for an Arca
workflow run), not against connector_id.
Directive envelope and result¶
The directive envelope, the result envelope returned to the caller, and the audit-only outcome record are defined as v1 schemas:
doc/schemas/sensorium-directive.v1.schema.jsondoc/schemas/sensorium-directive-result.v1.schema.jsondoc/schemas/sensorium-directive-outcome.v1.schema.json
These files retain "x-dia-status": "draft" as schema metadata independently
of this proposal's accepted hard-MVP status. They are the
implementation-facing v1 schemas for Sensorium directive invocation, caller
results, and audit-only outcomes.
Request envelope (sensorium-directive.v1), semantic summary:
schema— tagsensorium-directive.v1.schema/v— schema version, currently1.directive/id— opaque identifier assigned by the issuer (ULID recommended); threads the request to its outcome and any observations.directive/issued_at— RFC 3339 timestamp.issuer— identity of the invoking party.participant/did:keyis the sovereign participant axis;module_ididentifies the local module when applicable;node_idMAY identify the local node context. At least one ofparticipant/did:keyormodule_idis required.issuer_delegation— optional proposal-032DelegationProoffor proxy-key signing. In v1, sub-delegation chains are not supported;max_chain_depth, when present, MUST be0. Ifissuer_delegationis present, the directive signature MUST be produced byissuer_delegation.proxy_key, andissuer_delegation.principal_keyMUST derive toissuer.participant/did:key. Verifiers MUST normalizeissuer.participant/did:keyto theparticipant:did:key:...canonical form before comparing it to the participant derived fromissuer_delegation.principal_key.signature— optional Ed25519 signature over the canonical directive payload. It is required by schema whenissuer_delegationis present.idempotency/key— optional caller-provided key used with issuer andaction_idto make async/retryable directive retries safe.action_id— public, operator-allowlisted action identifier (dotted notation, e.g.os.process.spawn-read-only,git.push). Consumers address actions byaction_id, never byconnector_id.parameters— typed peraction_id, validated bysensorium-coreagainst the allowlist entry's parameter schema before dispatch. No raw command strings, script bodies, or SQL.evidence/inputs— optional artifact references using the minimal artifact-lane contract below.timing.timeout_msandtiming.mode— bounded duration.timing.timeout_msis the directive-level deadline enforced bysensorium-core: it covers the interval from directive admission through connector dispatch and execution to final outcome recording. The operator-signed action allowlist MUST definedefault_timeout_msandmax_timeout_ms;sensorium-coreMUST reject or clamp requests exceedingmax_timeout_ms. On expiry, exactly onesensorium-directive-outcome.v1is written withoutcome/status: "timed_out"andpolicy/decision.decision: "timeout".deadline_at— optional absolute RFC 3339 deadline propagated from the caller's enclosing workflow or service dispatch. When present,sensorium-coreand the connector enforce the smaller of the local timeout/max-timeout and the remaining time untildeadline_at. This prevents asymmetric traces where the role module, Sensorium outcome, and connector execution report different timeout boundaries for the same directive.syncreturns final status;asyncreturnsstatus: "admitted"and the caller reconciles completion through the audit outcome and optional linked observations filtered bycorrelation/id.correlation/id— optional opaque thread through a higher-level plan (Arca workflow run step, Dator task dispatch, agent plan).
Result envelope (sensorium-directive-result.v1), semantic summary:
schema— tagsensorium-directive-result.v1.schema/v— schema version, currently1.directive/id— echo of the request.correlation/id— optional echo of the request correlation id.status—admitted|completed|failed|timed_out|rejected.result— typed peraction_idagainst the allowlist entry's result schema; absent or null forrejectedand asyncadmitted.outcome/id— always present; identifier of thesensorium-directive-outcome.v1audit record (see Loop closure invariant below). Outcome records are audit-only and never reach Agora topics.observation/ids— always present; empty list means no world-fact observation has been produced, one element is the ordinary case, many elements represent multi-emit directives.artifacts— references to produced artifacts.diagnostics— optional connector hints (info/warn/error).
Outcome record (sensorium-directive-outcome.v1), semantic summary:
schema— tagsensorium-directive-outcome.v1.schema/v— schema version, currently1.outcome/id— audit outcome identifier; exactly one per directive.directive/id— id of the originating directive.outcome/status—admitted|completed|failed|timed_out|rejected.outcome/recorded_at— time at whichsensorium-corewrote the audit record.directive/signature_digest— optionalsha256:...digest of the originating directive signature bytes, preserving audit linkage without duplicating the full signature in every outcome record.action_id,issuer,connector/id, andconnector/kind— dispatch context; connector fields may be absent when rejection happened before connector selection.connector/dispatched_at— optional time at whichsensorium-coredispatched the directive to the selected connector.connector/responded_at— optional time at whichsensorium-corereceived the terminal connector response; absent when timeout happens before a response arrives.started_at,completed_at, andduration_ms— optional connector or execution telemetry. These are not source/instrument event times; facts discovered in the world belong in linkedsensorium-observation.v1records.policy/decision— compact reason/retryability summary;decisionis one ofadmit,reject,timeout, orfail.retry/attempts— number of execution attempts made for this outcome.issuer_delegation— optional proof copied from the originating directive when proxy-key signing was used.audit/store— optional host-owned audit sink reference; outcomes are retrieved through restrictedsensorium.audit.*capabilities.observation/ids— zero or more linked observations produced by the directive.artifactsanddiagnostics— references and structured diagnostic hints, never a replacement for the audit status.
Key modeling decisions:
- Parameters are typed per
action_id, validated bysensorium-coreagainst the schema held in the allowlist entry before the connector is invoked. No field is a raw command string or a free-form script body. An action likeos.process.spawn-read-onlytakes structured arguments; there is nocommand: "rsync -avz ..."escape hatch. evidence/inputspasses large inputs by artifact reference rather than inline, aligning with the artifact lane.- Issuer delegation follows proposal 032.
issuer_delegationis an inlineDelegationProofand is excluded from the surrounding directive signature payload. The proof carries its ownprincipal_signature; the surrounding directive signature is verified withproxy_key. Sensorium treats the proof as open-world data for forward compatibility, but verifies only the proposal-032 compact proof payload fields. correlation/idthreads directives through Arca workflow runs, Dator task dispatches, or agent plans, so the audit trail preserves causal chains.- Sync vs async is a
timing.modeflag, not a separate endpoint.asyncreturnsstatus: "admitted"immediately together with anoutcome/id. Completion is recorded in the host-owned audit trail; if the directive also produces a world-fact observation, consumers with suitable grants may observe the linkedsensorium-observation.v1throughlocal/sensorium/observations/{signal-kind}filtered bycorrelation/id. outcome/idis mandatory;observation/idsis always a list. Every directive produces exactly onesensorium-directive-outcome.v1audit record (see Loop closure invariant below); only directives whose execution produces a fact about the world also produce one or more linkedsensorium-observation.v1records. Rejected-at-admission directives carryoutcome/idand an emptyobservation/idslist; completed directives that touch the world carry one or more observation ids.
Connector-side declaration¶
Connectors declare invocable actions in their module report, alongside observations they emit without prompting:
{
"module_role": "sensorium-connector",
"connector_class": "OS",
"connector_sensitivity_baseline": "high",
"connector_incidental_effects": [
"disk-access-timestamp-update",
"network-emission"
],
"actions": [
{
"action_id": "os.process.spawn-read-only",
"parameters_schema": { "$ref": "schemas/os.process.spawn-read-only.params.v1.json" },
"result_schema": { "$ref": "schemas/os.process.spawn-read-only.result.v1.json" },
"emits_observation_kind": "git/fetch-result",
"default_timeout_ms": 30000,
"max_timeout_ms": 300000,
"execution_mode_support": "sync-only",
"deferred_profile": {
"preferred_retry_after_seconds": 15,
"preferred_max_ttl_seconds": 1800
},
"requires_grant": "sensorium.directive.invoke:os.process.spawn-read-only",
"artifact_outputs": ["stdout", "stderr"],
"reentrancy": "parallel"
}
],
"observations": [
{
"signal_kind": "filesystem/change",
"signal_family": "filesystem/change",
"emits_without_directive": true
}
]
}
The actions block is a proposal from the connector. It does not
become invocable until the operator promotes matching entries into the
signed allowlist; the module report alone grants nothing. This keeps the
allowlist the single authority over what the node may actually do to the
world, and keeps connector authors honest about what they are offering.
execution_mode_support is an operator-approved action property, not a caller
preference. The safe default is sync-only; timing.mode = "async" is rejected
before dispatch unless the signed allowlist entry says either or async-only.
deferred_profile carries connector/action hints only. The host still clamps
retry cadence and maximum lifetime through its deferred-operation policy.
Loop closure invariant¶
Every directive — whether it completes, fails, times out, or is rejected
at admission — results in exactly one sensorium-directive-outcome.v1
record written to the audit trail, with matching correlation/id and an
appropriate outcome/status (completed, failed, timed_out,
rejected). sensorium-directive-outcome.v1 records are not
published to local Agora topics and are not reachable through
consumer-facing subscription surfaces; they are reachable only through
host-owned audit capabilities.
Directives whose execution produces one or more facts about the world
additionally emit sensorium-observation.v1 records, linked to the
outcome by correlation/id and by mutual directive/id, outcome/id,
and observation/ids references. Only sensorium-observation.v1
reaches local/sensorium/observations/{signal-kind} topics.
The directive result envelope returned to the caller always carries
outcome/id and observation/ids; the latter is empty unless the
directive produced world-fact observations. This is how the
enactive loop closes without conflating ontological categories: the
act itself is recorded as an audit outcome, and the consequence in the
world — when there is one — is recorded as an observation.
Artifact-lane minimal contract¶
Sensorium v1 does not define a full artifact store. It only defines the reference shape that directive, result, outcome, and observation envelopes may use when a value is too large, binary, or policy-sensitive to embed inline.
The minimal artifact reference is:
{
"artifact/id": "sha256:...",
"role": "stdout",
"media_type": "application/json",
"size_bytes": 1234
}
Rules:
artifact/idis eithersha256:...ormemarium-blob:....roleis one ofstdout,stderr,produced-file, orraw-capture.media_typeandsize_bytesare optional hints.- The artifact content is stored and governed outside the envelope; the envelope only carries an auditable reference.
Hard rails¶
- Consumers MUST NOT select
connector_id; onlyaction_idis a public handle. action_identries MUST NOT be added, removed, or changed at runtime without an operator-signed allowlist update.- A single
action_idMUST NOT accept a raw shell string, raw script body, or raw SQL as a parameter. If a shell-runner shape is genuinely required, the action takes ascript_idreferring to a signed, stored script in the host-owned module store. - Every directive, regardless of outcome, MUST emit exactly one
sensorium-directive-outcome.v1audit record. No silent execution. sensorium-directive-outcome.v1MUST NOT be published to the local Agora bus. Outcome records are reachable only through host-owned audit capabilities.
5. Sensorium Responsibility¶
Sensorium is responsible for:
- admitting or rejecting connector-submitted observation candidates,
- assigning stable local observation identifiers,
- enforcing local policy gates,
- normalizing into the minimal observation contract,
- storing recent observations or forwarding them to Memarium under policy,
- deriving read models such as timelines, topic summaries, and connector status,
- exposing host-granted query and summary capabilities,
- recording local topic metadata for admitted observations and, in the post-MVP subscription-bus layer, publishing them to local Agora topics under policy,
- emitting audit records for admission, rejection, query, and redaction.
Sensorium SHOULD NOT embed connector-specific parsers in its core. If a source requires special parsing, that logic belongs in the connector.
Connector discovery and routing¶
sensorium-core discovers connectors through middleware role registration. It
does not own a connector plugin registry and does not load connector code.
The daemon remains the source of active module reports. sensorium-core asks the
host for modules whose report declares module_role: "sensorium-connector" and
then routes directives to those modules through the same invoke envelopes used by
other supervised middleware flows.
Consumers such as Monus, Arca, emergency evaluation, and UI code MUST NOT bypass
sensorium-core to invoke connectors directly. Their stable dependency is the
Sensorium capability surface, not the connector fleet.
This module discovery is distinct from planned local device discovery: finding a registered connector is not scanning external devices. The latter uses the same mediated directive boundary and has its own bounded authority, private candidates and qualification gates below.
Mediated admission and local bus distribution¶
The left side of Sensorium is mediated and ordered:
connector -> sensorium.observe.submit -> validate -> redact -> policy-gate
-> admit/quarantine/reject -> store -> publish
Those phases may short-circuit. Rejection and quarantine are valid results and must produce diagnostics and audit records.
The right side is a local event bus:
sensorium-core -> Agora local topic: local/sensorium/observations/{signal-kind}
-> Monus / Arca / emergency-eval / UI / future consumers
After admission, sensorium-core SHOULD republish the normalized observation on
a local Agora topic. The recommended default topic shape is:
local/sensorium/observations/{signal-kind}
The local/ prefix follows proposal 046 and is part of the contract:
Sensorium observation topics are node-local bus topics and MUST NOT be
federated by default.
For example:
local/sensorium/observations/github-release
local/sensorium/observations/arxiv-paper
local/sensorium/observations/feed-item
Topic ACL, retention, and subscription policy MUST derive from the admitted
observation's admission.consumer_scopes, sensitivity class, and connector
class. Public release-feed observations and health/wearable observations should
not share the same retention or ACL merely because both are Sensorium records.
Local Sensorium topics MUST NOT be federated by default. Cross-node read-through
is implemented by Proposal 082 as an explicitly
published, exact-resource Sensorium Interface over authenticated direct-peer
pull-batch. It is not topic federation or observation replication.
One shared local/sensorium/observations topic with subscriber-side filtering remains
possible, but is not the recommended default because retention and policy differ
too much between connector classes.
Local Agora loopback cost¶
Using Agora as the local Sensorium bus does not currently mean an in-process shortcut. In the current Node shape, Agora v1 is a separate supervised process and Sensorium is another supervised component. A single admitted observation may therefore cross loopback more than once:
sensorium-core process
-> HTTP loopback to daemon host capability bridge
-> HTTP loopback to agora-service
-> agora-core inside agora-service
-> relay backend
If signing is performed through a separate host capability, the full path may also include a signing round-trip before ingest. This is acceptable for the observation lane because an admitted observation is already a durable, policy-gated fact that may pay for signing, canonicalization, persistence, and audit.
The optimization rule is:
- do not fight loopback for low-frequency observations,
- do not send diagnostics through Agora,
- do not send raw high-frequency samples through Agora,
- batch observation ingest before considering transport changes,
- consider Unix domain sockets or another local transport optimization only as a separate proposal after measurements show the need,
- do not embed
agora-coreinside Sensorium merely to avoid loopback.
Embedding Agora inside Sensorium would collapse the boundary this proposal is trying to preserve. Sensorium should not need to know Agora signing domains, backend details, relay internals, or storage mechanics. It publishes admitted facts through the host-owned capability surface and lets the host route to the current Agora implementation.
Redaction authority¶
Sensorium is authoritative for the final admitted observation. The connector may submit a pre-redacted candidate or a redaction hint, but Sensorium decides:
- whether the candidate can be admitted as-is,
- whether it must be transformed into a redacted observation,
- whether it must be quarantined for operator or policy review,
- or whether it must be rejected with diagnostics.
If a connector cannot redact a candidate and Sensorium has no policy for the candidate's sensitivity class, Sensorium MUST fail closed. The default outcome is quarantine when the payload can be safely retained locally without consumer access; otherwise the outcome is rejection with a diagnostic record. Quarantined observations are not visible to Monus, Arca, Whisper, emergency evaluation, or other consumers until a policy grants release.
6. Minimal Observation Contract¶
The initial contract is intentionally boring. The sensorium-observation.v1
schema lives in:
doc/schemas/sensorium-observation.v1.schema.json
It carries "x-dia-status": "draft" because proposal 045 remains draft, but
the schema itself is the v1 implementation contract for admitted local
observations.
Example shape:
{
"schema": "sensorium-observation.v1",
"schema/v": 1,
"observation/id": "obs:local:01J...",
"invocation/id": "inv:local:01J...",
"directive/id": "drv_01JGABCD...",
"outcome/id": "dout_01JG...",
"correlation/id": "arca-workflow-run-...-step-3",
"connector/id": "sensorium.github.releases",
"connector/kind": "public-network-reader",
"observed/at": "2026-04-18T10:00:00Z",
"connector/submitted_at": "2026-04-18T10:00:01Z",
"ingested/at": "2026-04-18T10:00:02Z",
"signal/kind": "release",
"subject/kind": "github-repository",
"subject/id": "speakleash/bielik",
"summary": {
"lang": "en",
"text": "A new Bielik release candidate was observed."
},
"confidence": {
"class": "high",
"rationale": "Observed from the upstream repository release feed."
},
"freshness": {
"ttl_sec": 86400
},
"sensitivity": {
"class": "public",
"redaction": "none"
},
"source/ref": {
"kind": "url",
"value": "https://github.com/speakleash/bielik/releases"
},
"evidence/refs": [],
"policy/hints": {
"shareable": false,
"memarium_admit_hint": true,
"requested_consumer_scopes": ["monus.read", "arca.read"]
},
"admission": {
"status": "admitted",
"redaction_status": "not-needed",
"memarium_admit": true,
"consumer_scopes": ["monus.read", "arca.read"],
"store": {
"record/id": "module-store:sensorium:obs:local:01J...",
"ttl_sec": 86400
},
"publish_topics": ["local/sensorium/observations/release"]
}
}
The shape is not meant to be a universal ontology. It is a common local envelope for observations. Domain-specific payloads MAY be attached later, but consumers should be able to make basic policy decisions from the envelope alone.
summary, subject/kind, and subject/id are optional in the v1 schema.
Text summaries are useful for human-facing facts such as releases or feed items,
but numeric samples and high-frequency aggregates should not be forced to invent
prose. Subjectless observations MAY omit subject fields; node-self measurements
SHOULD use a stable subject/kind: "self" convention rather than blank strings.
Observation timing has three distinct clocks:
observed/atis the source or instrument event time: when the thing happened in the world, according to the best available source clock.connector/submitted_atis optional connector telemetry: when the connector emitted or submitted the candidate observation tosensorium-core.ingested/atis Sensorium admission time: whensensorium-coreaccepted and wrote the admitted observation record.
This separation lets consumers reason about source lag
(connector/submitted_at - observed/at) separately from Sensorium admission lag
(ingested/at - connector/submitted_at). Connectors that cannot provide a
meaningful source/instrument timestamp SHOULD set observed/at to the time they
observed the event locally and MAY omit connector/submitted_at.
signal/kind and source/ref.kind use the lowercase slash-separated token
convention from proposal 046, extended with optional reverse-DNS vendor
prefixes (see Signal naming rule below). When an admitted observation is
published to Agora, each admission.publish_topics entry MUST match:
local/sensorium/observations/{signal-kind}
The normative JSON Schema pattern is:
^local/sensorium/observations/[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)*(/[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)*)*$
Signal naming rule¶
signal/kind is the authoritative, collision-resistant identifier.
Each /-separated segment is a dotted chain of lowercase tokens, which
allows connectors to carry reverse-DNS vendor prefixes when collision with
other providers is possible:
- bare short names (
release,github-release,filesystem/change) are legal and live in the community-common namespace; operators accept collision risk, - dotted prefixes (
com.apple.ios.accelerometer/x-axis,ai.orbiplex.workflow.completed) give vendor-owned, collision-free namespacing under RFC 1035-style domain ownership semantics, - Orbiplex-owned kinds SHOULD use the
ai.orbiplex.*prefix per proposal 046.
signal/family is an optional, connector-declared twin key that carries
the vendor-independent family name alongside the authoritative
signal/kind. It MUST NOT contain dots; the no-dot constraint is the
formal distinction between the community-common family namespace and the
dotted vendor namespace. Examples:
signal/kind |
signal/family |
|---|---|
release |
release |
com.apple.ios.accelerometer/x-axis |
accelerometer/x-axis |
org.otherdao.workflow.completed |
workflow/completed |
ai.orbiplex.workflow.completed |
workflow/completed |
The signal/family value is the connector's honest declaration of what
family of signal it is emitting. sensorium-core does not derive family
from signal/kind; consumers querying across providers (e.g. "any
accelerometer") use sensorium.observe.query filtered by
signal/family. Topic publication remains on signal/kind only; a
dedicated family-axis topic space is not introduced in v1 (a consumer
needing bus-level fan-in across vendors can subscribe broadly and filter
on the envelope).
Connectors declare both values in their module report alongside each emitted observation kind, so the operator sees the vendor-vs-family split at grant time:
"observations": [
{
"signal_kind": "com.apple.ios.accelerometer/x-axis",
"signal_family": "accelerometer/x-axis",
"emits_without_directive": true
}
]
Because the v1 schema describes the admitted record, not the pre-admission
connector submission, admission.store and admission.publish_topics are
required. admission.store carries the Node-owned module-store reference and
TTL metadata; admission.publish_topics carries the local Agora topic or topics
on which the observation is eligible to be made available under ACL. The
hard-MVP runtime records this metadata and serves read models; actual local
Agora publication/subscription is the later subscription-bus integration.
confidence.class in this proposal is Sensorium-local and intentionally not the
same contract as the emergency C0-C4 credibility scale. A promotion rule may
map Sensorium confidence into emergency credibility when creating an
emergency-signal.v1, but that mapping belongs at the emergency boundary rather
than in the base observation envelope.
policy/hints are connector-supplied requests or suggestions. Hint fields should
be visibly named as hints, for example memarium_admit_hint. admission is
the Sensorium-authored decision and is the only policy section that consumers may
treat as authoritative.
Reactive observations SHOULD carry invocation/id, directive/id,
outcome/id, and correlation/id so the
trace connects directive, connector execution, diagnostics, artifacts, and final
admission. Autonomous observations MAY instead carry a schedule, subscription, or
source-event reference once those shapes exist.
7. Host Capability and Subscription Surface¶
The first useful surface is split by direction.
Submit-side capabilities¶
Connector -> sensorium-core:
sensorium.observe.submit
sensorium.connector.*
sensorium.observe.submit admits a connector-produced observation candidate.
sensorium.connector.* capability names are connector-facing grant units such
as sensorium.connector.github.releases or sensorium.connector.os.
Internal dispatch (sensorium-core -> connector)¶
These are not consumer-facing and are not granted to modules outside
sensorium-core. They are the internal transport by which
sensorium-core reaches a connector after a consumer directive has been
admitted through sensorium.directive.invoke (see Directive Invocation
Contract above):
sensorium.connector.list (internal: connector inventory + declared classes)
sensorium.connector.status (internal: health, last success/error, freshness)
sensorium.connector.invoke (internal: dispatch an admitted directive to a connector)
sensorium.connector.invoke MUST NOT be granted to consumer modules.
Consumers always use sensorium.directive.invoke, which internally
resolves the action_id through the signed allowlist and performs the
actual connector-facing dispatch. This preserves single-point admission,
connector_id hiding, automatic outcome emission, and optional observation
linkage on loop closure.
Consumer-side directive capabilities¶
Consumer -> sensorium-core:
sensorium.directive.list
sensorium.directive.invoke
Consumer-side observation pull capabilities¶
Consumer -> sensorium-core:
sensorium.observe.query
sensorium.observation.get
sensorium.topic.summary
sensorium.health
For a supervised HTTP/JSON module, these may be exposed as local host capability requests rather than public network APIs. The Node grants them per module and per operator policy.
Suggested behavior:
sensorium.directive.invokesubmits asensorium-directive.v1with a publicaction_idand typed parameters;sensorium-corevalidates, dispatches, and returns the directive outcome together with linkedobservation/ids(empty when the directive produced no world-fact observations) (see Directive Invocation Contract).sensorium.directive.listreturns theaction_idvalues the caller is authorized to invoke, each with its parameter schema — a HATEOAS-shaped discovery surface.sensorium.observe.submitadmits a connector-produced observation candidate (connector ->sensorium-core, submit-side).sensorium.observe.queryreturns bounded observation records by time, subject, signal kind, connector, or sensitivity class.sensorium.observation.getreturns one observation by id if the caller has scope.sensorium.topic.summaryreturns a compact local summary for a topic or subject class.sensorium.healthreports module readiness and degraded dependencies.
Subject timelines are a query profile, not a separate v1 capability, unless a real consumer later needs a distinct optimized surface.
Consumer-side push subscriptions (post-MVP)¶
Consumer -> local Agora:
subscribe local/sensorium/observations/{signal-kind}
After the local subscription-bus integration is enabled, consumers may subscribe
to local Agora topics such as
local/sensorium/observations/github-release or
local/sensorium/observations/feed-item.
This uses the existing Agora topic-addressed pub/sub substrate and SSE
subscription path; it does not introduce a new bus engine.
The subscription path is still policy-gated. Consumers see only topics and records allowed by local ACL, admitted consumer scopes, and sensitivity policy.
8. Relationship to Monus¶
Monus consumes Sensorium, but Sensorium does not replace Monus.
- Sensorium observes and normalizes local reality-facing signals.
- Monus weighs admitted local signals over time.
- Monus prepares candidate concern drafts, recommendations, or do-not-publish decisions.
- Whisper publication remains a separate Node-owned and policy-gated path.
If Sensorium materially shaped a Whisper-bound concern through Monus, downstream
provenance should preserve monus-sensorium-derived.
9. Relationship to Emergency Evaluation¶
Emergency evaluation may consume Sensorium observations, but Sensorium does not decide emergency activation.
emergency-signal.v1 already sits above raw connector telemetry and below
activation decisions. Sensorium may supply source observations that an emergency
pipeline transforms into emergency-signal.v1, but trigger classification,
corroboration thresholds, TC5 degraded-trust behavior, activation, TTL, and
post-crisis review remain emergency-domain responsibilities.
10. Relationship to Arca¶
Arca may consume Sensorium summaries as workflow inputs. For example, story 009 uses a research node with connectors to arXiv, GitHub repositories, mailing lists, and news feeds.
The healthy boundary is:
- Sensorium provides observations and summaries,
- Arca orchestrates workflow intent and task progression,
- external artifact movement remains in the chosen data plane, such as git, INAC, or another explicitly selected substrate.
Arca should not learn how to poll every external source itself when a local Sensorium capability can provide a bounded observation surface.
Story 009 can be the first full non-emergency Sensorium consumer because its research step can use observation records produced by an allowlisted OS connector. The OS connector opens the practical world first: network reads, git inspection, feed fetches, and similar operations can initially be modeled as operator-signed actions without introducing a separate connector class for each source.
The story remains stratified: Phase 1 research consumes admitted Sensorium facts
through sensorium.observe.query by subject/kind, subject/id,
signal/kind, and freshness; commit/push stays on the Arca task path. That Arca
task may later use sensorium.directive.invoke against the OS connector to run
the actual git commit or git push action under the signed allowlist.
11. Relationship to Memarium¶
Sensorium observations may be ephemeral or durable.
Memarium is the organ of durable memory and knowledge. Sensorium may forward selected observations into Memarium when policy allows durability. Sensorium should not assume that every observation deserves permanent storage.
A useful default split is:
- Sensorium keeps short-lived operational observations and connector state,
- Memarium preserves admitted observations that should not disappear,
- audit traces record why an observation was admitted, redacted, rejected, expired, or promoted.
12. Relationship to Whisper¶
Sensorium should not publish whispers.
Sensorium-originated signals can become part of a local reasoning chain:
Sensorium observation -> Monus weighting -> candidate concern draft
-> Node/Whisper review -> optional whisper-signal.v1 publication
This preserves the difference between:
- raw local observation,
- local interpretation,
- social-signal publication,
- and distributed correlation.
Acute personal emergencies should still prefer local help or emergency-assistance paths before Whisper. Whisper is for correlation-worthy distributed patterns, not the first response to likely cardiac arrest, fire, collapse, or comparable direct danger.
13. Relationship to Weak Signal Harvester¶
Weak Signal Harvester (Proposal 078) may consume configured Sensorium outputs as source material, but Sensorium does not own harvesting. Sensorium is the node's bounded contact surface with the world; the Harvester indexes, groups, and emits candidate findings into a review directory. Any later Whisper publication remains Node/Whisper-owned and approval-gated.
Policy and Safety¶
Sensorium is powerful because it touches reality. Its default safety posture must therefore be conservative:
- consent before invasive sources,
- data minimization by default,
- local-first processing,
- context separation between connectors and consumers,
- explicit capability grants,
- no ambient connector access to Node memory,
- no ambient consumer access to all observations,
- redaction before broader consumption,
- auditability for connector actions and observation reads,
- fail-closed behavior for high-sensitivity or high-risk connector classes.
Sensitive connector classes such as microphone, camera, health sensor, location, browser history, filesystem watcher, OS, and private inbox reader should require explicit operator policy and visible UI state.
Baseline connector class policy:
| Connector class | Sensitivity baseline | Default policy |
|---|---|---|
public-network-reader |
public |
admit locally with bounded TTL; no network publication |
feed-reader / mailing-list-reader |
public or community |
admit locally when source is public or explicitly configured |
OS |
operational-sensitive |
disabled by default; requires operator-visible grant screen, host-owned audit, and operator-signed action allowlist |
filesystem-watcher / private-inbox-reader |
private |
fail closed; explicit operator policy and redaction required |
microphone / camera / health-wearable / location |
sensitive-personal |
fail closed; visible UI state and explicit consent required |
Deployment Shape¶
The default architecture is:
Node host
-> sensorium-core middleware
-> sensorium-connector middleware modules
sensorium-core declares consumer-facing capabilities such as
sensorium.observe.query, sensorium.topic.summary,
sensorium.directive.invoke, and sensorium.directive.list. The
sensorium.connector.* family is reserved for internal
sensorium-core -> connector dispatch and is never granted to
consumer modules.
Each connector is a separate middleware module declaring
module_role: "sensorium-connector" and connector-facing capabilities such as
sensorium.connector.github.releases or sensorium.connector.os.
This keeps one extension mechanism:
- middleware init and module report for registration,
- host capability grants for authority,
- supervised lifecycle for readiness, shutdown, and restart,
- daemon traces for directive -> observation -> diagnostic accountability,
- independent language/runtime choice per connector.
The cost is process overhead. That cost buys isolation: a broken USB wearable
driver, hanging arXiv scraper, or camera crash should not take down
sensorium-core or unrelated connectors.
Deployment escape hatches¶
High-frequency sensor streams should not roundtrip every raw sample through HTTP. The connector should aggregate locally and submit only admitted observation candidates, for example "acoustic anomaly detected in a 4s window", with raw data kept behind artifact references when policy allows. Raw samples should not be published per-sample to local Agora topics; the connector boundary protects the bus from high-frequency flood.
Small devices such as SBCs may run only a few connectors. If measurements show
that a specific connector needs an in-process fast path, that fast path MAY be
implemented inside sensorium-core or as a tightly coupled sidecar, but it must
preserve the same directive/result/observation contracts and must not create a
general Sensorium plugin API.
Sub-10ms local reaction loops are also connector-specific exceptions. They may use a local fast path for detection, then emit normal Sensorium observations for admission, audit, and downstream consumption.
No-Sensorium Mode¶
Absence of Sensorium is a valid Node configuration. A Node without configured connectors remains a valid Node.
Consumers such as Monus or Arca MUST treat missing Sensorium capabilities as a degraded input condition, not as a runtime error. They may show reduced functionality, skip Sensorium-derived enrichment, or request operator configuration, but they must not fail the whole workflow merely because no Sensorium provider is attached.
Invariants¶
- Sensorium is local-first.
- Connectors adapt; Sensorium normalizes.
- Sensorium observations are not external network publications.
- Local Agora publication is a local bus mechanism and MUST NOT imply federation.
- Consumers receive only host-granted views.
- Connector-specific logic does not leak into every consumer.
- Raw sensitive data is not retained or shared unless policy explicitly allows it.
- Downstream artifacts preserve provenance when Sensorium materially contributed.
- Sensorium MUST NOT publish Whisper artifacts.
- Sensorium MUST NOT decide emergency activation.
- Sensorium MUST NOT own Arca workflow authority.
- Every Sensorium connector is a middleware module by default.
sensorium-coredoes not expose a connector plugin API.- Consumers MUST NOT bypass
sensorium-coreto reach connector modules. - Consumers reach observations either by pull capability queries or by push subscription to local Agora topics.
- Consumers MUST NOT become implicit next steps in a connector pipeline.
- OS is an optional connector class, not a built-in Sensorium privilege.
- No OS allowlist entry may be changed without an operator-signed configuration update.
- A single connector MAY declare and hold grants on multiple lanes;
observation-only grants still require explicit operator acknowledgement
of the connector's declared
connector_incidental_effects, and those effects are retained in the admission audit trail. - Sensorium observations are multi-consumer by construction; adding a consumer is a configuration change (grants, subscriptions), not a contract change in Sensorium or in any connector.
- Directive outcomes and world observations are separate record kinds.
sensorium-directive-outcome.v1records are audit-only and MUST NOT be published to local Agora topics. Onlysensorium-observation.v1records, which describe facts about the world, reach consumer subscription surfaces. - Absence of Sensorium is a valid Node configuration; consumers MUST degrade, not crash.
Resolved Design Decisions¶
The following decisions close the v1 design questions:
sensorium-observation.v1is promoted todoc/schemas/sensorium-observation.v1.schema.json. It is the implementation-facing v1 contract for admitted observations.- Admitted observations are stored in the Node-owned generic module store with TTL. Sensorium may keep read models and indexes, but the durable local substrate is host-owned.
- The first reference connector class is
OS: an allowlisted operating-system connector. It opens practical access to network tools, git, feeds, and local commands without defining one connector class per external source in Phase 1. - Local observation publication metadata uses per-kind local Agora topics. The
topic shape is
local/sensorium/observations/{signal-kind}, following proposal 046. Sensorium observations are never published to public/federated topics by default. The hard-MVP runtime records and validates this topic shape; actual local Agora publication/subscription is a post-MVP integration layer. - Story 009 Phase 1 uses Sensorium only for research facts, queried by
subject/kind,subject/id,signal/kind, and freshness. Commit/push remains on the Arca task path and may later invoke the OS connector to run allowlistedgit commitorgit pushactions. - Connector discovery uses both mechanisms:
module_role: "sensorium-connector"for discovery/routing andsensorium.connector.*capabilities for grants. - OS connector definitions and action allowlists are host-owned module store records. Simple public-network readers may begin with static configuration, but signed action definitions use host-owned storage.
- The minimal UI for OS is an operator-visible grant screen plus audit. Camera, microphone, location, and comparable invasive connectors require active UI status before they are enabled.
sensorium-directive.v1,sensorium-directive-result.v1, andsensorium-directive-outcome.v1are promoted to v1 schema files. They remain draft-status contracts because the implementation is not complete, but they are no longer candidate shapes.- Rejected directive outcomes are reachable only through host-owned audit capabilities. No restricted internal-only Agora topic is introduced until a concrete consumer, such as emergency evaluation, requires it.
- Cross-node Sensorium read-through is not part of this local-enaction v1 contract. Proposal 082 and Solution 046 now own the implemented, separate Sensorium Interface resource and gateway for explicitly granted observation and Workbench projections.
- Connector classes do not need a catalog in v1. Local module reports and grants are enough until federated connector interchange becomes real.
- The first production directive path should exercise a small OS action before
any invasive or high-risk connector is attempted. The reference action id is
os.process.spawn-read-only, initially used for a constrainedgit fetch origin <branch>against a configured repository. It is intentionally useful but bounded: it may update local git metadata and perform network egress, so it testsconnector_incidental_effects, allowlist policy, directive outcome, artifact references, and optional observation loop closure without makinggit commitorgit pushpart of story-009 Phase 1.
Implementation Acceptance Checks¶
The schemas are promoted, and the hard-MVP implementation has proven the contracts in the narrow local path:
sensorium-observation.v1: connector ->sensorium-coreadmission -> Node-owned module store with TTL -> query/topic-summary read models. Local Agora topic publication tolocal/sensorium/observations/{signal-kind}is a post-MVP subscription-bus integration, not a hard-MVP gate.sensorium-directive.v1: consumer ->sensorium.directive.invoke-> allowlist resolution byaction_id-> internalsensorium.connector.invoke.sensorium-directive-outcome.v1: exactly one audit-only outcome per directive, written to the Node-owned module store and reachable only through restrictedsensorium.audit.*capabilities.sensorium-directive-result.v1: caller response always carriesoutcome/idandobservation/ids; async callers can reconcile later through audit and observation links.- Artifact lane: produced stdout/stderr/files/raw captures are referenced by
artifact/idandrole, not embedded by default. - Delegation: if a directive carries
issuer_delegation, validation follows proposal 032 withmax_chain_depth: 0.
Local Device Discovery Continuation¶
Scope, provenance and status¶
Decision recorded on 2026-10-13: extend the existing local directive boundary with bounded device discovery. Human agency and privacy at the upstream Vision/Constitution boundary become three separate decisions here: detect a candidate -> approve a binding -> authorize acquisition. Detection establishes a scoped observation of availability, not ownership, identity proof, wearer consent or permission to use a device.
This section owns the common contract and continuation tracker. It is planned design, with no new runtime, frozen schema, machine capability entry or change to existing hard-MVP status. S030 records the planned solution responsibility. P096 owns the first BLE provider and its qualification; USB/serial and mDNS have contract fixtures in this continuation but deferred runtime providers. There is no new proposal or universal device registry.
Actions, profiles and planned data contracts¶
Consumers invoke sensorium.directive.invoke with the operator-admitted
action_id device.discover.ble, device.discover.usb-serial or
device.discover.mdns. These are planned action names, not currently available
catalogue entries. connector_id stays internal. Reuse action-catalogue
admission, signatures, action-scoped grants and internal connector routing
under P072; do not create a parallel
sensorium.device.discover capability or transport capability registry.
The common draft contracts frozen on 2026-10-13 are:
| Contract | Semantics frozen in P045-DISC-001 |
|---|---|
sensorium-device-discovery.request.v1 |
Exact profile revision/digest, discovery/mode: passive | active, typed transport scope and filters, caller-bound operation/idempotency context, finite window/deadline, candidate-count/byte and progress budgets; host-derived authority is never accepted as a caller assertion |
sensorium-device-discovery-candidate.v1 |
Opaque candidate/ref, operation/caller/profile/scope binding and expiry; bounded untrusted label; selector kind and identity evidence with method, provenance and validity scope; private provider-local selector material |
sensorium-device-discovery-result.v1 |
Bounded current candidate snapshot, disclosed-candidate count and domain completion reason/partiality, linked to the operation; no nonmatching identifiers/counts, automatic observation or artifact |
The canonical schemas in doc/schemas/, synchronized Node mirrors and Schema
Gate validators now define these fields. Portable limits are 16 KiB per request,
64 candidates, 32 KiB per encoded candidate vector and whole progress snapshot,
1–30,000 ms observation window, a deadline no longer than 45,000 ms and no shorter
than the window, 100–5,000 ms progress cadence, and 1,000–120,000 ms candidate TTL.
Host admission may narrow every bound, reserve additional cleanup time and refuse
unsupported modes before I/O. Revisions are positive JSON-safe integers; providers
have at most 300 cadence updates within the largest observation window. Terminal
and expiry transitions remain bounded separately. BLE, USB/serial and mDNS profile
fixtures freeze transport effects and identity evidence without promising a
runtime provider. Structural and semantic negative vectors are distinct.
A request
can narrow an admitted profile and host policy, never widen them. Backend
capability determines whether a mode is available: if true passive discovery
cannot be provided and enforced, return a typed refusal before I/O rather
than run active discovery. Mode describes transport behavior; it is independent
of the P048 execution/effect class. Port probing is excluded; a future probing
action would need its own contract and grant.
Selector kinds advertised-name, transport-address and verified-serial
are evidence categories, not an ordered trust ladder. A serial field alone is
not verification: evidence names the verification method, source and where/
when it remains valid. A display label is never a stable device identity.
Provider registration and bounded lifecycle¶
A discovery provider is registered independently of an acquisition instance. Reuse the adapter-neutral middleware instance plan, package/signature admission, supervisor and invocation channel. Registration may persist; a scan session may not. The host starts an admitted executor for one bounded S029 operation and ends that executor after confirmed completion or enforced cleanup. There is no new supervisor and no requirement to activate a BrainFlow instance in order to find its device. Generic instance materialization remains pure: it consumes an approved binding and performs no scan, pairing, permission grant or acquisition.
Before transport I/O the host atomically obtains the relevant shared transport claim. Discovery and acquisition check conflicts in both directions under the same claim owner/fencing mechanism planned by P096-005. V1 refuses discovery while acquisition owns the same controller, and refuses acquisition while a scan or uncertain cleanup owns it. Different device names do not prove different controllers; an unknown sharing relation is a refusal. P096-005 supplies the reused mechanism, not a second discovery lock.
Cancellation ends only this provider's discovery session. It cannot disable the whole Bluetooth controller or interrupt another owner. Release requires backend confirmation, or deployment-qualified proof that verified executor exit releases that backend session. Process death by itself is insufficient. On expiry, revocation, provider hang or uncertain cleanup, fence disclosure and binding consumption first, enforce the cleanup deadline, retain/quarantine the claim until release is proven, and report uncertainty rather than successful cancellation. The same rules cover normal completion with failed cleanup. Restart never resumes scanning or restores candidate lists; it must reconcile unreleased resource claims before admitting conflicting work.
Execution effects and unsupported-enforcement refusal are owned by P048. BLE radio access, USB/serial enumeration and multicast are distinct effects: current C1/C4 labels do not automatically contain arbitrary implementations. Qualification records the actual host -> supervisor -> provider launch chain, OS access and attribution. The P096 terminal/iTerm TCC lab observations do not qualify a launchd daemon or another launch context.
P096's finite qualification bootstrap owns the separate authority to measure an exact normal candidate before its native proof exists. It keeps ordinary catalogue/directive/generic-RPC effect routes closed and retains current OS access, consent, protected withdrawal and the same claim/cleanup owners. Inert signed-package registration is not a scan grant; a consumed case authority cannot authorize a retry or ordinary discovery. Source facts, independent qualification and explicit adoption remain separate.
Private candidates and atomic binding¶
candidate/ref is short lived, bound to this operation, authenticated caller,
profile and transport scope. binding/ref is a stable host-owned reference
with its own current validity rules; it does not inherit acquisition authority.
Candidates expire with their declared TTL, host restart, or relevant authority
change. Never merge candidates from different providers; alias resolution and
exclusive device claims remain binding/P096-005 responsibilities.
A user may select a candidate from a running snapshot, but selection alone performs no binding write. The host waits for confirmed scan termination, then revalidates current candidate, profile, caller and binding authority. It creates the approved binding and consumes the candidate in one atomic transaction. Only successful creation consumes it; another request cannot use it to create a second binding. Exact retry of the already approved request returns the same binding, including after restart, through a minimal private binding receipt. It does not resurrect an unconsumed candidate or extend authority. Conflicting retries, stale candidates and another caller's read or consumption are refused. The receipt is binding-owner state, not a retained discovery list or discovery audit identifier.
Manual, operator-confirmed selector entry remains usable without discovery. P096-004's completed private binding path is preserved; the new candidate consumption route is an additive P096-017/018 integration, not evidence that P096-004 has already implemented scanning.
Minimization, budgets and private progress¶
Providers filter advertisements before they leave their process; the host
validates the admitted projection again. Nonmatching advertisements, their
identifiers and their counts leave neither boundary. All disclosed device
results default to sensitive-personal / Personal, including USB/serial.
Audit may retain admitted scope, time, outcome and disclosed-candidate count;
it retains no device/candidate identifiers, private lists or digests derived
from them. Scope in audit is a non-identifying profile/policy projection,
not echoed private filter values. Native logs, directive outcomes, receipts,
status registries and exported diagnostics must obey this projection too.
Candidate selectors remain only in bounded private operation state and an
explicitly approved binding's restricted owner store.
The approved binding owner's confined, owner-only recovery journal may retain
the exact binding-source integrity needed for atomic commit and crash recovery.
This is part of the restricted binding store: ordinary configuration events,
heads, audit projections and receipts must contain only closed lifecycle metadata
and independently allocated references, never those private-derived digests.
The legacy node:sensorium-core/src/lib.rs outcome builder copies a compact
result/summary from a connector result into its durable outcome. Discovery
must split its private response from the metadata result before this
builder too; compact summaries, result references and native diagnostic text
are not redaction. The same file's deferred_operation_seed hashes all request
parameters into a seed used for the retained operation identifier. For discovery,
use an opaque host-allocated operation identity and caller-scoped idempotency
mapping that are independent of private filters/candidates, rather than this
parameter-derived seed. Handles, causal/correlation references and receipt
material must not encode or hash private identifiers either. P045-DISC-002/004
must qualify these identity and directive-audit paths together with the S029
status-history hash boundary before provider exposure. Other v1 consumers keep
their existing identity and retention semantics.
There is no discovery-result history, automatic Sensorium observation, capture artifact, Agora/Room publication or federated export. Rate-limit admitted scans per caller and across the shared transport budget, persisting budget accounting across host restarts. Polling an existing operation spends no new scan budget. Periodic or autonomous retries need a separate domain policy; the Scheduler boundary does not confer it. Enforce finite duration, count, bytes, invocation rate, provider concurrency and polling bounds at their owners before exposure.
Labels remain untrusted. Apply byte/length bounds, escape markup and terminal control sequences, and visibly mark invisible characters using P026's presentation rules. Do not treat escaping in the console as permission to leak labels into audit.
First-stage incremental results reuse S029's existing status/poll/cancel path,
not a new channel. P055-10/11
and S029
plan deferred-operation-status.v2 with optional typed progress. V1 remains
supported with unchanged meaning; its extensions field must not acquire
permanent discovery semantics. Discovery is unavailable until the entire
host/provider/console path supports v2.
The caller-private progress projection contains a bounded replacement snapshot with increasing revision, not appended history. Every poll/status read rechecks caller identity and current disclosure authority. A selected candidate may disappear or expire before confirmation. Keep this private response separate from durable metadata status and audit: the current S029 registry hashes the whole supplied status, so candidate identifiers/bytes and derived digests must be excluded before its event/digest path, including terminal results. Restart can restore metadata and rate budgets, never lists.
Domain completion distinguishes window-completed (the planned observation
window ended), limit-reached and deadline-reached. The latter two are
explicit partial results. An orderly provider finish at the admitted domain
deadline is different from a host watchdog timeout; provider failure, policy
refusal and uncertain cleanup do not become ordinary partial success. A
finished observation window, even with zero candidates, claims only what was
seen in that scope/time, not that no device exists. Final results and binding
consumption require confirmed session cleanup.
Published Sensorium Interface catalogue discovery under P082 and S046 is a separate disclosure domain. An ephemeral local device candidate gives neither publication authority nor an Interface read grant, and an Interface catalogue cannot expose private physical device scans.
Scenario and failure contract¶
sequenceDiagram
participant U as Caller console
participant H as Sensorium host
participant P as Admitted provider
participant B as Private binding owner
U->>H: directive.invoke(action_id, admitted scope)
H->>H: Grant, profile, budget, effects and atomic transport claim
H->>P: Start bounded discovery operation
P-->>H: Filtered bounded replacement snapshot
U->>H: S029 status poll with current authority
H-->>U: Private status v2 progress and revision
U->>H: Select candidate and approve binding
H->>P: End own discovery session
P-->>H: Confirm session cleanup
H->>B: Revalidate and atomically bind/consume
B-->>U: Stable binding/ref (no acquisition)
| Failure or edge | Required behavior / retained evidence |
|---|---|
| Denied action/profile/mode/effect or expired authority | Refuse before executor start/I/O; include BLE allowed with network forbidden and unsupported passive mode |
| Simultaneous scan/acquisition, either arrival order | One atomic claim winner; refuse the other, including unknown shared-controller mapping |
| Provider hang, revoke, watchdog or uncertain cleanup | Fence all disclosure/consumption; enforce own-session cleanup, hold resource on uncertainty; no successful cancellation |
| Unrelated advertisements | Provider filter and host validation; prove no foreign identifiers/counts or derived private-list digest in logs/audit/status events |
| Different caller, expiry, restart or replay | Refuse read/new consumption; exact approved binding retry returns the original binding without a second allocation |
| Snapshot overflow or deadline | Bounded replacements/revisions; distinct partial reasons, no appended history or scan resume |
| Misleading label or cross-provider alias | Safe display, separate candidates; identity claims require scoped method/provenance, no implicit merge |
| USB/serial or mDNS fixture | No assumed radio or serial-port probing; explicit mDNS emission effects and untrusted announcements |
Implementation recommendations and trade-offs¶
Freeze portable data contracts and pure profile/transition validation first; keep BLE details in the provider. Reuse admitted middleware registration, supervised executor/channel, action routing, P096-005 fenced claims, the private binding owner and S029 operation lifecycle. Do not couple scan startup to a live device instance, widen C1/C4, overload status v1 or create a device registry.
One replacement snapshot bounds memory and disclosure but deliberately loses past sightings. Conservative same-controller exclusion sacrifices concurrent radio availability until qualified sharing exists. No passive fallback reduces backend availability in exchange for an enforceable effect contract. Separate binding approval and acquisition preserve consent at the cost of one explicit transition. Open implementation choices are exact profile budgets, enforcement backends and qualified cleanup evidence; their defaults stay fail closed until the owning tracker gates provide evidence.
Continuation tracker¶
All rows start todo; the document change completes design preparation only.
Dependencies are completion prerequisites. Solutions point here rather than
duplicating work. P055-10 freezes v2/private-retention semantics; P055-11 and
P045-DISC-005 integrate them without a circular prerequisite.
| ID | Work item | Depends on | Status | Completion gate and retained evidence |
|---|---|---|---|---|
P045-DISC-001 |
Freeze common contracts and admitted profiles | — | done |
Request/candidate/result data, authority, finite limits, states/reasons and scoped identity evidence; BLE, USB/serial and mDNS positive/negative fixtures; distinguish passive/active, no port probing |
P045-DISC-002 |
Admit packages and route actions | P045-DISC-001 |
todo |
Existing signed catalogue/P072 grants and Schema Gate; typed denial before provider spawn/I/O, network-denied BLE, no passive-to-active substitution; opaque operation identity and private-response split before directive audit; no available machine entry before implementation |
P045-DISC-003 |
Enforce lifecycle and transport resources | P045-DISC-001, P045-DISC-002, P096-005 |
todo |
Independent provider registration and bounded supervised sessions; atomic bidirectional scan/acquisition exclusion, unknown-sharing refusal, revocation/hang/cleanup uncertainty, claim recovery without scan resume; actual launch/access evidence |
P045-DISC-004 |
Own private candidates and binding consumption | P045-DISC-001, P045-DISC-002 |
todo |
Source filtering and host revalidation; no foreign counts/ids or private-list/filter-derived digests in any retained sink, including handles/causal refs/receipts; TTL/caller/scope fences, atomic one-use binding/idempotent retry, no cross-provider merge/history; commit waits for confirmed cleanup |
P045-DISC-005 |
Integrate typed private S029 progress | P045-DISC-003, P045-DISC-004, P055-10, P055-11 |
todo |
Coordinate P055-11 host/provider/console v2 path; bounded replacement revisions, current-authority polls, private projection excluded before durable hash, two partial reasons, no restart list/scan restoration; v1 regression |
P045-DISC-006 |
Deliver shared UI and CLI | P045-DISC-005 |
todo |
Same contracts for incremental display, cancel and approval; bounded escaped/invisible-marked labels, stale selection refusal, selection never starts acquisition; existing directives/manual binding regression |
P045-DISC-007 |
Qualify cross-cutting discovery acceptance | P045-DISC-006, P096-018 |
todo |
All failure-table cases and real first-provider launch/transport/stop/binding use; old S029 v1 and Sensorium directives preserved; USB/serial/mDNS contract-only evidence labelled, runtime deferred; exact tuple and scope, no capability promotion beyond tested evidence |
Implementation checkpoint, 2026-10-14: the isolated Node branch adds current signed package/runtime admission, an exact host-selected deployment, private directive/status routing, shared controller claims, bounded independent stop, atomic scope-bound binding receipts and explicit UI/CLI clients. Device-free tests exercise current-authority loss, blocked provider lanes, candidate expiry, ambiguity, restart, crash recovery and private retention. A separate console permission preflight observed allowed Bluetooth access without scanning in the operator-attributed iTerm2 context. These software and laboratory observations do not close actual launch/access, wearer control or native disposal qualification; 002 through 007 and P096-005/017/018 retain their full completion gates. A separately consented supervisor-terminal scan attempt ended failed with cleanup uncertain; its fenced zero disclosure count supplies neither a no-advertisement claim nor disposal proof. The laboratory controller remains quarantined pending explicit recovery; no automatic retry or native qualification follows.
The same checkpoint implements a separate two-phase wearer enrollment: a canonical deferred operation and private loopback activation/withdrawal control are delivered before device effects. The dedicated bounded listener preserves withdrawal after operator logout and ordinary request-pool saturation. Idle launch of the exact known native worker grants no acquisition; full runtime integrity and current authority are checked again before its effect permit. Ongoing admission reads one coherent registered config/pin snapshot and does not rehash external runtime trees. These are implementation boundaries with device-free process evidence, not proof of native or launchd enforcement.
Device-free maintenance checkpoint, 2026-10-20: Node source 3e514138
reconstructs three different misleading fixture waits over the actual
DiscoveryHost/SQLite owners: a returned expired-candidate refusal, a missed
counter observation during a concurrent approval, and terminal authority failure
before publication. Same-image original/corrected controls retain all 18 actual
outcomes, including intentional negative exits; 35 discovery checks, 36 core
checks and eight collector checks pass. The original unphased historical timeout
is not uniquely attributable, and an unrelated full-load Responsibility timing
outlier remains separately disclosed. This is diagnostic/test maintenance, not
a change to authority, production TTL/deadlines or disposal semantics. See
node:docs/audits/REVIEW-SENSORIUM-CANCELLATION-TIMEOUT-2026-10-20.md and its
bounded metadata/private cross-run inventory. No native work, grant renewal,
recovery, acquisition or acceptance promotion follows; tracker gates stay unchanged.
Native-Helper Diagnostic Follow-Up, 2026-10-20¶
The ordinary frozen-image library run (4635d23a) retains 2,430 passed, two
failed and 64 ignored. The two device-free native-helper cases observed zero
frames despite EOF and confirmed exit, and a readiness deadline before
revocation, respectively. Their historical causes remain unassigned.
Instrumented original behavior (e0a0ea1b) produced twelve complete controlled
negative cases, each exiting 101 as expected: three watchdog-before-frame cases
ended with SIGKILL 9 and an expired deadline, while three preflight failures
ended with code 23, no deadline expiry and no signal. Both yield the same
zero-frame/EOF shape, proving that shape does not identify one cause. Three
cancel and three hang cases with a 3.5-second readiness delay reached the
original three-second guard while the helper remained alive, with no signal or
deadline expiry and approximately 2.87–2.90 seconds of the six-second request
remaining.
They reached neither revocation nor protected stop. All twelve collections have
valid phase records, no event/metric drops and confirmed teardown. Three
unforced original controls pass; they do not explain the historical failures.
Original-behavior native instrumentation passes eight tests with one ignored.
The corrected shared supervisor suite passes 54 tests. Its retained intermediate
53-pass/one-failure run exposed an incorrect requirement that an initial optional
snapshot be present; an explicit contention control confirms that None is
legitimate. The new implementation records closed exit states, milestones and
partial counts without raw stderr, sample data, paths or process identifiers.
The purpose-specific fixture candidate has built successfully in 118.625864708 seconds. It separates retained-image identity using shell builtins and stop/ack using minimal Python from the full-containment test. That pre-integration purpose image, using the repository's existing four-thread gate and pinned Messaging prerequisite, passes the daemon library with 2,434 passed, zero failed and 65 ignored in 441.37 seconds. The focused purpose-native suite passes ten tests with one ignored in 16.71 seconds; strict workspace/all-target Clippy passes in 44.86 seconds. This is scoped software evidence, not a claim that every workspace test passed or that arbitrary loaded startup is bounded.
Contrary observations remain retained: an initial 16-thread library run without the Messaging prerequisite has 2,429 passed, five failed and 65 ignored in 223.42 seconds, comprising two explicit prerequisite refusals and three native failures. Two isolated native 16-thread runs each have nine passed, one failed and one ignored: 12.33 seconds without an OS sampler and 9.96 seconds with one. Both fail the retained-image watchdog. An absent phase file does not prove failure before script entry; sampled dyld waits do not identify the causal receiver, and observer perturbation remains unresolved. The final four-thread gate was already repository policy, not a new lock or timeout fix. Neither its success nor these stress observations uniquely explains the historical failures.
Integration checkpoint: Node caa616f9 and Orbidocs 3514802a retain the combined
history. The first integrated frozen image's four-thread native-prefix run has eight
passed, two failed and one ignored: the retained-image case at watchdog expiry and a new
OS-backed preflight-code-23 assumption. The full library on that exact same image
then has 2,539 passed, zero failed and 71 ignored in 387.55 seconds. That green
run does not explain the earlier refusal, and four-thread execution is not a
startup guarantee either.
The new ordinary code-23 test had a confirmed test-layer error. The correction
tests the raw State::apply port with seven passing pure cases and replaces only
that new ordinary OS-dependent case with deterministic EOF without an
acknowledgment. The explicitly ignored OS code-23 control remains available;
neither the mature retained-image guard nor the revocation guard is ignored or
increased. On the corrected f33bff8 image the four-thread native-prefix run
still has eight passed, one failed and one ignored in 12.19 seconds, failing the
mature retained-image case at watchdog expiry. Strict workspace/all-target Clippy passes; the
final full-library run on this corrected image has 2,545 passed, zero failed and
71 ignored in 454.54 seconds. This does not explain the retained prefix refusal.
No four- or sixteen-thread startup guarantee follows, and the unique historical
causes remain unassigned.
The retained-image helper's original 1,000 ms watchdog and the protected-stop
fixture's three-second readiness guard within its six-second request remain
unchanged. No lifetime, admission, sandbox or disclosure rule is relaxed, and no
timeout increase or harness lock is part of this follow-up. Native/hardware and
product-exposure qualification remain open. The evidence
owner is
node:docs/audits/REVIEW-SENSORIUM-NATIVE-HELPER-FAILURES-2026-10-20.md.
P045-DISC-002 through P045-DISC-007 retain their existing completion gates;
device-free diagnostics do not qualify a BLE/native launch tuple, protected-stop
matrix or product exposure.
Next actions: integrate the frozen 001/P055-10 contracts through 002/003/004 and P055-11/005, before provider exposure. P096-017 depends on the common path; P096-018 supplies first-provider qualification and only then closes DISC-007. Existing P096-009 manual setup and P096-015 initial acquisition qualification do not depend on completing this optional extension.
Implementation Sketch¶
Phase 0:
- [x] create the Sensorium Core boundary and supervised connector skeleton,
- [x] define the module report extension for
module_role: "sensorium-connector"and connector metadata, - [x] implement connector list/status and health,
- [x] implement
sensorium.observe.submitadmission, - [x] implement no-sensorium degradation behavior for consumers,
- [x] adopt the v1 schemas for
sensorium-observation.v1,sensorium-directive.v1,sensorium-directive-result.v1, andsensorium-directive-outcome.v1, - [x] adopt proposal 046 topic naming metadata for admitted observations:
local/sensorium/observations/{signal-kind}. - [x] delegate deliberate local/cross-node enacted-representation exposure to Proposal 082 / Solution 046 without federating local Sensorium topics.
Phase 1:
- [x] persist admitted observations in the Node-owned generic module store with TTL,
- [x] expose bounded query, get, and topic summary read surfaces,
- [ ] post-MVP: expose local Agora subscription paths for admitted observations,
- [x] implement
sensorium.directive.invoke(consumer-facing) and the internalsensorium.connector.invokedispatch for the OS connector, - [x] represent OS connector definitions and signed action allowlist entries as host-owned module store records,
- [x] add audit/outcome records for directive and observation flows,
- [ ] post-MVP: publish admitted observations to
local/sensorium/observations/{signal-kind}with local ACL and retention policy, - [x] satisfy story-009 research input through bounded Sensorium OS actions and Sensorium-mediated directive flow,
- [ ] post-MVP: satisfy more story-009 research input through observation queries over facts produced by observation-only connectors where possible,
- [x] implement reference bounded OS action classes through Sensorium OS, including process/script execution without shell interpolation, bounded workdir/script roots, stdout/stderr caps, timeout policy, artifact references, and connector incidental-effect declarations.
Phase 2:
- add additional connector classes where they remove friction compared with OS actions (for example public-network reader, feed reader, local file watcher),
- add active UI status for invasive connector classes before camera, microphone, location, health wearable, or comparable sensors are enabled,
- allow Monus and Arca to consume Sensorium summaries through explicit host grants.
Phase 3:
- define promotion rules from Sensorium observation to
emergency-signal.v1, Monus concern draft, or Memarium durable fact. - add further production action ids only after the OS reference path has proven allowlist, audit, artifact, and loop-closure behavior.