sense §11: what a running agent receives when an observation surfaces to it #584

Merged
dcharlot merged 1 commit from sense/injected-observation into main 2026-11-02 18:03:33 -05:00
8 changed files with 606 additions and 3 deletions

View file

@ -225,6 +225,11 @@ A conforming implementation reproduces, from the published vectors alone
(`deterministic`); an open-ended query escalates.
- **C5 — chain integrity.** A surfacing log verifies (`verify_chain → n`), and
excising the middle link breaks it at the published index.
- **C6 — injected observations (§11).** A sealed surfacing delivers into a running
agent's record and the frame carries the link's own facts; a hold, a
self-authored observation, a wake with no authority, and a delivery priced at
zero are each refused; and neither the destination nor the presence of a wake
can change without changing the frame's address.
## 10. Recognized edges
@ -244,3 +249,85 @@ standard, not a dependency it owns:
- **joule-ui** — the surface a highlight is rendered on; a surfaced highlight is
itself a metered, sealed joule-ui interaction.
- **WAI** — the container for multimodal sensor payloads referenced by a `Cid`.
---
## 11. Surfacing into a running agent (REQUIRED where the recipient is an agent)
§5 decides whether an observation is worth attention; §8 seals that decision.
Neither says what the recipient *receives*. Where the recipient is a person, that
is right: the form is a UI concern and a non-goal (§1.6). Where the recipient is a
**running agent** it is not, because the delivery enters the agent's own record of
what it has been told — and three plausible forms each corrupt that record.
- **As a result on a call the agent made.** The agent made no such call. A record
in which every result answers a call cannot hold one that answers nothing
without ceasing to mean that.
- **As the principal's own words.** The principal did not say it. An auditor
reading the record afterwards could no longer separate what the agent was
*asked* from what it was *told*, and that distinction is most of why the record
is worth keeping.
- **Outside the order.** What an agent did depends on when it learned a thing. An
observation lifted out of the order silently changes what the record says the
agent knew at each point before it.
A surfaced observation delivered to an agent is therefore an **injected
observation**: a distinctly-kinded frame occupying one position in the recipient's
order, which **MUST** state
- the **surfacing link** it carries out (§8), by the content address of that
link's signed core — so the delivery cites a sealed decision instead of
restating it, and the two cannot drift apart;
- the observed event's content id and its declared **trust level** (§2), bound in
so a delivery cannot re-tag what it carries;
- its **destination** (below);
- the **authority** under which a parked recipient was woken, where one was
needed;
- the **joules** the delivery charged — the cost of the recipient reading the
frame, which is not the cost §5 already charged for deciding to surface it.
A host **MUST NOT** present an injected observation as a result, as the
principal's words, or outside the order. The injected kind **MUST NOT** be offered
to the agent as something it may author, and a host **MUST** refuse an attempt by
the recipient to author one: an agent able to author its own observations could
manufacture a record of having been told something, which is the one thing this
frame exists to witness.
### 11.1 Destination
A delivery states where it landed, because the two destinations say different
things about what the recipient knows.
- **`own`** — into the recipient's own record. Everything the recipient does
afterwards was done knowing it.
- **`derived`** — into a derived record that inherits the recipient's context. The
recipient's own record gains that record's *outcome*, not the observation, so
the recipient never came to know the observation itself.
The destination **MUST** be stated rather than inferred from shape. An auditor
reading a recipient's record has to be able to tell that an observation was
handled elsewhere rather than never delivered.
### 11.2 What is refused
Four conditions are refused rather than recorded.
1. **A hold is not deliverable.** §8 chains holds precisely so a decision not to
surface cannot be quietly forgotten; delivering one is the same fault in the
other direction, and **MUST** be refused.
2. **The recipient is not the author.** Author and recipient **MUST** be distinct
principals, as a steering amendment's amender must differ from its author
(JCP §4.7).
3. **A wake needs an authority.** Where delivery wakes a parked run, the frame
**MUST** name the authority that permitted it — the fire of a standing grant
(JCP §4.6) — and delivery **MUST** be refused where none is held. An
already-running recipient names none, which is a different fact from a wake
nobody permitted, and the two **MUST NOT** share a shape.
4. **A delivery that happened is not free.** Something ran: the recipient read the
frame. Zero is therefore not a measurement, and a delivery priced at zero
**MUST** be refused. Where a host cannot measure, it estimates and labels
(§7); it does not report nothing.
Conformance class **C6** exercises the delivery, each of the four refusals, and
that neither the destination nor the presence of a wake can be changed without
changing the frame's address.

View file

@ -1,6 +1,6 @@
# Sense conformance vectors — v1
Reproducible fixtures for the five conformance classes (SPEC §9). A third-party
Reproducible fixtures for the six conformance classes (SPEC §9). A third-party
implementation is conforming if it reproduces these values from the spec alone.
Regenerate with:

View file

@ -29,5 +29,14 @@
"c4_recall_model": "deterministic",
"c5_excision_breaks_at": 1,
"c5_first_link_jcr1_envelope_hex": "d2845821a2012704581b6469643a6578616d706c653a73656e73652d7265666572656e6365a0590160ad6373657100646b696e646873616c69656e636564707265767840303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030306574727573746a466972737450617274796773746577617264781b6469643a6578616d706c653a73656e73652d7265666572656e6365686465636973696f6e6773757266616365686576656e745f69647840653232356166356230306161306632643562663765666437623061383833633962376433623763356636313537366438616334633930353564663631383035376a636861726765645f756a1903e86a636f73745f6d6963726f006b73636f72655f6d6963726f1a000e7ef06b76616c75655f6d6963726f1a000e7ef06d73656e73655f726563656970747173656e73652f737572666163696e672f31736275646765745f72656d61696e696e675f756a1903e85840e3f034e6f4d38ac68a1075e04b26a3e86297b19e40cdedeba2ed81999e25c00de1bd4841771a5e3687719b9855ed644669da85d1f8c6c27c95d2a365ee983700",
"c5_verify_ok": 3
"c5_verify_ok": 3,
"c6_injected_id_derived_woken": "1968d0a2acc40ebe7074cfc355c83f3914dddf338cb34a721265446641e66344",
"c6_injected_id_own_running": "23feae15df140457b12b9a4add128bd67fbacb5aa0c65904a64f830dadd71094",
"c6_injected_id_own_woken": "d892422446e0a8588657fe5ef8b3eacfba081c28a34b22b82985632ec3fa4fb2",
"c6_refusals": [
"not-surfaced",
"authored-by-recipient",
"no-wake-authority",
"unpriced-delivery"
]
}

View file

@ -45,6 +45,11 @@ fn main() {
let first = &log.entries()[0].core;
let envelope_hex = hex::encode(seal_jcr1(first, &sk, c::STEWARD).expect("seal"));
// C6 — the injected observation (§11): the frame's address under each
// destination and with/without a wake, and the four refusals by token.
let (c6_own_woken, c6_derived_woken, c6_own_running) = c::c6_distinct_addresses();
let c6_refusals: Vec<&str> = c::c6_refusals().iter().map(|e| e.label()).collect();
let vectors = serde_json::json!({
"c1_replay_digest": c::c1_replay_digest().to_hex(),
"c2_event_id": c::c2_event().id().to_hex(),
@ -57,6 +62,10 @@ fn main() {
"c5_verify_ok": c5_ok.map(|n| n as i64).unwrap_or(-1),
"c5_excision_breaks_at": c5_broken.err().map(|i| i as i64).unwrap_or(-1),
"c5_first_link_jcr1_envelope_hex": envelope_hex,
"c6_injected_id_own_woken": c6_own_woken.to_hex(),
"c6_injected_id_derived_woken": c6_derived_woken.to_hex(),
"c6_injected_id_own_running": c6_own_running.to_hex(),
"c6_refusals": c6_refusals,
});
std::fs::write(out_dir.join("meta.json"), format!("{}\n", serde_json::to_string_pretty(&meta).unwrap())).expect("write meta");

View file

@ -25,7 +25,8 @@ use sense_cascade::{
CascadeClient, CascadeStage, DeterministicStage, Envelope, RecorderClient, RetrievedSpan,
StageDecision, SynthesisClient,
};
use sense_receipt::{verify_chain, SurfacingLog};
use sense_receipt::injected::{Delivery, InjectError, InjectedObservation};
use sense_receipt::{verify_chain, SealedSurfacing, SurfacingLog};
use sense_schema::{Cid, Event, Hlc, Highlight, SourceClass, StateProjection, TrustLevel};
/// The fixed steward key the conformance receipts seal with. A vector pack must
@ -33,6 +34,9 @@ use sense_schema::{Cid, Event, Hlc, Highlight, SourceClass, StateProjection, Tru
/// nothing.
pub const STEWARD_SEED: [u8; 32] = [0x5e; 32];
pub const STEWARD: &str = "did:example:sense-reference";
/// The agent a surfaced observation is delivered to (§11). Distinct from
/// [`STEWARD`], which authors the delivery: the two may never be one.
pub const RECIPIENT: &str = "did:example:sense-recipient";
/// The shared scripted signal stream: a quiet baseline of shell activity, then a
/// burst of file changes, then a low-trust log entry. Each tuple is
@ -189,6 +193,82 @@ pub fn c5_verify() -> (Result<usize, usize>, Result<usize, usize>) {
(ok, broken)
}
/// A link from the C5 log, chosen by what it decided rather than by position,
/// so a change to the fixture's budget cannot silently turn a "held" case into
/// a surfaced one and quietly stop testing the refusal.
fn c6_pick(log: &SurfacingLog, surfaced: bool) -> SealedSurfacing {
log.entries()
.iter()
.find(|e| (e.core.decision == "surface") == surfaced)
.unwrap_or_else(|| {
panic!(
"the C5 log has no {} link",
if surfaced { "surfaced" } else { "held" }
)
})
.clone()
}
/// C6 — an injected observation (§11): the frame a surfaced decision takes
/// when its recipient is a running agent, and each condition that is refused
/// rather than recorded.
pub fn c6_injected() -> Result<InjectedObservation, InjectError> {
let (log, _pk) = c5_log();
let surfaced = c6_pick(&log, true);
InjectedObservation::deliver(
&surfaced,
RECIPIENT,
STEWARD,
Delivery::Own,
0,
true,
Some(Cid::of(b"sense-conformance-standing-fire")),
4_200,
)
}
/// Each of §11.2's four refusals, in order, as the harness asserts them.
pub fn c6_refusals() -> Vec<InjectError> {
let (log, _pk) = c5_log();
let surfaced = c6_pick(&log, true);
let held = c6_pick(&log, false);
let fire = Cid::of(b"sense-conformance-standing-fire");
let d = |s: &SealedSurfacing, to: &str, parked, woken, uj| {
InjectedObservation::deliver(s, to, STEWARD, Delivery::Own, 0, parked, woken, uj)
.expect_err("each case is a refusal")
};
vec![
// 1. a decision that was a hold
d(&held, RECIPIENT, false, None, 1),
// 2. the recipient authoring its own observation
d(&surfaced, STEWARD, false, None, 1),
// 3. a parked recipient woken with no authority named
d(&surfaced, RECIPIENT, true, None, 1),
// 4. a delivery priced at nothing
d(&surfaced, RECIPIENT, false, Some(fire), 0),
]
}
/// The addresses of the same delivery to each destination, and of one that
/// needed a wake against one that did not. Neither distinction may be
/// invisible in the frame's address.
pub fn c6_distinct_addresses() -> (Cid, Cid, Cid) {
let (log, _pk) = c5_log();
let s = &c6_pick(&log, true);
let fire = Cid::of(b"sense-conformance-standing-fire");
let mk = |dest, parked, woken| {
InjectedObservation::deliver(s, RECIPIENT, STEWARD, dest, 0, parked, woken, 4_200)
.expect("delivers")
.content_id()
.expect("canonicalizes")
};
(
mk(Delivery::Own, true, Some(fire)),
mk(Delivery::Derived, true, Some(fire)),
mk(Delivery::Own, false, None),
)
}
#[cfg(test)]
mod tests {
use super::*;
@ -245,4 +325,38 @@ mod tests {
assert_eq!(ok, Ok(3));
assert_eq!(broken, Err(1));
}
#[test]
fn c6_a_surfaced_decision_delivers_with_the_links_own_facts() {
let (log, _pk) = c5_log();
let surfaced = &log.entries()[0];
assert_eq!(surfaced.core.decision, "surface", "the first link really surfaced");
let i = c6_injected().expect("a surfaced decision delivers");
assert_eq!(i.surfacing_id, surfaced.content_id);
assert_eq!(i.event_id, surfaced.core.event_id);
assert_eq!(i.trust, surfaced.core.trust);
assert_ne!(i.author, i.recipient);
assert!(i.woken_under.is_some(), "a parked recipient names its authority");
assert!(i.charged_uj > 0, "the delivery is priced");
}
#[test]
fn c6_every_refusal_fires_for_its_own_reason() {
assert_eq!(
c6_refusals(),
vec![
InjectError::NotSurfaced,
InjectError::AuthoredByRecipient,
InjectError::NoWakeAuthority,
InjectError::UnpricedDelivery,
]
);
}
#[test]
fn c6_destination_and_wake_are_both_visible_in_the_address() {
let (own_woken, derived_woken, own_running) = c6_distinct_addresses();
assert_ne!(own_woken, derived_woken, "the destination is bound in");
assert_ne!(own_woken, own_running, "whether a wake happened is bound in");
}
}

View file

@ -311,3 +311,43 @@ fn the_published_envelope_verifies_under_the_published_key() {
let stranger = ed25519_dalek::SigningKey::from_bytes(&[0x42; 32]).verifying_key();
assert!(stranger.verify(&sig_structure(&protected, &core), &sig).is_err());
}
/// C6 — the injected observation (§11), held to the file.
///
/// Three addresses and four refusal tokens. The addresses matter more than they
/// look: if the destination or the presence of a wake stopped being bound into
/// the frame, two of the three would collapse into one, and a delivery could be
/// rewritten after the fact without changing what it addresses to.
#[test]
fn the_published_injected_frames_recompute() {
let v = doc("vectors.json");
let (own_woken, derived_woken, own_running) = c::c6_distinct_addresses();
for (got, key) in [
(own_woken, "c6_injected_id_own_woken"),
(derived_woken, "c6_injected_id_derived_woken"),
(own_running, "c6_injected_id_own_running"),
] {
assert_eq!(
got.to_hex(),
v[key].as_str().unwrap_or_else(|| panic!("pack records {key}")),
"the injected frame no longer addresses to the published {key}"
);
}
// Still three distinct frames, as §11.1 and §11.2 require.
assert_eq!(
[own_woken, derived_woken, own_running].iter().collect::<std::collections::BTreeSet<_>>().len(),
3,
"the destination and the wake must each be visible in the address"
);
let published: Vec<&str> =
v["c6_refusals"].as_array().expect("pack records the refusals")
.iter().map(|x| x.as_str().expect("a refusal token")).collect();
let got: Vec<&str> = c::c6_refusals().iter().map(|e| e.label()).collect();
assert_eq!(got, published, "§11.2's refusals, in order");
assert_eq!(
published,
vec!["not-surfaced", "authored-by-recipient", "no-wake-authority", "unpriced-delivery"],
"a refusal that stopped firing would otherwise publish a shorter list"
);
}

View file

@ -0,0 +1,343 @@
//! Surfacing into a running agent (SPEC §11) — the form an observation takes
//! when the thing it is surfaced *to* is an agent rather than a person.
//!
//! §5 decides whether an observation is worth attention and §8 seals that
//! decision. Neither says what the recipient receives, and where the recipient
//! is a person that is right: the form is a UI concern, out of scope (§1.6).
//! Where the recipient is a running agent it is not out of scope, because the
//! delivery enters the agent's own record of what it has been told, and three
//! plausible forms each corrupt that record:
//!
//! - **as a result on a call the agent made.** The agent made no such call. A
//! record in which every result answers a call cannot hold one that answers
//! nothing without ceasing to mean that.
//! - **as the principal's own words.** The principal did not say it. An auditor
//! reading the record afterwards could no longer separate what the agent was
//! *asked* from what it was *told*, which is the distinction that makes the
//! record worth keeping.
//! - **outside the order.** What an agent did depends on when it learned a
//! thing. An observation lifted out of order silently changes what the record
//! says it knew at each point.
//!
//! So a surfaced observation is delivered as a distinctly-kinded frame that
//! occupies one position in the recipient's order and cites the sealed decision
//! it carries out. Four things are refused rather than recorded: delivering a
//! decision that was a hold, an agent authoring its own observation, waking a
//! parked recipient with no authority, and a delivery priced at nothing.
use crate::{ReceiptError, SealedSurfacing};
use sense_schema::{Cid, TrustLevel};
use serde_json::{json, Value};
/// The profile tag bound into a delivery's canonical bytes. The `/1` is the
/// shape version: changing the preimage bumps it so two versions never collide.
pub const PROFILE: &str = "sense/injected/1";
/// Where a delivered observation landed.
///
/// Stated, not inferred, because the two say different things about what the
/// recipient knows — and an auditor reading a recipient's record must be able
/// to tell that an observation was handled elsewhere rather than missed.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Delivery {
/// Into the recipient's own record. It is thereafter part of what the
/// recipient knows, and everything the recipient does afterwards was done
/// knowing it.
Own,
/// Into a derived record that inherits the recipient's context. The
/// recipient's own record gains that record's outcome, not the
/// observation — so the recipient did not come to know the observation
/// itself, only what was concluded from it.
Derived,
}
impl Delivery {
pub fn label(&self) -> &'static str {
match self {
Delivery::Own => "own",
Delivery::Derived => "derived",
}
}
}
/// Why a delivery was refused.
#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
pub enum InjectError {
/// The cited decision was a hold. A held highlight is exactly the record
/// §8 chains so it cannot be quietly forgotten; delivering one would be
/// the same fault in the other direction — a decision not to surface,
/// surfaced anyway.
#[error("the cited decision was a hold, not a surfacing")]
NotSurfaced,
/// The recipient authored the observation it received. An agent able to
/// author its own observations could manufacture a record of having been
/// told something, which is the one thing this frame exists to witness.
#[error("an agent may not author an observation delivered to itself")]
AuthoredByRecipient,
/// The recipient was parked and the delivery named no authority to wake
/// it. Waking a parked run is work someone must have permitted.
#[error("a parked recipient was woken with no authority named")]
NoWakeAuthority,
/// The delivery charged nothing. Something ran — the recipient read the
/// frame — so zero is not a measurement. Where a host cannot measure it
/// estimates and labels (§7); it does not report nothing.
#[error("a delivery that happened cannot be priced at zero")]
UnpricedDelivery,
}
impl InjectError {
/// A stable token for the pack. The `Display` text is prose and may be
/// reworded; a published vector must not move when it is.
pub fn label(&self) -> &'static str {
match self {
InjectError::NotSurfaced => "not-surfaced",
InjectError::AuthoredByRecipient => "authored-by-recipient",
InjectError::NoWakeAuthority => "no-wake-authority",
InjectError::UnpricedDelivery => "unpriced-delivery",
}
}
}
/// One observation delivered into a running agent's record (§11).
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct InjectedObservation {
/// The surfacing link (§8) whose decision this delivery carries out, by
/// the content address of its signed core. The delivery cites a sealed
/// decision rather than restating it, so the two cannot drift apart.
pub surfacing_id: Cid,
/// Content id of the observed event (§2).
pub event_id: Cid,
/// Its declared trust level, bound in so a delivery cannot re-tag what it
/// carries.
pub trust: TrustLevel,
/// Where it landed.
pub delivery: Delivery,
/// The principal the observation was delivered to.
pub recipient: String,
/// The principal that delivered it — never the recipient.
pub author: String,
/// The position this frame occupies in the recipient's order.
pub seq: u64,
/// The authority under which a parked recipient was woken: the fire of a
/// standing grant. `None` where the recipient was already running, which
/// is a different fact from a wake nobody permitted.
pub woken_under: Option<Cid>,
/// Microjoules this delivery charged — the cost of the recipient reading
/// the frame, which is not the cost §5 already charged for deciding to
/// surface it.
pub charged_uj: u64,
}
impl InjectedObservation {
/// Deliver a sealed surfacing decision into a recipient's record, or
/// refuse. Every field the frame carries is taken from the sealed link or
/// from the delivery itself; nothing is restated by the caller, so a frame
/// cannot disagree with the decision it cites.
#[allow(clippy::too_many_arguments)]
pub fn deliver(
surfacing: &SealedSurfacing,
recipient: impl Into<String>,
author: impl Into<String>,
delivery: Delivery,
seq: u64,
parked: bool,
woken_under: Option<Cid>,
charged_uj: u64,
) -> Result<Self, InjectError> {
if surfacing.core.decision != "surface" {
return Err(InjectError::NotSurfaced);
}
let (recipient, author) = (recipient.into(), author.into());
if recipient == author {
return Err(InjectError::AuthoredByRecipient);
}
if parked && woken_under.is_none() {
return Err(InjectError::NoWakeAuthority);
}
if charged_uj == 0 {
return Err(InjectError::UnpricedDelivery);
}
Ok(Self {
surfacing_id: surfacing.content_id,
event_id: surfacing.core.event_id,
trust: surfacing.core.trust,
delivery,
recipient,
author,
seq,
woken_under,
charged_uj,
})
}
/// The canonical wire JSON — a flat uint/text map, as §3 requires of
/// anything content-addressed. `woken_under` is absent rather than null
/// when no wake was needed, so "already running" and "woken" do not share
/// a shape.
pub fn to_wire(&self) -> Value {
let mut m = json!({
"sense_injected": PROFILE,
"surfacing_id": self.surfacing_id.to_hex(),
"event_id": self.event_id.to_hex(),
"trust": self.trust.label(),
"delivery": self.delivery.label(),
"recipient": self.recipient,
"author": self.author,
"seq": self.seq,
"charged_uj": self.charged_uj,
});
if let Some(w) = &self.woken_under {
m["woken_under"] = json!(w.to_hex());
}
m
}
/// Canonical bytes, under the family's JCR-1 canonicalization.
pub fn canonical_bytes(&self) -> Result<Vec<u8>, ReceiptError> {
Ok(crate::jcr1::signed_core_bytes(&self.to_wire())?)
}
/// This frame's content id, so a recipient's record can cite it.
pub fn content_id(&self) -> Result<Cid, ReceiptError> {
Ok(Cid::of(&self.canonical_bytes()?))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::SurfacingLog;
use ed25519_dalek::SigningKey;
use sense_attention::{AttentionBudget, EngagementState, Modality};
use sense_schema::{Event, Highlight, HighlightKind, Hlc, SourceClass};
fn event_id() -> Cid {
Event::new(Hlc::new(1, 0), SourceClass::FileChange, TrustLevel::FirstParty, b"d", "/a.md")
.id()
}
/// One sealed link. `surface` picks a budget that can afford the
/// interruption; otherwise the gate holds on budget, which is the record
/// a delivery must refuse to act on.
fn sealed(surface: bool) -> SealedSurfacing {
let mut log = SurfacingLog::new(SigningKey::from_bytes(&[7u8; 32]), "did:example:sense");
let h = Highlight {
kind: HighlightKind::Salience,
score: 0.95,
headline: "x".into(),
triggered_at_unix_ns: 0,
};
let mut budget =
AttentionBudget::new(if surface { 10_000 } else { 100 }, 1_000);
let v = budget.decide(&h, EngagementState::default(), Modality::Visual);
log.record(event_id(), TrustLevel::FirstParty, &h, &v).unwrap();
log.entries()[0].clone()
}
fn deliver(
s: &SealedSurfacing,
recipient: &str,
d: Delivery,
parked: bool,
woken: Option<Cid>,
uj: u64,
) -> Result<InjectedObservation, InjectError> {
InjectedObservation::deliver(s, recipient, "did:example:sense", d, 0, parked, woken, uj)
}
#[test]
fn a_delivery_carries_the_sealed_decisions_own_facts() {
let s = sealed(true);
assert_eq!(s.core.decision, "surface", "the fixture really did surface");
let i = InjectedObservation::deliver(
&s,
"did:example:agent",
"did:example:sense",
Delivery::Own,
3,
false,
None,
4_200,
)
.expect("a surfaced decision delivers");
// Nothing is restated by the caller, so the frame cannot disagree with
// the link it cites.
assert_eq!(i.surfacing_id, s.content_id);
assert_eq!(i.event_id, s.core.event_id);
assert_eq!(i.trust, s.core.trust);
assert_eq!(i.seq, 3);
assert!(i.content_id().is_ok());
}
/// A held highlight delivered anyway is the §8 fault in the other
/// direction: a decision not to surface, surfaced.
#[test]
fn a_hold_is_not_deliverable() {
let s = sealed(false);
assert_ne!(s.core.decision, "surface", "the fixture really did hold");
assert_eq!(
deliver(&s, "did:example:agent", Delivery::Own, false, None, 1),
Err(InjectError::NotSurfaced)
);
}
#[test]
fn the_recipient_may_not_be_the_author() {
let s = sealed(true);
assert_eq!(
deliver(&s, "did:example:sense", Delivery::Own, false, None, 1),
Err(InjectError::AuthoredByRecipient)
);
}
#[test]
fn waking_a_parked_recipient_needs_an_authority() {
let s = sealed(true);
assert_eq!(
deliver(&s, "did:example:agent", Delivery::Own, true, None, 1),
Err(InjectError::NoWakeAuthority)
);
let fire = Cid::of(b"standing-fire");
let ok = deliver(&s, "did:example:agent", Delivery::Own, true, Some(fire), 1).unwrap();
assert_eq!(ok.woken_under, Some(fire));
}
#[test]
fn a_delivery_that_happened_cannot_cost_nothing() {
let s = sealed(true);
assert_eq!(
deliver(&s, "did:example:agent", Delivery::Own, false, None, 0),
Err(InjectError::UnpricedDelivery)
);
}
/// The two destinations say different things about what the recipient
/// knows, so they must not share an address.
#[test]
fn the_two_destinations_are_distinguishable() {
let s = sealed(true);
let own = deliver(&s, "did:example:agent", Delivery::Own, false, None, 9).unwrap();
let derived = deliver(&s, "did:example:agent", Delivery::Derived, false, None, 9).unwrap();
assert_ne!(own.content_id().unwrap(), derived.content_id().unwrap());
}
/// "Already running" and "woken under an authority" are different facts,
/// so they must not canonicalize alike — and the absent case carries no
/// key at all rather than a null.
#[test]
fn a_wake_is_visible_in_the_address() {
let s = sealed(true);
let running = deliver(&s, "did:example:agent", Delivery::Own, false, None, 9).unwrap();
let woken = deliver(
&s,
"did:example:agent",
Delivery::Own,
true,
Some(Cid::of(b"standing-fire")),
9,
)
.unwrap();
assert_ne!(running.content_id().unwrap(), woken.content_id().unwrap());
assert!(!running.to_wire().as_object().unwrap().contains_key("woken_under"));
}
}

View file

@ -21,6 +21,7 @@ use sense_attention::AttentionVerdict;
use sense_schema::{Cid, Highlight, StateProjection, TrustLevel};
use serde_json::{json, Value};
pub mod injected;
pub mod jcr1;
/// The profile tag bound into every signed core. The `/1` is the canonical-core