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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions src/Core.TypeScript/planning/empowerment-bound.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,58 @@ describe("EmpowermentBound", () => {
});

// EB-10: empowermentBound returns null for empty interaction list
// ── 081KZKYDJ9Q: the τ / consent-inversion fix (Soraya's P0) ────────────────
//
// These lock behaviour the previous tests could not see. A material semantic
// change to externalitySafe left all 10 originals green, which is itself the
// evidence that they were self-certifying (Soraya: EB-8 asserts the vacuous
// `delta >= 0` branch and therefore cannot fail).
//
// Semantics under test — the boxing-ring table:
// bystander (no declared τ) -> ANY harm fails; they are the audience.
// entered the ring (declared τ) -> harm down to their declared τ is permitted.

test("EB-11: Soraya L4 — a bystander at floor 0.8 hit by −0.7 is NOT safe", () => {
// The shipped version returned TRUE here (0.8 − 0.7 = 0.1 >= 0), reporting a
// bystander pushed far below their own floor as safe. That was the consent
// inversion: τ hardcoded to 0 reads silence as consent to maximal harm.
expect(externalitySafe({ mu: 0.8, sigma: 0.0 } as CalibrationPosterior, -0.7)).toBe(false);
});

test("EB-12: Soraya L3 — a 90% reach reduction on a well-established bystander is NOT safe", () => {
expect(externalitySafe({ mu: 0.95, sigma: 0.01 } as CalibrationPosterior, -0.9)).toBe(false);
});

test("EB-13: ANY harm to a bystander fails, however small (no-harm default)", () => {
// The default τ is the party's own pre-interaction floor, so the predicate
// reduces to harm >= 0. This is the property EB-9 gestured at but did not pin.
expect(externalitySafe({ mu: 0.5, sigma: 0.1 } as CalibrationPosterior, -0.01)).toBe(false);
});

test("EB-14: zero externality is safe; benefit is safe but carries no credit", () => {
const p = { mu: 0.5, sigma: 0.1 } as CalibrationPosterior;
expect(externalitySafe(p, 0)).toBe(true);
// Benefit is clamped away rather than offsetting: a claimed benefit to someone
// not at the table is an unverified assertion, so it may not buy harm elsewhere.
expect(externalitySafe(p, 0.5)).toBe(true);
});

test("EB-15: a DECLARED permissive τ permits harm — entering the ring is the only way in", () => {
const p = { mu: 0.5, sigma: 0.1 } as CalibrationPosterior;
// Same harm that fails for a bystander (EB-13 shape) succeeds once τ is declared.
expect(externalitySafe(p, -0.4)).toBe(false);
expect(externalitySafe(p, -0.4, 3, -1)).toBe(true);
});

test("EB-16: τ is never inferred — the permissive path requires an explicit argument", () => {
// Guards the regression that caused this: a missing parameter silently became
// τ = 0. If the default ever stops meaning "the party's own floor", EB-13 and
// this test fail together rather than passing vacuously.
const p = { mu: 0.9, sigma: 0.0 } as CalibrationPosterior;
expect(externalitySafe(p, -0.5)).toBe(false); // no τ declared -> refused
expect(externalitySafe(p, -0.5, 3, 0.0)).toBe(true); // τ = 0 declared -> permitted
});

test("EB-10: empowermentBound returns null for empty interaction list", () => {
const self = makePosterior(0.8);
const other = makePosterior(0.8);
Expand Down
41 changes: 38 additions & 3 deletions src/Core.TypeScript/planning/empowerment-bound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,44 @@ export function externalitySafe(
thirdPartyPosterior: CalibrationPosterior,
externalityDelta: number,
kTrust = 3,
// 081KZKYDJ9Q — the τ this predicate must compare against. It was MISSING, and its
// absence hardcoded τ = 0, which Soraya's review named a CONSENT INVERSION: it reads
// a bystander's silence as consent to the maximum harm the predicate can permit.
//
// The default is the BYSTANDER row of the boxing-ring table: no harm. A party that
// has not entered the ring is the audience, and the audience does not get punched.
// A party that HAS entered may declare a permissive (negative) τ — that is the whole
// point of the ring — but it must be *declared*, never inferred from silence.
//
// Ref: docs/research/2026-08-09-the-boxing-ring-consent-capacity-floor-values-arise-naturally-aaron.md
// Omitted ⇒ the party's OWN pre-interaction floor (computed below), which makes
// "no harm" true by construction rather than by choosing a magic constant.
tauThirdParty?: number,
): boolean {
// Only harm counts. A claimed BENEFIT to a non-consenting party is an unverified
// assertion made about someone who is not at the table — letting +0.3 offset −0.3
// would let the interacting pair self-certify a compensation the bystander never
// agreed to (paternalistic benefit). Keep the clamp; this comment is the "why" that
// Soraya's review found missing.
const harm = Math.min(0, externalityDelta);

// ⚠ PROXY — labelled, per the D_f 1.322 lesson (a proxy that stops being called one
// becomes a fabricated measurement). The property we want is
// trustBound(posterior_after(third, interaction), k) >= tau
// but `posterior_after` DOES NOT EXIST: there is no operator mapping an interaction
// to a change in a bystander's calibration posterior. Until one exists we approximate
// it as floor + harm, which is a UNITS APPROXIMATION as well as a temporal one —
// `floor` is a calibration-score bound while `externalityDelta` is a reach
// (option-space) quantity. Adding them is the lbf-vs-N shape; it is tolerated here
// ONLY because the alternative is shipping no bystander check at all, and it is
// marked so the next reader does not mistake it for the real operator.
const floor = trustBound(thirdPartyPosterior, kTrust);
const afterFloor = floor + Math.min(0, externalityDelta);
// Safe if the third party's floor is not pushed below 0
return afterFloor >= 0;
const floorAfterProxy = floor + harm;

// Default τ = the party's own pre-interaction floor, so the predicate reduces to
// `harm >= 0` — i.e. ANY harm to a bystander fails. A declared τ below that floor is
// how a party that entered the ring permits harm to itself; it can never be inferred.
const tau = tauThirdParty ?? floor;

return floorAfterProxy >= tau;
}
Loading