Close four retirement test gaps and route the mirror-forgery test through replay (PA.f39-f40)

PA.f39: each surviving mutation gets a test that fails under it.
- M2: `AcquireKnowledge` now has a test with an `Evidenced` source, so a
  narrowing of the retired check to `source != Evidenced` is caught.
- M6: a mirror declared into a `Reach::Subjects` channel now has a test
  proving it stays in the audience, so `is_retired` matching
  `ExternallyControlled` is caught.
- M9: the Draft-only approval shape clause in `verify_state_shape` is now
  pinned directly with a forged `draft_approvals` entry outside
  `required_approvers`, rather than only exercised indirectly.
- Soul's probe S2: a placeless subject reachable only through a
  `Reach::Subjects` channel is now proven reachable while live and refused
  once retired, exercising `audience()`'s channel side, which PA.f33's
  Colocated-only `CanReach` test never reached.

`WorldJournal` gains a `#[cfg(test)]` `commits_for_test` accessor and
`verify_history` becomes `pub(super)` (matching `verify_state_shape`'s
existing visibility) so a Soul-style forgery test outside `journal.rs` can
route its falsification through the function that actually judges committed
history.

PA.f40: the "mirror acted" test at consumer.rs claimed the shape check
refused it on a controller-id mismatch. That clause was deleted in PA.f31,
and the test passed only by accident through the unrelated speech-claim
clause. Renamed and routed through `verify_history`: it forges the committed
effect's event scope onto the mirror, recomputes the commit digest, and
proves replaying the original command no longer reproduces that effect.

All four PA.f39 mutations verified as killed by direct mutation testing
against the committed code, then restored by reverse edit. Lib census: 549
before batch 5, 555 after bc1852d/33fc9c6 (PA.f36-f38), 559 after this commit
(PA.f39 adds 4; PA.f40 renames one test in place).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-09-22 08:34:52 +02:00
commit 662a51f647
3 changed files with 276 additions and 18 deletions

View file

@ -471,8 +471,9 @@ mod tests {
EntityDeclaration, EntityId, EntityKind, EvidenceRef, FactDeclaration, FactStandingRef,
FictionalMinutes, JurisdictionKey, NewController, PatchGround, Quantity, Ref,
RouteDeclaration, Statement, SubjectDeclaration, SubjectId, SubjectKind, SystemCapability,
WorldId, WorldKernel, WorldMailbox, WorldScaleIntentRef, agency_graph, derive_boundaries,
derive_cover, derive_opportunities, derive_scale_deficit, ground_covers,
WorldEffect, WorldId, WorldKernel, WorldMailbox, WorldScaleIntentRef, agency_graph,
commit_digest, derive_boundaries, derive_cover, derive_opportunities,
derive_scale_deficit, ground_covers,
};
use super::*;
use std::collections::BTreeSet;
@ -1908,11 +1909,19 @@ mod tests {
// ---- Soul: falsification of the pass's own claims ----------------------
/// A committed decision under the forgery, with a real event beneath it,
/// and proof that the honest state — a mirror with no controller and no
/// grant — passes the same shape check.
/// PA.f40: this used to claim `verify_state_shape` refused a re-scoped
/// event on a controller-id mismatch. That clause was deleted in PA.f31;
/// the version that called only `verify_state_shape` kept passing, but
/// only by accident, through the unrelated speech-claim clause (the
/// event's fixture always carries speech, and a claim asserted by one
/// subject is never canonical when re-scoped onto another). What
/// actually refuses a mirror-scoped forgery in general is a full replay:
/// re-deriving the effect from the original, unforged command via
/// `reduce` no longer reproduces the forged commit, so `verify_history`
/// — not the structural shape check — is what this test pins. Renamed
/// and routed accordingly.
#[test]
fn soul_a_forged_decision_event_on_a_mirror_is_refused_at_replay() {
fn a_forged_mirror_acted_event_is_refused_by_verify_history() {
let directory = tempfile::tempdir().unwrap();
let (mut kernel, mirror) = mirror_kernel(directory.path(), "Acted");
let snapshot = kernel.snapshot().unwrap();
@ -1939,21 +1948,24 @@ mod tests {
"the fixture must commit a real event for this forgery to mean anything"
);
// The honest state passes: an externally controlled subject with no
// controller id and no affordance grant is legal.
super::super::journal::verify_state_shape(&kernel.state)
.expect("a world holding a mirror is a well-shaped world");
// Re-scoping the committed event onto the mirror is refused: the
// mirror's assignment has no controller id to match.
let mut forged = kernel.state.clone();
let mut event = forged.events.first().cloned().expect("a committed event");
// Re-scope the committed effect onto the mirror and route the
// forgery through the commit log: replaying the original, unforged
// command via `reduce` no longer reproduces this effect.
let head = kernel.state.clone();
let mut commits = kernel.journal.commits_for_test();
let exercised = commits
.values_mut()
.find(|commit| commit.resulting_revision == head.revision)
.expect("the exercise decision is the head commit");
let WorldEffect::DecisionExercised { event, .. } = &mut exercised.effect else {
panic!("expected the head commit to carry a DecisionExercised effect");
};
event.scope = DecisionScope {
subject_id: mirror.first,
};
forged.events = vec![event];
exercised.digest = commit_digest(exercised).unwrap();
assert!(
super::super::journal::verify_state_shape(&forged).is_err(),
super::super::journal::verify_history(&head, &commits).is_err(),
"a forged history in which the mirror acted replayed"
);
}

View file

@ -186,6 +186,15 @@ impl WorldJournal {
self.commits.len()
}
/// PA.f40: a test outside this module needs the full commit map to forge
/// one commit's effect and route the forgery through `verify_history`
/// directly, the same way this module's own forgery tests already do via
/// `self.commits.clone()`.
#[cfg(test)]
pub(super) fn commits_for_test(&self) -> BTreeMap<CommandId, WorldCommit> {
self.commits.clone()
}
#[cfg(test)]
pub(super) fn fail_after_durable_commit_for_test(&mut self) {
self.fail_after_durable_commit = true;
@ -336,7 +345,11 @@ fn verify_append(
Ok(())
}
fn verify_history(
/// `pub(super)`, matching `verify_state_shape`: a Soul-style forgery test
/// outside this module routes its falsification through the same function
/// that actually judges a committed history, rather than through the
/// structural-only `verify_state_shape`.
pub(super) fn verify_history(
state: &WorldState,
commits: &BTreeMap<CommandId, WorldCommit>,
) -> Result<(), JournalError> {
@ -2393,6 +2406,36 @@ mod custody_tests {
);
}
/// PA.f39, M9: the Draft-only approval shape clause is defence in depth,
/// so it is pinned directly on `verify_state_shape` rather than only
/// through a full submit path. A fresh Draft world's approvals pass; a
/// forged principal outside `required_approvers` does not.
#[test]
fn draft_approvals_outside_required_approvers_is_corrupt() {
use crate::tests::{auth_principal, creation, owner};
let directory = tempfile::tempdir().unwrap();
let path = directory.path().join("world.cc");
let (kernel, _) = WorldKernel::create(
&path,
creation(CommandId::new(), "PAf39ApprovalShape"),
&auth_principal(owner()),
)
.unwrap();
assert_eq!(kernel.state.phase, crate::WorldPhase::Draft);
verify_state_shape(&kernel.state)
.expect("a fresh Draft world has a canonical approval shape");
let mut forged = kernel.state.clone();
forged
.draft_approvals
.insert(crate::PrincipalId::new("interloper@example.test"));
assert!(
matches!(verify_state_shape(&forged), Err(JournalError::Corrupt(_))),
"an approval outside the required set passed the shape check"
);
}
/// Absence is zero and one slot holds one pair, so a stored zero, an empty
/// holder, and a holding on something that is not a resource are each
/// corrupt at replay.

View file

@ -18478,4 +18478,207 @@ mod clock_tests {
"the obligation pressed somewhere along the replayed path"
);
}
// ---- Retirement fix batch, test gaps (PA.f39) --------------------------
/// PA.f39, M2: `AcquireKnowledge` refuses a retired subject regardless of
/// source. `Evidenced` already carries its own provenance guard
/// (`EvidencedKnowledgeOfClaim`), which makes it plausible for a future
/// edit to narrow the retirement check to `source != Evidenced`; this
/// proves the retirement check still fires for an `Evidenced` acquire
/// too.
#[test]
fn a_retired_subject_cannot_acquire_evidenced_knowledge() {
let directory = tempfile::tempdir().unwrap();
let (mut kernel, clockwork, _) = clock_kernel(directory.path(), "PAf39Evidenced");
owner_retires(&mut kernel, clockwork.farmer).expect("retire");
let patch = WorldPatch {
declarations: vec![Declaration::Fact(FactDeclaration {
handle: DraftHandle::new("news"),
label: "The Harvest Report".into(),
statement: Statement::new("The winter grain is counted.").unwrap(),
standing: FactStandingRef::Canonical {
evidence: EvidenceRef::new("vault:count"),
},
})],
operations: vec![ComponentOp::AcquireKnowledge {
subject: Ref::Existing(clockwork.farmer),
fact: Ref::Draft(DraftHandle::new("news")),
source: AuthoredSource::Evidenced,
confidence: Confidence::Certain,
}],
evidence: vec![EvidenceRef::new("vault:count")],
};
let error = submit_as(
&mut kernel,
play_caller(),
CommandBody::AdmitPatch { answers: None, patch },
)
.unwrap_err();
assert!(
matches!(&error, KernelError::PatchRejected(set)
if set.contains(&Mismatch::RetiredSubjectActed { operation: 0 })),
"{error:?}"
);
}
/// PA.f39, M6: `is_retired` reads `ControllerAssignment::Retired`
/// specifically. If it also matched `ExternallyControlled`, a mirror
/// would be silently dropped from `Reach::Subjects` audience derivation —
/// the same site PA.f33 fixed for an actually retired member. A mirror is
/// not retired, and stays in the audience.
#[test]
fn a_mirror_in_a_subjects_channel_stays_in_the_audience() {
let directory = tempfile::tempdir().unwrap();
let (mut kernel, clockwork, _) = clock_kernel(directory.path(), "PAf39MirrorAudience");
let mirror = declare_mirror(&mut kernel, &clockwork, "pa-f39-mirror");
let mut patch = ruled_fact_patch("news");
patch.declarations.push(Declaration::Channel(ChannelDeclaration {
handle: DraftHandle::new("wire"),
label: "The Wire".into(),
reach: ReachRef::Subjects(BTreeSet::from([
Ref::Existing(mirror),
Ref::Existing(clockwork.farmer),
])),
controller: None,
}));
patch.operations.push(ComponentOp::Communicate {
speaker: Ref::Existing(clockwork.farmer),
fact: Ref::Draft(DraftHandle::new("news")),
to: AudienceRef::Channel(Ref::Draft(DraftHandle::new("wire"))),
});
submit_as(
&mut kernel,
play_caller(),
CommandBody::AdmitPatch { answers: None, patch },
)
.expect("admitted");
let mirror_knows = kernel
.state
.knowledge
.get(&mirror)
.map(BTreeMap::len)
.unwrap_or(0);
assert_eq!(
mirror_knows, 1,
"a mirror was excluded from a Subjects-reach audience"
);
}
/// PA.f39, Soul's probe S2: `CanReach` to a placeless target reachable
/// only through a `Reach::Subjects` channel — no co-location is possible
/// — is refused once the target retires. This exercises `audience()`'s
/// channel side, which PA.f33's Colocated-only `CanReach` test
/// (`a_retired_subject_is_unreachable_through_can_reach`) never reaches,
/// and kills a mutation that removes `audience()`'s retired filter.
#[test]
fn a_retired_placeless_subject_is_unreachable_through_a_subjects_channel() {
let directory = tempfile::tempdir().unwrap();
let (mut kernel, clockwork, _) = clock_kernel(directory.path(), "PAf39S2");
let speak = super::tests::speak_entry(&kernel);
submit_as(
&mut kernel,
play_caller(),
CommandBody::AdmitPatch {
answers: None,
patch: WorldPatch {
declarations: vec![
Declaration::Subject(SubjectDeclaration {
handle: DraftHandle::new("outcast"),
label: "The Placeless Outcast".into(),
kind: SubjectKind::Person,
controller: NewController::NarrativePersona,
affordances: BTreeSet::from([speak.clone()]),
position: None,
}),
Declaration::Channel(ChannelDeclaration {
handle: DraftHandle::new("wire"),
label: "The Outcast Wire".into(),
reach: ReachRef::Subjects(BTreeSet::from([
Ref::Draft(DraftHandle::new("outcast")),
Ref::Existing(clockwork.farmer),
])),
controller: None,
}),
Declaration::Affordance(AffordanceDeclaration {
handle: DraftHandle::new("hail"),
kind: AffordanceKindName("hail".into()),
roles: vec![
RoleSpec {
role: Role("target".into()),
kind: RefKind::Subject(None),
},
RoleSpec {
role: Role("channel".into()),
kind: RefKind::Entity(EntityKind::Channel),
},
],
preconditions: vec![Precondition::CanReach {
subject: Role("target".into()),
via: AudienceSpec::Channel(Role("channel".into())),
}],
effect_slots: Vec::new(),
outcome_bands: vec![OutcomeBand {
weight: 1,
effects: Vec::new(),
}],
carries_speech: true,
}),
],
operations: vec![ComponentOp::GrantAffordance {
subject: Ref::Existing(clockwork.farmer),
affordance: Ref::Draft(DraftHandle::new("hail")),
}],
evidence: Vec::new(),
},
},
)
.expect("the play authority declares the placeless outcast and its channel");
let positions = kernel.state.positions.clone();
let outcast = *kernel
.state
.subjects
.keys()
.find(|id| !positions.contains_key(id))
.expect("the declared placeless outcast");
let wire = *kernel.state.channels.keys().next().expect("the declared channel");
let snapshot = kernel.snapshot().unwrap();
let hail = affordance_named(&snapshot, "hail");
let opportunity = opportunity_for(&snapshot, clockwork.farmer);
let invocation = DecisionInvocation {
affordance: hail,
bindings: vec![
binding("target", Target::Subject(outcast)),
binding("channel", Target::Entity(wire)),
],
proposed: Vec::new(),
speech: Some(Statement::new("Hail!").unwrap()),
display: None,
};
submit_as(
&mut kernel,
CallerId::Controller(opportunity.controller_id),
CommandBody::ExerciseDecision {
invocation: invocation.clone(),
opportunity: opportunity.clone(),
},
)
.expect("the live outcast is reachable through the channel");
owner_retires(&mut kernel, outcast).expect("retire the outcast");
let snapshot = kernel.snapshot().unwrap();
let opportunity = opportunity_for(&snapshot, clockwork.farmer);
let error = submit_as(
&mut kernel,
CallerId::Controller(opportunity.controller_id),
CommandBody::ExerciseDecision { invocation, opportunity },
)
.unwrap_err();
assert!(
matches!(&error, KernelError::ActionRejected(set)
if set.contains(&ActionMismatch::CannotReach { precondition: 0 })),
"{error:?}"
);
}
}