Project Persona self-authored history
This commit is contained in:
parent
3238b7f08d
commit
e692e2f5eb
2 changed files with 79 additions and 1 deletions
|
|
@ -40,6 +40,9 @@ pub struct PermittedActorSlice {
|
|||
/// from silently impersonating an already-durable person.
|
||||
pub reserved_public_identities: BTreeSet<String>,
|
||||
pub memories: Vec<String>,
|
||||
/// Exact recent public responses already committed for this stable subject.
|
||||
/// These are event-history witnesses, not private memory or new world fact.
|
||||
pub recent_self_authored_turns: Vec<String>,
|
||||
pub perceived_events: Vec<String>,
|
||||
pub perceived_actors: std::collections::BTreeMap<String, String>,
|
||||
pub relationships: Vec<String>,
|
||||
|
|
@ -588,6 +591,11 @@ fn ground_actor_lived_stream(slice: &PermittedActorSlice, projection: &str) -> S
|
|||
} else {
|
||||
slice.memories[recent_memory_start..].join("; ")
|
||||
};
|
||||
let prior_public_response = if slice.recent_self_authored_turns.is_empty() {
|
||||
"no earlier public response by this exact subject is active in this moment".to_owned()
|
||||
} else {
|
||||
slice.recent_self_authored_turns.join("; ")
|
||||
};
|
||||
let interaction = match slice.interaction_role {
|
||||
ActorInteractionRole::DirectResponseExpected => {
|
||||
"You are an exact direct addressee of the current speech. A response is expected from you now. You retain the agency to answer, refuse, or remain silent, but refusal or silence must be made observable rather than disappearing from the scene."
|
||||
|
|
@ -619,7 +627,7 @@ fn ground_actor_lived_stream(slice: &PermittedActorSlice, projection: &str) -> S
|
|||
}
|
||||
};
|
||||
format!(
|
||||
"{projection}\n\n{subject_grounding} Your active self-identity: {identity}. In your social world, {established_peer_identities}. {interaction} Your reliable footing in this moment is narrow. What you know as external fact: {reliable_knowledge}. What you remember experiencing or being told: {remembered_experience}. These are your attributed recollections, not omniscient proof. What is happening now: {visible_now}. People you can presently perceive: {people_now}. Everything else in your impressions is feeling, inference, uncertainty, or possibility—not a remembered or witnessed fact."
|
||||
"{projection}\n\n{subject_grounding} Your active self-identity: {identity}. In your social world, {established_peer_identities}. {interaction} Your reliable footing in this moment is narrow. What you know as external fact: {reliable_knowledge}. What you remember experiencing or being told: {remembered_experience}. These are your attributed recollections, not omniscient proof. Your exact recent public response history: {prior_public_response}. This response history records what you previously made observable; it does not prove that the content of those statements was true. What is happening now: {visible_now}. People you can presently perceive: {people_now}. Everything else in your impressions is feeling, inference, uncertainty, or possibility—not a remembered or witnessed fact."
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -4681,6 +4689,9 @@ mod tests {
|
|||
identity_experience: vec!["A tired navigator".into()],
|
||||
reserved_public_identities: BTreeSet::new(),
|
||||
memories: vec!["Proposed the eastern trail evacuation at dusk.".into()],
|
||||
recent_self_authored_turns: vec![
|
||||
"At world revision 3, your committed public response was exactly: Use the eastern trail.".into(),
|
||||
],
|
||||
perceived_events: vec![],
|
||||
perceived_actors: std::collections::BTreeMap::from([(
|
||||
"player".into(),
|
||||
|
|
@ -4701,6 +4712,8 @@ mod tests {
|
|||
assert!(grounded.contains("Your active self-identity: A tired navigator"));
|
||||
assert!(grounded.contains("What you remember experiencing or being told"));
|
||||
assert!(grounded.contains("Proposed the eastern trail evacuation at dusk."));
|
||||
assert!(grounded.contains("Use the eastern trail."));
|
||||
assert!(grounded.contains("does not prove that the content"));
|
||||
assert!(grounded.contains("not omniscient proof"));
|
||||
let result = engine.execute(slice).await.unwrap();
|
||||
assert_eq!(result.stage_receipts.len(), 3);
|
||||
|
|
@ -4718,6 +4731,7 @@ mod tests {
|
|||
identity_experience: vec!["You are an unnamed patient.".into()],
|
||||
reserved_public_identities: BTreeSet::new(),
|
||||
memories: vec![],
|
||||
recent_self_authored_turns: vec![],
|
||||
perceived_events: vec!["The player asks your name.".into()],
|
||||
perceived_actors: BTreeMap::from([("player".into(), "Player".into())]),
|
||||
relationships: vec![],
|
||||
|
|
@ -4766,6 +4780,7 @@ mod tests {
|
|||
identity_experience: vec!["You are an unnamed patient.".into()],
|
||||
reserved_public_identities: BTreeSet::new(),
|
||||
memories: vec![],
|
||||
recent_self_authored_turns: vec![],
|
||||
perceived_events: vec!["A regulator is inspected.".into()],
|
||||
perceived_actors: BTreeMap::from([("player".into(), "Player".into())]),
|
||||
relationships: vec![],
|
||||
|
|
@ -4861,6 +4876,7 @@ mod tests {
|
|||
identity_experience: vec!["You are an unnamed patient.".into()],
|
||||
reserved_public_identities: BTreeSet::new(),
|
||||
memories: vec![],
|
||||
recent_self_authored_turns: vec![],
|
||||
perceived_events: vec!["The player asks your name.".into()],
|
||||
perceived_actors: BTreeMap::from([("player".into(), "Player".into())]),
|
||||
relationships: vec![],
|
||||
|
|
|
|||
|
|
@ -281,6 +281,7 @@ pub async fn appraise_present(
|
|||
let receipts = campaign.branch_origin.evidence_receipt_ids.clone();
|
||||
let perceived_actors = perceived_actors.clone();
|
||||
let reserved_public_identities = reserved_public_identities(campaign, &actor);
|
||||
let recent_self_authored_turns = recent_self_authored_turns(campaign, &actor.id);
|
||||
let semaphore = semaphore.clone();
|
||||
let interaction_role = if response_expected_actor_ids.contains(&actor.id) {
|
||||
ActorInteractionRole::DirectResponseExpected
|
||||
|
|
@ -301,6 +302,7 @@ pub async fn appraise_present(
|
|||
identity_experience: vec![format!("You are {}.", actor.name)],
|
||||
reserved_public_identities,
|
||||
memories: actor.memories,
|
||||
recent_self_authored_turns,
|
||||
perceived_events: vec![event],
|
||||
perceived_actors,
|
||||
relationships: actor
|
||||
|
|
@ -329,6 +331,7 @@ pub async fn appraise_present(
|
|||
let event = event_summary.to_owned();
|
||||
let receipts = campaign.branch_origin.evidence_receipt_ids.clone();
|
||||
let perceived_actors = perceived_actors.clone();
|
||||
let recent_self_authored_turns = recent_self_authored_turns(campaign, &gestalt.id);
|
||||
let semaphore = semaphore.clone();
|
||||
let interaction_role = if response_expected_actor_ids.contains(&gestalt.id) {
|
||||
ActorInteractionRole::DirectResponseExpected
|
||||
|
|
@ -352,6 +355,7 @@ pub async fn appraise_present(
|
|||
)],
|
||||
reserved_public_identities: perceived_actors.values().cloned().collect(),
|
||||
memories: vec![],
|
||||
recent_self_authored_turns,
|
||||
perceived_events: vec![event],
|
||||
perceived_actors,
|
||||
relationships: vec![],
|
||||
|
|
@ -400,6 +404,26 @@ pub async fn appraise_present(
|
|||
})
|
||||
}
|
||||
|
||||
fn recent_self_authored_turns(campaign: &Campaign, subject_id: &str) -> Vec<String> {
|
||||
const LIMIT: usize = 8;
|
||||
let mut turns = campaign
|
||||
.transcript
|
||||
.iter()
|
||||
.rev()
|
||||
.filter(|turn| turn.speaker == subject_id)
|
||||
.take(LIMIT)
|
||||
.map(|turn| {
|
||||
format!(
|
||||
"At world revision {}, your committed public response was exactly: {}",
|
||||
turn.revision,
|
||||
turn.text.trim()
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
turns.reverse();
|
||||
turns
|
||||
}
|
||||
|
||||
fn reserved_public_identities(
|
||||
campaign: &Campaign,
|
||||
actor: &crate::domain::ActorState,
|
||||
|
|
@ -609,6 +633,44 @@ mod tests {
|
|||
campaign
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stable_subject_history_survives_folding_and_remains_bounded() {
|
||||
let mut campaign = addressed_campaign();
|
||||
for revision in 1..=10 {
|
||||
campaign.transcript.push(NarrativeTurn {
|
||||
revision,
|
||||
at: Utc::now(),
|
||||
speaker: "refugee-one".into(),
|
||||
text: format!("response {revision}"),
|
||||
persona_response_actor_ids: BTreeSet::new(),
|
||||
});
|
||||
}
|
||||
campaign.transcript.push(NarrativeTurn {
|
||||
revision: 11,
|
||||
at: Utc::now(),
|
||||
speaker: "refugee-two".into(),
|
||||
text: "another person's answer".into(),
|
||||
persona_response_actor_ids: BTreeSet::new(),
|
||||
});
|
||||
|
||||
let before_folding = recent_self_authored_turns(&campaign, "refugee-one");
|
||||
assert_eq!(before_folding.len(), 8);
|
||||
assert!(before_folding[0].contains("world revision 3"));
|
||||
assert!(before_folding[0].ends_with("response 3"));
|
||||
assert!(before_folding[7].ends_with("response 10"));
|
||||
assert!(
|
||||
before_folding
|
||||
.iter()
|
||||
.all(|turn| !turn.contains("another person's answer"))
|
||||
);
|
||||
|
||||
campaign.actors.remove("refugee-one");
|
||||
assert_eq!(
|
||||
recent_self_authored_turns(&campaign, "refugee-one"),
|
||||
before_folding
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn materialized_actor_receives_dormant_peer_identities_as_social_context() {
|
||||
let mut campaign = crate::resolution::tests::campaign(0, 8);
|
||||
|
|
|
|||
Loading…
Reference in a new issue