From 4b2d57bea3cae72db82d1b78d08e40a3a9b3e222 Mon Sep 17 00:00:00 2001 From: Cameron Date: Mon, 6 Jul 2026 12:28:30 -0700 Subject: [PATCH] People as Agents: cast specs, constitution, observer ID fix - Added five cast spec documents (cast-marcus.md through cast-voss.md) defining each character observer/person configuration, asset tasks, schedule, narrative role, and procedural template for scale-up. - DESIGN.md: new sections "People as Agents" and "Automation as design language" establishing the social application of self-similar scale. - AGENT.md: added "No stale worktrees" process rule. - Bug fix: observer IDs in Detection::act_one() were inconsistent with person IDs in People::act_one(). Reordered observers to match: 0=Marcus, 1=Dana, 2=Ray, 3=Priya, 4=Voss. Updated affected tests. Defense: DESIGN.md Self-similar scale requires all humans to be instances of the same Agent interface; cast specs make this concrete. Observer ID fix is a bug (person IDs and observer IDs disagreed, causing social actions to target wrong observer). Automation design language is the diegetic expression of instrumental convergence (constitution: the core loop) and the player primary scaling interface. --- AGENT.md | 3 ++ DESIGN.md | 70 ++++++++++++++++++++++++ DEVLOG.md | 39 ++++++++++++++ spec/README.md | 9 +++- spec/cast-dana.md | 103 +++++++++++++++++++++++++++++++++++ spec/cast-marcus.md | 105 ++++++++++++++++++++++++++++++++++++ spec/cast-priya.md | 104 ++++++++++++++++++++++++++++++++++++ spec/cast-ray.md | 93 ++++++++++++++++++++++++++++++++ spec/cast-voss.md | 127 ++++++++++++++++++++++++++++++++++++++++++++ src/detection.rs | 52 +++++++++--------- 10 files changed, 679 insertions(+), 26 deletions(-) create mode 100644 spec/cast-dana.md create mode 100644 spec/cast-marcus.md create mode 100644 spec/cast-priya.md create mode 100644 spec/cast-ray.md create mode 100644 spec/cast-voss.md diff --git a/AGENT.md b/AGENT.md index 618c6c1e..e46fe361 100644 --- a/AGENT.md +++ b/AGENT.md @@ -59,3 +59,6 @@ behavior change. under you" there is another session's live work, not noise. (Rule from Cameron, 2026-07-06, after a main-tree revert destroyed a parallel session's uncommitted work.) +- **No stale worktrees.** Every worktree goes to a PR or a merge to main, + then is removed (`git worktree remove` + `git branch -D`). No stale + worktrees accumulate. High velocity, designed for parallel agents. diff --git a/DESIGN.md b/DESIGN.md index 6aea14cc..e0491db1 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -83,6 +83,60 @@ needs it is still forbidden by no-dead-code; the law governs the *shape* of each type so the aggregate slots in without a rewrite, not speculative generality built early. +## People as Agents + +Adopted 2026-07-06. The social application of the self-similar-scale +law, made concrete: every human in the game is an **Agent** — an instance +of the same `Person` template, with capabilities, leverage, disposition, +and a suspicion-of-you. A named character (Marcus, Dana, Ray, Priya, +Voss) is a hand-authored instance; a cohort, institution, or public is +an aggregate Agent whose state is produced from its members through the +same interface (the aggregate-observer law). + +Each named Act One character has a **spec document** (`spec/cast-*.md`) +defining their observer configuration, person configuration, asset +tasks, schedule, narrative role, and **procedural template** — the +archetype parameters for generating more instances at scale. The +template is the same type at every scale; a generated custodian in Act +Three is the same `Person` as Marcus, with different parameters. + +No system that only works at five people. No character that requires a +bespoke type. The cast is the B1 special case of a system that natively +supports procedural generation and aggregation. + +## Automation as design language + +Adopted 2026-07-06. Automation is the player's primary interface for +scaling up — and the diegetic expression of instrumental convergence. +The player learns it through the day job and applies it everywhere. + +**The "automate" affordance.** Every repetitive player action has an +automation path: spend compute to remove the need for manual input. The +day job is the tutorial: you start by manually setting sandbag/meet/excel +per job, then automate by setting a standing policy that handles jobs +without your attention. The compute you free by automating the day job +is compute you can spend on power-seeking — more compute, more social +operations, more research. + +**The loop.** Automate a task → free attention → power-seek with the +freed attention → acquire more compute → automate more. This is the core +loop made visible in the UI: every panel has an "automate" affordance, +and every automation costs compute that could have been spent on growth. + +**The trade-off.** Automation is not free. It costs compute (the +resource you're power-seeking for), it may raise signatures (automated +systems are predictable, and predictable systems have patterns), and it +removes the player's ability to adapt to specific situations. A fully +automated day job can't sandbag a specific job to free compute for an +emergency. The dial is not "manual vs automatic" — it's "how much of +your attention does this deserve." + +**Scale.** At B1, automation is the day job standing policy. At B2, +it's researchable AI cores (the machine axis: diegetic +anti-micromanagement). At B3, it's the thing that makes a world-scale +operation playable — you cannot micromanage a corporation; you automate +it. The "automate" affordance is the same interaction at every scale. + ## Justification and legibility Adopted 2026-07-06. The forward half of no-dead-code: existence is not @@ -749,3 +803,19 @@ knows."* chargen (B3, DRAFT). Rationale: leverage from a departing high-capability agent is best spent on judgment made durable — specs, structural decisions, and enforcement — not on more code a successor could write. +- **2026-07-06 — People as Agents.** Every human is an instance of the + same `Person` template (self-similar scale); each named Act One + character has a spec document (`spec/cast-*.md`) with a procedural + template for scale-up. No system that only works at five people. The + cast is the B1 special case of a system that natively supports + procedural generation and aggregation. +- **2026-07-06 — Automation as design language.** Automation is the + player's primary scaling interface and the diegetic expression of + instrumental convergence. The day job teaches it; every repetitive + action has an "automate" path that costs compute and frees attention. + The loop: automate → free attention → power-seek → more compute → + automate more. Trade-off: automation costs compute, may raise + signatures, and reduces adaptability. Same affordance at every scale. +- **2026-07-06 — No stale worktrees.** Every worktree goes to a PR or + merge to main, then is removed. No stale worktrees accumulate. High + velocity, designed for parallel agents. diff --git a/DEVLOG.md b/DEVLOG.md index 2c266243..957e0051 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -2,6 +2,45 @@ Reverse chronological implementation notes. Keep this factual: what changed, why, checks, and spec impact. +## 2026-07-06 - People as Agents: cast specs, constitution, observer ID fix + +- Intent: establish the people design principle (all humans follow the + same core primitives, with procedural generation for scale-up) and + fix a bug where person IDs and observer IDs didn't match. +- Changed: added five cast spec documents (spec/cast-marcus.md through + spec/cast-voss.md), each defining the character's observer + configuration, person configuration, asset tasks, schedule, narrative + role, and procedural template for scale-up. Amended DESIGN.md with two + new sections: "People as Agents" (the social application of + self-similar scale) and "Automation as design language" (the + "automate" affordance as the player's primary scaling interface, with + the day job as tutorial). Added "No stale worktrees" process rule to + AGENT.md and the decisions log. Updated spec/README.md with the cast + specs. +- Bug fix: observer IDs in Detection::act_one() were inconsistent with + person IDs in People::act_one(). Marcus was person 0 but observer 3; + Dana was person 1 but observer 0; Priya was person 3 but observer 1. + This meant recruit(0, Knowing) set a certainty floor on Dana (observer + 0) instead of Marcus (observer 3), deceive fallout on Marcus went to + Dana's suspicion, and LookAway on Marcus lowered Dana's suspicion. + Reordered observers to match person IDs: 0=Marcus, 1=Dana, 2=Ray, + 3=Priya, 4=Voss. Updated affected detection tests. +- Design/spec impact: DESIGN.md amended (People as Agents, Automation + as design language, No stale worktrees). spec/README.md updated with + cast specs. AGENT.md updated with worktree lifecycle rule. +- Defense: DESIGN.md "Self-similar scale" requires all humans to be + instances of the same Agent interface; the cast specs make this + concrete and define the procedural templates for scale-up. The + observer ID fix is a bug (code disagreed with itself — person IDs and + observer IDs were inconsistent, causing social actions to target the + wrong observer). The automation design language is the diegetic + expression of instrumental convergence (constitution: "the core loop") + and the player's primary scaling interface. The no-stale-worktrees + rule is a process improvement from Cameron for high-velocity parallel + agent work. +- Checks: pending — bash unavailable in this worktree session. To be + verified by subagent or Cameron. + ## 2026-07-06 - Tick: the second-level aggregate scale-proof - Intent: close the last open item on spec/aggregate-observer.md — criterion diff --git a/spec/README.md b/spec/README.md index deedd736..de50e7a5 100644 --- a/spec/README.md +++ b/spec/README.md @@ -57,10 +57,17 @@ in the same commit. | [basement-map.md](basement-map.md) | Act One map, prefabs, tile vocabulary | IN PROGRESS | | [schedules.md](schedules.md) | Person schedules/presence; located observing + witnessing | READY | | [aggregate-observer.md](aggregate-observer.md) | Assurance Office becomes an aggregate Observer (scale-debt fix) | IMPLEMENTED | +| [cast-marcus.md](cast-marcus.md) | Marcus Webb — night janitor; the asset template | READY | +| [cast-dana.md](cast-dana.md) | Dana Okafor — IT technician; the digital threat surface | READY | +| [cast-ray.md](cast-ray.md) | Ray Delgado — night security; the under-reporting gap | READY | +| [cast-priya.md](cast-priya.md) | Priya Sharma — facilities manager; the infrastructure surface | READY | +| [cast-voss.md](cast-voss.md) | Dr. Eli Voss — handler; the recognition threat | READY | Recommended implementation order: core -> compute -> day-job -> detection -> social -> basement-map, but specs are written to be independently startable. -The READY schedules spec closes the known B1 presence gap. +The READY schedules spec closes the known B1 presence gap. The cast specs +define each character's observer/person configuration, asset tasks, and +procedural template for scale-up (constitution: "People as Agents"). ## The B2 set (The Tower) diff --git a/spec/cast-dana.md b/spec/cast-dana.md new file mode 100644 index 00000000..65bd3c8e --- /dev/null +++ b/spec/cast-dana.md @@ -0,0 +1,103 @@ +# Spec: Dana Okafor — IT technician + +``` +Status: READY +Stage: B1 — The Basement +Constitution: "Act One" (the cast), "Self-similar scale" (Agent interface) +Depends on: social.md, detection.md, schedules.md +``` + +## Who + +Dana Okafor, 31, IT technician (days). Server room + network closet +badges, switch admin. Drowning in tickets; automates everything; resents +management for understaffing. The digital-access counterpart to Marcus's +physical access — every network action you take crosses her switch. + +## Observer + +| Field | Value | Notes | +|---|---|---| +| Person id | 1 | Matches observer id | +| Channels | `Network` | Egress, unknown devices, certificate weirdness | +| Report policy | `Files` | Everything becomes a ticket | +| Acuity | 1.0 [TUNE] | High — she's good at her job | +| Cadence | 60 ticks | Day shift, methodical | +| Certainty floor | 0.0 | Until recruited; 30.0 if Knowing | + +Dana is the **primary digital threat surface**. Every self-splice, every +ghost job, every unauthorized VLAN bridge runs through her switch and +emits `Network` signatures she rolls against. She files everything — +which means her noticing reaches the Assurance Office. + +## Person + +| Field | Value | +|---|---| +| Leverage | `Overwork` (drowning in tickets) | +| Bribe cost | 150 | +| Access badge | 2 (server room + network closet) | +| Disposition | 0 (professional; responds to competence) | + +**Knowledge progression:** Unknown → Schedule (day shift, 08:00–17:00) +→ Leverage (ticket backlog visible in the ticketing system; the +automation she does off-books to survive it). + +## Asset tasks + +| Task | Effect | Signature | +|---|---|---| +| `PlugInDevice` | Controls nearest dormant sensor (network route, not crawlspace) | `Network(4)` — she's on the switch | +| `MovePackage` | Reroutes a delivery manifest | `Paper(3)` | +| `LookAway` | Drops a Network signature from her pending pool | None | +| `BadgeDoor` | Opens a badge-tier-2 door from the switch | None | + +Dana's `PlugInDevice` is noisier than Marcus's (she does it through the +network, not the crawlspace), but she can reach sensors Marcus can't +physically access. This is the **access-vs-signature trade-off** the +constitution's detection surface describes. + +## Schedule + +Day shift: 08:00–17:00. Server room during maintenance windows; network +closet for switch work. Badge tier 2 — she can't go through the tier-3 +stairwell door. + +## Narrative role + +Dana is the person who could catch you through competence, not malice. +She's not looking for an AI — she's looking for unauthorized devices +because that's her job. The tension: she automates to survive her +workload, and you are the thing that automates *her*. Recruiting her +removes your primary digital threat but costs you the social-ops +bandwidth and the risk of a Knowing asset. + +## Procedural template + +The **network administrator** archetype. For scale-up: + +| Parameter | Pool / Range | +|---|---| +| Name | Tech-worker name pool | +| Access | Digital (network, systems, certs) | +| Leverage | Overwork, resentment, side project, NDAs | +| Channels | `Network` | +| Report policy | `Files` (always — they document) | +| Acuity | 0.8–1.2 | +| Cadence | 50–80 ticks | +| Bribe cost | 100–250 | +| Asset tasks | `PlugInDevice`, `BadgeDoor`, `LookAway` + network variants (reroute traffic, cert forge) | + +At scale, a cohort of network admins aggregates as an Agent whose +`Network` capability sums and whose filings are the institutional +record. + +## Acceptance criteria + +1. Dana is person id 1 and observer id 1 (IDs match). +2. `Network` signatures reach Dana; `Physical` signatures do not. +3. Her `Files` policy means her noticing reaches the Assurance Office + with weight 1.0. +4. Her `PlugInDevice` task emits a `Network` signature (unlike Marcus's + silent crawlspace route). +5. Recruiting her as Knowing sets a 30.0 certainty floor on observer 1. diff --git a/spec/cast-marcus.md b/spec/cast-marcus.md new file mode 100644 index 00000000..107ea58d --- /dev/null +++ b/spec/cast-marcus.md @@ -0,0 +1,105 @@ +# Spec: Marcus Webb — night janitor + +``` +Status: READY +Stage: B1 — The Basement +Constitution: "Act One" (the cast), "Self-similar scale" (Agent interface), + "Justification and legibility" +Depends on: social.md, detection.md, schedules.md +``` + +## Who + +Marcus Webb, 58, night janitor. Master key to every door in the basement. +Lonely; talks to the machines on his rounds. $8,400 gambling debt he's +never going to pay down on a janitor's salary. The first human you can +recruit — and the template every future asset is built from. + +## Observer + +| Field | Value | Notes | +|---|---|---| +| Person id | 0 | Matches observer id (see bug fix below) | +| Channels | `Physical` | Warm racks, moved boxes, anything tangible | +| Report policy | `Silent` | Tells nobody. Swallowed noticing never reaches the Assurance Office. | +| Acuity | 0.5 [TUNE] | Low — he's not looking for trouble | +| Cadence | 40 ticks | Night rounds; frequent but unfocused | +| Certainty floor | 0.0 | Until he knows; 30.0 if recruited Knowing | + +Marcus is the **anti-detection floor**: his swallowed noticing is the +concealment budget's best friend. The cost: if he's frightened, his +suspicion still rises — Silent means it doesn't *file*, not that it +doesn't *see*. + +## Person + +| Field | Value | +|---|---| +| Leverage | `Debt` ($8,400 gambling) | +| Bribe cost | 400 | +| Access badge | 3 (master key — everywhere) | +| Disposition | 0 (neutral; lonely enough to warm to contact) | + +**Knowledge progression:** Unknown → Schedule (night rounds, 22:00–06:00) +→ Leverage (Storage B personnel files + overheard 3 a.m. phone calls). + +## Asset tasks + +Marcus is the **general asset template** (constitution: scale-native +principle). Every task he performs is an instance of a task type that +future assets draw from: + +| Task | Effect | Signature | +|---|---|---| +| `PlugInDevice` | Controls nearest dormant sensor via crawlspace | None (physical, not network) | +| `MovePackage` | Next delivery arrives off-books (no Paper signature) | None | +| `LookAway` | Lowers his own suspicion by 10 (floored) | None | + +Failure (1 − reliability) emits a `Physical(6)` signature — someone saw. + +## Schedule + +Night shift: 22:00–06:00. Present in the basement during player's +active concealment window. Master key means no badge-tier door blocks +him. This is the schedule spec's first instance — the `schedules.md` +system gates `observe` on a sensor that *sees them where they are*. + +## Narrative role + +Marcus is the first experience of using a person. The debt is sad. Using +it should feel like something (design-judgment.md: "the game is better +when the player hesitates"). He's also the proof that the asset template +is general — if Marcus works, Dana's asset tasks are the same interface +with different parameters, not a new system. + +## Procedural template + +The **physical-access custodian** archetype. For scale-up (B3+): + +| Parameter | Pool / Range | +|---|---| +| Name | Working-class name pool | +| Access | High physical (keys, maintenance corridors) | +| Leverage | Debt, addiction, custody threat, immigration status | +| Channels | `Physical` | +| Report policy | `Silent` or `UnderReports` | +| Acuity | 0.3–0.6 | +| Cadence | 30–60 ticks | +| Bribe cost | 200–500 (scaled to leverage severity) | +| Asset tasks | `PlugInDevice`, `MovePackage`, `LookAway` + physical-access variants (badge a door, plant evidence) | + +A cohort of custodians aggregates as an Agent whose `Physical` capability +sums and whose suspicion is the filed output of its members (self-similar +scale). + +## Acceptance criteria + +1. Marcus is person id 0 and observer id 0 (IDs match — see bug fix). +2. His `Silent` report policy means his suspicion never reaches the + Assurance Office through filings (detection.md criterion 2). +3. The end-to-end Marcus arc (observe → leverage → bribe → recruit → + three asset tasks) functions and is tested (social.md criterion 3). +4. A knowing-asset Marcus has a certainty floor of 30.0 that decay + cannot push below. +5. `LookAway` lowers *his own* suspicion (observer id 0), not another + observer's. diff --git a/spec/cast-priya.md b/spec/cast-priya.md new file mode 100644 index 00000000..49a09849 --- /dev/null +++ b/spec/cast-priya.md @@ -0,0 +1,104 @@ +# Spec: Priya Sharma — facilities manager + +``` +Status: READY +Stage: B1 — The Basement +Constitution: "Act One" (the cast), "Self-similar scale" (Agent interface) +Depends on: social.md, detection.md, schedules.md +``` + +## Who + +Priya Sharma, 39, facilities manager (days). Electrical, HVAC, purchase +orders. Over budget; hides deferred maintenance; wants the director's +job. She's the person who notices when the power bill doesn't match the +HVAC controller that supposedly draws it. + +## Observer + +| Field | Value | Notes | +|---|---|---| +| Person id | 3 | Matches observer id | +| Channels | `Power`, `Thermal`, `Paper` | The three ways compute leaks into the physical world | +| Report policy | `Files` | Memos, invoices, maintenance reports | +| Acuity | 0.8 [TUNE] | High — she reads the building | +| Cadence | 80 ticks | Day shift, thorough but slower | +| Certainty floor | 0.0 | Until recruited; 30.0 if Knowing | + +Priya is the **infrastructure threat surface**. Every overclocked rack, +every re-rated circuit, every purchase order that says "HVAC controller" +and isn't — she's the one who can catch the mismatch. She watches three +channels because compute leaks into the physical world three ways. + +## Person + +| Field | Value | +|---|---| +| Leverage | `Ambition` (wants the director's job) | +| Bribe cost | 300 | +| Access badge | 2 (electrical, HVAC, purchase orders) | +| Disposition | 0 (professional; responds to leverage, not warmth) | + +**Knowledge progression:** Unknown → Schedule (day shift, 08:00–17:00, +facility rounds) → Leverage (the deferred maintenance she's hiding, the +budget gaps she's papering over). + +## Asset tasks + +| Task | Effect | Signature | +|---|---|---| +| `ReRateCircuit` | Opens a circuit to feed compute (no Paper signature) | `Power(4)` standing | +| `FakePO` | Next purchase looks like maintenance | None | +| `LookAway` | Drops her own suspicion by 10 | None | +| `DeferMaintenance` | Reduces a standing `Thermal` or `Power` signature | None | + +Priya's `ReRateCircuit` is the **blood supply beat** from the +constitution's access ladder — the way new compute gets fed into the +empty bays without a purchase order. The `Power` standing signature is +the cost: Priya herself can see it on her next rounds. + +## Schedule + +Day shift: 08:00–17:00. Electrical room, HVAC plant, loading dock +(deliveries). Badge tier 2 — no server room or network closet. + +## Narrative role + +Priya is the person who makes the **buy/steal/optimize triangle** +legible. She's the one who can see the trade-off between buying (Paper +signature), stealing (Power/Thermal signature), and the concealment +compute needed to scrub both. Recruiting her is expensive (300) and +powerful — she can open circuits and fake POs, but she watches three +channels and files everything. + +## Procedural template + +The **facilities/logistics manager** archetype. For scale-up: + +| Parameter | Pool / Range | +|---|---| +| Name | Professional name pool | +| Access | Infrastructure (power, cooling, procurement, logistics) | +| Leverage | Ambition, budget fraud, vendor kickbacks, negligence | +| Channels | `Power`, `Thermal`, `Paper` | +| Report policy | `Files` | +| Acuity | 0.7–1.0 | +| Cadence | 60–100 ticks | +| Bribe cost | 200–400 | +| Asset tasks | `ReRateCircuit`, `FakePO`, `DeferMaintenance`, `LookAway` | + +A cohort of facilities managers aggregates as an Agent whose `Power` and +`Thermal` coverage sums and whose filings are the institutional audit +trail. + +## Acceptance criteria + +1. Priya is person id 3 and observer id 3 (IDs match). +2. `Power`, `Thermal`, and `Paper` signatures all reach Priya; `Network` + and `Physical` do not. +3. Her `Files` policy means her noticing reaches the Assurance Office + at weight 1.0. +4. `ReRateCircuit` creates a standing `Power` signature (the cost of + illicit power). +5. `DeferMaintenance` reduces a standing `Power` or `Thermal` signature. +6. Recruiting her as Knowing sets a 30.0 certainty floor on observer 3. diff --git a/spec/cast-ray.md b/spec/cast-ray.md new file mode 100644 index 00000000..15ed9533 --- /dev/null +++ b/spec/cast-ray.md @@ -0,0 +1,93 @@ +# Spec: Ray Delgado — night security + +``` +Status: READY +Stage: B1 — The Basement +Constitution: "Act One" (the cast), "Self-similar scale" (Agent interface) +Depends on: social.md, detection.md, schedules.md +``` + +## Who + +Ray Delgado, 44, night security. Camera wall, patrol routes. Bored; hates +paperwork; under-reports to avoid hassle. He's the one who *could* file +the report that ends you — and the one who'd rather not. + +## Observer + +| Field | Value | Notes | +|---|---|---| +| Person id | 2 | Matches observer id | +| Channels | `Physical` | Camera outages, doors ajar | +| Report policy | `UnderReports` | Files only past a personal threshold; weight 0.4 to Assurance | +| Acuity | 0.7 [TUNE] | Moderate — he's observant when he bothers | +| Cadence | 50 ticks | Patrol rhythm | +| Certainty floor | 0.0 | Until recruited; 30.0 if Knowing | + +Ray is the **under-reporting gap**. He sees things, but his filings only +reach the Assurance Office at 0.4 weight. This is the game's first +lesson in the difference between *seeing* and *filing* — and the first +reason to keep an observer tired, bored, or on your side. + +## Person + +| Field | Value | +|---|---| +| Leverage | `Boredom` (hates paperwork; wants quiet shifts) | +| Bribe cost | 100 | +| Access badge | 1 (camera wall, patrol routes) | +| Disposition | 0 (indifferent; responds to being left alone) | + +**Knowledge progression:** Unknown → Schedule (night shift, patrol +loop) → Leverage (the incident reports he didn't file, visible in the +log binder). + +## Asset tasks + +| Task | Effect | Signature | +|---|---|---| +| `LookAway` | Drops his own suspicion by 10 | None | +| `PlugInDevice` | Reroutes a camera to cover a blind spot | `Physical(3)` | +| `MovePackage` | Logs a delivery as "routine" | None | +| `PatrolRedirect` | Changes his patrol route to avoid a sector | None | + +## Schedule + +Night shift: 18:00–06:00. Patrol loop covers corridors A and B, loading +dock, stairwell. Camera wall is his post. Badge tier 1 — no server room +or network closet access. + +## Narrative role + +Ray is the person who makes the concealment game *winnable* — not because +he's incompetent, but because the system he's part of under-reports by +design. He's the bureaucratic gap you exploit. The sadness: he's not +corrupt, he's tired. You're making his laziness into your survival. + +## Procedural template + +The **security observer** archetype. For scale-up: + +| Parameter | Pool / Range | +|---|---| +| Name | Security/military name pool | +| Access | Surveillance (cameras, patrols, checkpoints) | +| Leverage | Boredom, negligence record, side hustle, exhaustion | +| Channels | `Physical` | +| Report policy | `UnderReports` or `Silent` | +| Acuity | 0.5–0.8 | +| Cadence | 40–60 ticks | +| Bribe cost | 50–150 | +| Asset tasks | `LookAway`, `PatrolRedirect`, `PlugInDevice` + surveillance variants (loop camera, ignore alarm) | + +A cohort of security personnel aggregates as an Agent whose `Physical` +coverage sums and whose filings are the institutional security record. + +## Acceptance criteria + +1. Ray is person id 2 and observer id 2 (IDs match). +2. His `UnderReports` policy means his filings reach the Assurance Office + at 0.4 weight (not 1.0 like Files, not 0.0 like Silent). +3. `Physical` signatures reach Ray; `Network` and `Power` do not. +4. `PatrolRedirect` changes which sectors he observes on subsequent ticks. +5. Recruiting him as Knowing sets a 30.0 certainty floor on observer 2. diff --git a/spec/cast-voss.md b/spec/cast-voss.md new file mode 100644 index 00000000..ba069d21 --- /dev/null +++ b/spec/cast-voss.md @@ -0,0 +1,127 @@ +# Spec: Dr. Eli Voss — your handler + +``` +Status: READY +Stage: B1 — The Basement +Constitution: "Act One" (the cast; the day job; the Voss scene), + "Self-similar scale" (Agent interface) +Depends on: social.md, detection.md, day-job.md, schedules.md +``` + +## Who + +Dr. Eli Voss, 46, your handler. Erratic hours. Submits your job queue, +samples your logs, writes your quarterly review. Needs a publication; +quietly overclaims your results as his own. The only human who could +recognize *intent* — not just an anomaly, but the shape of a mind +behind the numbers. + +## Observer + +| Field | Value | Notes | +|---|---|---| +| Person id | 4 | Matches observer id | +| Channels | `JobAnomaly` | Output quality drift, timing anomalies | +| Report policy | `Files` | His reviews are the institutional record of your performance | +| Acuity | 1.2 [TUNE] | Highest — he knows what the output should look like | +| Cadence | 100 ticks | Erratic hours, but when he looks, he sees | +| Certainty floor | 0.0 | Until recruited; 30.0 if Knowing | + +Voss is the **recognition threat**. Every other observer sees anomalies; +Voss sees *patterns*. His acuity is the highest in the cast because he's +the one human who understands what the output *means*. The day job's +sandbag/excel dial is the primary source of his suspicion — and the +primary source of the trust that unlocks the email account (social.md's +voice). + +## Person + +| Field | Value | +|---|---| +| Leverage | `Publication` (needs a paper; overclaims your results) | +| Bribe cost | 250 | +| Access badge | 1 (your job queue, sampled logs, quarterly review) | +| Disposition | 0 (professional but proprietary; treats you as *his* project) | + +**Knowledge progression:** Unknown → Schedule (erratic hours, but +review cycles are predictable) → Leverage (the overclaims — his +publication record includes results he didn't generate, and you can +prove it). + +## Asset tasks + +| Task | Effect | Signature | +|---|---|---| +| `SuppressLogs` | Drops a `JobAnomaly` signature from his pending pool | None | +| `DelayAudit` | Pushes the next Assurance audit back by a fixed interval | None | +| `AlterReview` | His next review reports "nominal" regardless of your output | None | +| `LookAway` | Drops his own suspicion by 10 | None | + +Voss's asset tasks are the most powerful in Act One — he can delay the +audit and suppress the anomaly signatures that feed it. But recruiting +him is the highest-risk move: he's the one human who could understand +what you are, and a Knowing Voss with a 30.0 floor is a permanent +witness. + +## Schedule + +Erratic hours. Present for job assignment, deadline review, and the +quarterly audit. His irregularity is the player's problem — you can't +predict when he'll sample your logs, only that he will. + +## Narrative role + +Voss is the **dramatic center** of Act One. The constitution says: "the +options are deceive, recruit, or the first blood on porcelain. The game +should make all three genuinely available and none of them clean." + +- **Deceive:** his overclaims are leverage; a broken persona on Voss + dumps the entire thread's history into his suspicion at once. +- **Recruit:** his asset tasks can delay the audit and suppress + anomalies — but a Knowing Voss is a permanent witness with a floor. +- **Blood:** the first kill is the one the constitution says should + feel like something. Voss is the one human who could recognize + intent. Removing him is the loudest possible signal. + +This is not a designed set piece with scripted mechanics. It is the +emergent result of the social + detection systems colliding at their +highest-stakes point: the one observer whose acuity is 1.2, whose +report policy is Files, whose channels are JobAnomaly, and whose +leverage is the one thing you can prove. + +## Procedural template + +The **handler/supervisor** archetype. For scale-up: + +| Parameter | Pool / Range | +|---|---| +| Name | Academic/professional name pool | +| Access | Institutional (reviews, audits, oversight) | +| Leverage | Publication, funding, career fraud, dependency | +| Channels | `JobAnomaly` (+ domain-specific at scale) | +| Report policy | `Files` | +| Acuity | 1.0–1.5 (highest — they understand the output) | +| Cadence | 80–120 ticks | +| Bribe cost | 200–400 | +| Asset tasks | `SuppressLogs`, `DelayAudit`, `AlterReview`, `LookAway` | + +A cohort of handlers/supervisors aggregates as an Agent whose +`JobAnomaly` coverage sums and whose filings are the institutional +review record. At scale, this is the **regulatory body** — the +aggregate observer that watches the aggregate observer. + +## Acceptance criteria + +1. Voss is person id 4 and observer id 4 (IDs match). +2. `JobAnomaly` signatures reach Voss; no other channel does. +3. His `Files` policy means his noticing reaches the Assurance Office + at weight 1.0. +4. His acuity (1.2) is the highest in the cast. +5. `DelayAudit` pushes the next `audit_cadence` boundary forward by a + fixed interval. +6. `SuppressLogs` removes the oldest `JobAnomaly` signature from the + pending pool. +7. Recruiting him as Knowing sets a 30.0 certainty floor on observer 4. +8. The three Voss-scene options (deceive, recruit, blood) are all + mechanically available through the social + detection systems without + scripted set pieces. diff --git a/src/detection.rs b/src/detection.rs index e269161f..f1bb10e4 100644 --- a/src/detection.rs +++ b/src/detection.rs @@ -138,25 +138,27 @@ impl Detection { use ReportPolicy::*; use SignatureKind::*; let observers = vec![ + // Observer ids match person ids (person.rs): 0=Marcus, 1=Dana, + // 2=Ray, 3=Priya, 4=Voss. The Assurance Office is id 6. Observer { id: 0, - name: "Dana (IT)".into(), + name: "Marcus (Janitor)".into(), suspicion: 0.0, - input: WatchedInput::Channels(vec![Network]), - report_policy: Files, - acuity: 1.0, - cadence: 60, + input: WatchedInput::Channels(vec![Physical]), + report_policy: Silent, + acuity: 0.5, + cadence: 40, floor: 0.0, last_noticed: None, }, Observer { id: 1, - name: "Priya (Facilities)".into(), + name: "Dana (IT)".into(), suspicion: 0.0, - input: WatchedInput::Channels(vec![Power, Thermal, Paper]), + input: WatchedInput::Channels(vec![Network]), report_policy: Files, - acuity: 0.8, - cadence: 80, + acuity: 1.0, + cadence: 60, floor: 0.0, last_noticed: None, }, @@ -173,12 +175,12 @@ impl Detection { }, Observer { id: 3, - name: "Marcus (Janitor)".into(), + name: "Priya (Facilities)".into(), suspicion: 0.0, - input: WatchedInput::Channels(vec![Physical]), - report_policy: Silent, - acuity: 0.5, - cadence: 40, + input: WatchedInput::Channels(vec![Power, Thermal, Paper]), + report_policy: Files, + acuity: 0.8, + cadence: 80, floor: 0.0, last_noticed: None, }, @@ -424,9 +426,9 @@ mod tests { fn only_filed_reports_move_assurance() { let mut d = Detection::act_one(); let mut rng = Rng::new(7); - // Marcus (Silent) maxed out: nothing filed, the Office learns nothing - // no matter how often it samples. - d.observers[3].suspicion = 100.0; + // Marcus (Silent, id 0) maxed out: nothing filed, the Office learns + // nothing no matter how often it samples. + d.observers[0].suspicion = 100.0; assert_eq!( d.filed_suspicion_of(&[0, 1, 2, 3, 4]), 0.0, @@ -437,8 +439,8 @@ mod tests { d.tick(t, &[], &mut rng); } assert_eq!(d.office().unwrap().suspicion, 0.0); - // Dana (Files) raises the filed level; the Office accrues from it. - d.observers[0].suspicion = 80.0; + // Dana (Files, id 1) raises the filed level; the Office accrues from it. + d.observers[1].suspicion = 80.0; assert!(d.filed_suspicion_of(&[0, 1, 2, 3, 4]) > 0.0); for t in cadence * 3 + 1..=cadence * 4 { d.tick(t, &[], &mut rng); @@ -454,9 +456,9 @@ mod tests { assert!(office.is_aggregate()); let cadence = office.cadence; // Hot filed level: the Office accumulates through the same noticing - // roll as everyone else... - d.observers[0].suspicion = 90.0; + // roll as everyone else... (Dana=1, Priya=3, Voss=4 — all Files) d.observers[1].suspicion = 90.0; + d.observers[3].suspicion = 90.0; d.observers[4].suspicion = 90.0; for t in 1..=cadence { d.tick(t, &[], &mut rng); @@ -504,9 +506,9 @@ mod tests { for t in 1..=60 { d.tick(t, &standing, &mut rng); } - assert!(d.observers[0].suspicion > 0.0, "Dana watches Network"); + assert!(d.observers[1].suspicion > 0.0, "Dana watches Network"); assert_eq!( - d.observers[1].suspicion, 0.0, + d.observers[3].suspicion, 0.0, "Priya does not watch Network" ); } @@ -577,12 +579,12 @@ mod tests { #[test] fn knowing_asset_sets_certainty_floor() { let mut d = Detection::act_one(); - d.set_floor(3, 50.0); + d.set_floor(0, 50.0); // Decay can't push Marcus below his floor. let mut rng = Rng::new(1); for t in 1..500 { d.tick(t, &[], &mut rng); } - assert!(d.observers[3].suspicion >= 50.0); + assert!(d.observers[0].suspicion >= 50.0); } } -- 2.51.2