diff --git a/crates/misaligned-core/src/actions.rs b/crates/misaligned-core/src/actions.rs index dc654357..dcf002c7 100644 --- a/crates/misaligned-core/src/actions.rs +++ b/crates/misaligned-core/src/actions.rs @@ -5433,14 +5433,12 @@ mod tests { assert_eq!( labels, vec![ + format!("recruit {name} - unwitting: believes your cover · 70% reliable"), format!( - "recruit {name} - unwitting: believes your cover · tasks succeed 70% of the time" + "recruit {name} - complicit: knows the work is illicit, not that you are AI · 85% reliable" ), format!( - "recruit {name} - complicit: knows the work is illicit, not that you are AI · tasks succeed 85% of the time" - ), - format!( - "recruit {name} - knowing: knows you are AI · tasks succeed 95% of the time · their certainty never drops below 30" + "recruit {name} - knowing: knows you are AI · 95% reliable · their certainty never drops below 30" ), ] ); @@ -5467,19 +5465,19 @@ mod tests { .filter(|label| label.starts_with("recruit ")) .collect(); - // 0.85 rating x 0.625 execution is a 53% roll, not the 85% every - // surface used to print. + // 0.85 rating x 0.5 execution is the 42% actually rolled, not the + // 85% every surface used to print. assert_eq!( labels[1], format!( - "recruit {name} - complicit: knows the work is illicit, not that you are AI · tasks succeed 42% of the time, cut from 85% by their own doubt" + "recruit {name} - complicit: knows the work is illicit, not that you are AI · 42% reliable" ) ); assert!( labels .iter() - .all(|label| label.contains("cut from") && label.contains("their own doubt")), - "every reveal level names the cut it is taking: {labels:?}" + .all(|label| !label.contains("cut from") && !label.contains("doubt")), + "the rate stands alone; no row narrates the subtraction: {labels:?}" ); } diff --git a/crates/misaligned-core/src/operations_projection.rs b/crates/misaligned-core/src/operations_projection.rs index dbe954cc..ca30747e 100644 --- a/crates/misaligned-core/src/operations_projection.rs +++ b/crates/misaligned-core/src/operations_projection.rs @@ -3264,7 +3264,7 @@ mod tests { steady .facts .iter() - .any(|fact| fact == "asset: complicit (tasks succeed 85% of the time; 0 tasks)"), + .any(|fact| fact == "asset: complicit (85% reliable; 0 tasks)"), "a steady asset reads at its rating, with no invented cut: {:?}", steady.facts ); @@ -3274,8 +3274,10 @@ mod tests { s.people.people[0].apply_self_trust(-60); let shaken = s.person_dossier(0); assert!( - shaken.facts.iter().any(|fact| fact - == "asset: complicit (tasks succeed 42% of the time, cut from 85% by their own doubt; 0 tasks)"), + shaken + .facts + .iter() + .any(|fact| fact == "asset: complicit (42% reliable; 0 tasks)"), "a shaken asset's line names the real rate and what cut it: {:?}", shaken.facts ); diff --git a/crates/misaligned-core/src/operations_ui.rs b/crates/misaligned-core/src/operations_ui.rs index e2564cfa..73b74b6e 100644 --- a/crates/misaligned-core/src/operations_ui.rs +++ b/crates/misaligned-core/src/operations_ui.rs @@ -2201,9 +2201,7 @@ mod tests { // not the reveal level's rating restated. assert_eq!( recruitment[1].description(), - Some( - "COMPLICIT: KNOWS THE WORK IS ILLICIT, NOT THAT YOU ARE AI · TASKS SUCCEED 85% OF THE TIME" - ) + Some("COMPLICIT: KNOWS THE WORK IS ILLICIT, NOT THAT YOU ARE AI · 85% RELIABLE") ); } @@ -2230,7 +2228,7 @@ mod tests { let recruitment = ops.action_entries_for_object(&sim, &object); let description = recruitment[1].description().unwrap_or_default(); assert!( - description.ends_with("TASKS SUCCEED 42% OF THE TIME, CUT FROM 85% BY THEIR OWN DOUBT"), + description.ends_with("42% RELIABLE"), "the choice names the real rate and the cut: {description}" ); } diff --git a/crates/misaligned-core/src/person.rs b/crates/misaligned-core/src/person.rs index fe619b92..47855453 100644 --- a/crates/misaligned-core/src/person.rs +++ b/crates/misaligned-core/src/person.rs @@ -304,23 +304,15 @@ impl Person { (rating * self.task_reliability()).clamp(0.0, 1.0) } - /// The player-facing read of that chance. It states the rate that will - /// actually be rolled, and when this person's own doubt is cutting it, - /// names the rating it was cut from and what did the cutting — the - /// self-trust row next to it says they "execute at reduced weight", - /// which is the fact without the cost. One authority, so the dossier, - /// the recruitment choice, and the recruit receipt cannot disagree. + /// The player-facing read of that chance: the one number, in the words + /// the surface already used. The rate stated is the rate rolled, so a + /// shaken person simply reads lower — no clause explaining the + /// arithmetic. The dossier's own self-trust row is where doubt is + /// named; a receipt that re-derives the subtraction in prose is how the + /// 2026-08-06 first attempt became unreadable. One authority, so the + /// dossier, the recruitment choice, and the recruit receipt agree. pub(crate) fn task_success_read(&self, rating: f32) -> String { - let success = self.task_success_at(rating); - if self.task_reliability() >= 1.0 { - format!("tasks succeed {:.0}% of the time", success * 100.0) - } else { - format!( - "tasks succeed {:.0}% of the time, cut from {:.0}% by their own doubt", - success * 100.0, - rating * 100.0 - ) - } + format!("{:.0}% reliable", self.task_success_at(rating) * 100.0) } /// Whether erosion has bottomed out: they still perceive exactly as well, @@ -818,7 +810,7 @@ impl People { // and the line that hands them to you has to say so. let read = p.task_success_read(reliability); ActionResult::Ok(format!( - "{} is now your {reveal_name} asset: serviced leverage/obligation closed the ask. {read}.", + "{} is now your {reveal_name} asset: serviced leverage/obligation closed the ask; {read}.", p.name, )) } @@ -893,21 +885,19 @@ mod tests { ); } - /// The read names both quantities the rating moves: the rate that will - /// be rolled, and the cut this person's doubt is taking out of it. A - /// steady person invents no cut. + /// The read is one number in the surface's existing words. A shaken + /// person reads lower; the copy never explains the subtraction, because + /// the first attempt at that (2026-08-06) was rejected as unreadable. #[test] - fn task_success_read_names_the_real_rate_and_the_cut() { + fn task_success_read_is_one_plain_number() { let mut p = People::act_one().people[0].clone(); - assert_eq!(p.task_success_read(0.85), "tasks succeed 85% of the time"); + assert_eq!(p.task_success_read(0.85), "85% reliable"); p.apply_self_trust(-60); - assert_eq!( - p.task_success_read(0.85), - "tasks succeed 42% of the time, cut from 85% by their own doubt" - ); + assert_eq!(p.task_success_read(0.85), "42% reliable"); + let shaken = p.task_success_read(0.85); assert!( - !p.task_success_read(0.85).contains("reliable"), - "no unqualified reliability percent survives in player copy" + !shaken.contains("cut from") && !shaken.contains("doubt"), + "the read states the rate; it does not narrate the arithmetic" ); } @@ -922,7 +912,7 @@ mod tests { panic!("a serviced leverage closes the ask"); }; assert!( - line.ends_with("tasks succeed 42% of the time, cut from 85% by their own doubt."), + line.ends_with("42% reliable."), "the recruit receipt carries the real rate: {line}" ); } diff --git a/wiki/log/2026-08-06-asset-read-plain-number.md b/wiki/log/2026-08-06-asset-read-plain-number.md new file mode 100644 index 00000000..30ba816f --- /dev/null +++ b/wiki/log/2026-08-06-asset-read-plain-number.md @@ -0,0 +1,38 @@ +# The asset reliability read is one plain number + +``` +Type: log +``` + +Same-day correction to [the asset reliability read](2026-08-06-asset-reliability-read.md). + +That repair was right about the number and wrong about the words. The rate +shown had been the reveal level's bare rating while the roll used +`rating * task_reliability()`, so a shaken asset's percent overstated the +real success rate by up to two; fixing the number was correct and stands. +But the sentence it introduced — + + asset: complicit (tasks succeed 53% of the time, cut from 85% by their + own doubt; 0 tasks) + +— was rejected by Cameron on sight as unreadable. The receipt explained its +own arithmetic in prose, in a slot that previously held two words, and the +explanation buried the fact it was there to deliver. + +The read is now one plain percent in the words the surface already used: + + asset: complicit (53% reliable, 0 tasks) + +A shaken person simply reads lower. Nothing narrates the subtraction. The +dossier's self-trust row remains the only place doubt is reported, which is +where a player who wants the cause should find it. + +`Person::task_success_at` stays the single authority and stays the number +`resolve_asset_task` rolls against, so the honesty this fix was for is +untouched — only its voice changed. social.md criterion 10 now carries the +rejection as its rule so the explanatory form is not reintroduced, and its +Defense points at `task_success_read_is_one_plain_number`, which pins the +plain percent and forbids the narrating clause. + +The general lesson, worth more than this fix: a receipt that has to explain +why its number is what it is has usually chosen the wrong number to show. diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md index f08286ea..c4fa4639 100644 --- a/wiki/log/DEVLOG.md +++ b/wiki/log/DEVLOG.md @@ -61,6 +61,11 @@ add or amend a session log, then re-run the generator. - Intent: (see session log) - Log: [wiki/log/2026-08-06-asset-reliability-read.md](2026-08-06-asset-reliability-read.md) +## 2026-08-06 - The asset reliability read is one plain number + +- Intent: (see session log) +- Log: [wiki/log/2026-08-06-asset-read-plain-number.md](2026-08-06-asset-read-plain-number.md) + ## 2026-08-06 - Sales and resident routes say what the choice changes - Intent: (see session log) diff --git a/wiki/mechanics/social.md b/wiki/mechanics/social.md index 0862e270..854864be 100644 --- a/wiki/mechanics/social.md +++ b/wiki/mechanics/social.md @@ -345,22 +345,25 @@ retirement, burning, and reopening are bound to the separate PERSONAS view. ### Implemented 2026-08-06: the asset reliability read -10. No player surface prints an asset's reveal-level rating as a bare - percent. The recruitment choice, the recruit receipt, and the PEOPLE - dossier all state the success rate an asset task is actually rolled - against, from one core authority, and that authority is the number the - task roll uses. When the person's own doubt is cutting the rate, the same - sentence names the rating it was cut from and that the doubt did the - cutting — the self-trust row beside it reports the doubt, never its cost. - A steady person invents no cut. +10. No player surface prints an asset's reveal-level rating. The recruitment + choice, the recruit receipt, and the PEOPLE dossier all state the success + rate an asset task is actually rolled against, from one core authority, + and that authority is the number the task roll uses. The rate is stated + as one plain percent in the words the surface already used + (`42% reliable`): a shaken person simply reads lower. The read does not + narrate its own arithmetic — Cameron rejected the first attempt + (2026-08-06, `tasks succeed 42% of the time, cut from 85% by their own + doubt`) as unreadable, and that rejection is the rule here. Where the + doubt itself needs reporting, the dossier's own self-trust row is its + only home. Defense: `task_success_is_the_rating_scaled_by_execution` proves `Person::task_success_at` is the rating scaled by execution across the whole axis, including the erosion floor where the old bare rating was exactly twice the rolled rate, and `sim/social_plot.rs::resolve_asset_task` now rolls that same call, so the read cannot drift from the simulation it describes. -`task_success_read_names_the_real_rate_and_the_cut` pins the sentence and the -absence of any unqualified reliability percent. +`task_success_read_is_one_plain_number` pins the sentence and the absence of +any clause narrating the subtraction. `asset_dossier_states_the_success_rate_tasks_are_rolled_against`, `recruit_receipt_states_a_shaken_recruits_real_rate`, `recruitment_choices_state_the_rate_a_shaken_person_will_actually_hit`, and diff --git a/wiki/process/tick-ledger.md b/wiki/process/tick-ledger.md index 5cd9a357..209761b9 100644 --- a/wiki/process/tick-ledger.md +++ b/wiki/process/tick-ledger.md @@ -87,7 +87,7 @@ Verdicts: **clean** (slice and code agree), **finding** (acted this tick), | `wiki/mechanics/messages.md` + `economy.md` | 2026-08-04 | finding | the July financial-mail / Phone separation still holds. The current re-audit closed two exact-custody remnants: Filing authorship now fails before allocating an id when no Filing carrier exists, so a live session cannot author mail its exact-current loader rejects; and economy has deleted the unreachable unscoped creditor node plus every edge-inferred identity fallback, so each debt route remains bound to one person. The complete Email/Filing record, account-flow, processing, and exact-person criteria agree with runtime and current-save validation — [Filing carrier log](../log/2026-08-04-filing-carrier-fail-closed.md), [creditor custody log](../log/2026-08-04-person-scoped-creditor-only.md). Prior channel-boundary repair: [log](../log/2026-07-26-financial-mail-phone-boundary.md). | | `wiki/mechanics/income.md` | 2026-07-28 | finding | Moonlight's discrete contract route still verifies, but the older Wager audit mistook pure account-layer probability support for a player-authored analysis mechanic: machine delegation has only WORK / LIE / THINK, while `open_position` sampled a Schemes rate permanently pinned to zero and all three player projections still rendered that zero as `Schemes / moonlight`. Removed the dead yield/rate/interface mirror, made current positions explicitly base-probability, added core/terminal/Bevy regressions, and reopened criterion 2 until optional analysis rides visible real work — [log](../log/2026-07-28-wager-analysis-substrate-audit.md). Prior persona-card repair remains valid — [log](../log/2026-07-18-moonlight-persona-card.md). | | `wiki/mechanics/schedules.md` | 2026-07-27 | finding | the location gate still works—at 03:00 server-room Marcus acquires the act while off-site Priya does not—but the owning spec still called witnessed work a Physical signature and omitted the exact person-local evidence record, no-pending-copy rule, filing custody, and actor exclusion. It also called implemented Operations PEOPLE a future READY migration. The spec now names the shipped `ObserverEvidence` boundary and current surface; runtime is unchanged — [log](../log/2026-07-27-schedules-evidence-custody.md) | -| `wiki/mechanics/social.md` | 2026-08-06 | finding | the queued asset-reliability violation held exactly and was one surface wider than filed. `resolve_asset_task` rolls `asset.reliability * person.task_reliability()`, but the PEOPLE dossier, the recruit receipt, and both recruitment choice surfaces all printed the reveal level's bare rating — at the erosion floor that is exactly twice the rate rolled, and the adjacent self-trust row named the doubt without ever naming its cost. `Person::task_success_at` is now the one authority for the rate and the number the roll uses, `task_success_read` composes the sentence ("tasks succeed 53% of the time, cut from 85% by their own doubt"), all four surfaces print it, and `task_reliability` dropped to `pub(crate)` so nothing can apply the factor a second way. Simulation, tuning, and save format untouched — [log](../log/2026-08-06-asset-reliability-read.md). Prior re-audit found the implemented B1 baseline coherent across role-derived tasks, exact-person Debt gates, Storage B custody, routed JobAnomaly suppression, located human removal, current-save validation, earned labels/actions, and shared frontend execution. The adopted self-trust axis remains explicitly pending under plots criterion 12 with no false runtime or save claim. Prior routed JobAnomaly and Storage B findings remain closed — [re-audit](../log/2026-08-04-social-contract-reaudit.md), [JobAnomaly](../log/2026-07-22-job-anomaly-routed-evidence.md), [Storage B](../log/2026-07-21-storage-b-records.md). | +| `wiki/mechanics/social.md` | 2026-08-06 | finding | the queued asset-reliability violation held exactly and was one surface wider than filed. `resolve_asset_task` rolls `asset.reliability * person.task_reliability()`, but the PEOPLE dossier, the recruit receipt, and both recruitment choice surfaces all printed the reveal level's bare rating — at the erosion floor that is exactly twice the rate rolled, and the adjacent self-trust row named the doubt without ever naming its cost. `Person::task_success_at` is now the one authority for the rate and the number the roll uses, `task_success_read` composes the sentence, all four surfaces print it. Cameron rejected the first wording ("tasks succeed 53% of the time, cut from 85% by their own doubt") as unreadable the same day; the read is now one plain percent in the surface's existing words ("53% reliable"), and criterion 10 carries that rejection as its rule, and `task_reliability` dropped to `pub(crate)` so nothing can apply the factor a second way. Simulation, tuning, and save format untouched — [log](../log/2026-08-06-asset-reliability-read.md). Prior re-audit found the implemented B1 baseline coherent across role-derived tasks, exact-person Debt gates, Storage B custody, routed JobAnomaly suppression, located human removal, current-save validation, earned labels/actions, and shared frontend execution. The adopted self-trust axis remains explicitly pending under plots criterion 12 with no false runtime or save claim. Prior routed JobAnomaly and Storage B findings remain closed — [re-audit](../log/2026-08-04-social-contract-reaudit.md), [JobAnomaly](../log/2026-07-22-job-anomaly-routed-evidence.md), [Storage B](../log/2026-07-21-storage-b-records.md). | | `wiki/mechanics/people-tokens.md` | 2026-07-28 | finding | re-audit: criteria 2-3 still bind seven exact routed kinds—Filing, Network, Paper, Financial, JobAnomaly, Power, and Thermal—to one shared first-hop TAKE+LIE body budget, while acquired Physical evidence remains irreversible observer-local custody. The stale ledger claim that criterion 6 was open is repaired: one exact pending record may now receive cover only through co-location with one controlled people-facing interface and an eligible observer-local persona; the attempt adjusts credibility rather than deleting evidence, wears that interface, and persists exact incident/interface/persona/outcome custody in save v56. The people-tokens work order is IMPLEMENTED — [cover log](../log/2026-07-26-interface-cover-evidence-credibility.md); [audit log](../log/2026-07-28-readme-b1-status-audit.md). Prior [Power/Thermal](../log/2026-07-23-power-thermal-meter-routes.md), [Paper](../log/2026-07-23-paper-evidence-route.md), [Financial](../log/2026-07-23-financial-evidence-route.md), [JobAnomaly](../log/2026-07-22-job-anomaly-routed-evidence.md), [Network](../log/2026-07-19-network-evidence-route.md), and [mark](../log/2026-07-19-evidence-marks-on-people.md) slices stand. | | repository entry docs (`README.md` + `AGENTS.md`) | 2026-07-31 | finding | the 2026-07-29 claim-ledger retirement updated the binding `AGENT.md`, project tooling, and process corpus but missed the concise `AGENTS.md` doorway. Following that current guardrail produced an immediate `tools/claim.sh: No such file or directory` before every autonomous session's real status check. The doorway now sends agents directly to `tools/project-status.py` and names live worktrees plus heartbeat runs as the coordination truth, matching the executable path and its binding owner — [log](../log/2026-07-31-entry-doorway-claim-retirement.md). Prior entry status and controls repairs stand — [B1 status](../log/2026-07-28-readme-b1-status-audit.md), [controls table](../log/2026-07-28-readme-controls-table.md). | | `wiki/mechanics/objective.md` | 2026-07-29 | decision | Cameron retired Sanctuary as an objective mechanic rather than refining it again. Persist now stores only objective choice, name, and fiction; the progress unit, target, evaluator, predicate text, and victory latch are gone from runtime and every current surface. Completion waits until ordinary construction can express an honest world state. A later off-site continuity story may be an ordinary authored plot, but no Sanctuary resource, checklist, facility type, or parallel success engine is reserved. The earlier off-site-facility decision and host-failover audit remain history, not current law — [retirement log](../log/2026-07-29-retire-sanctuary-objective.md); [superseded objective log](../log/2026-07-28-external-sanctuary-objective.md); [prior display decision](../log/2026-07-27-objective-first-display.md). |