Forum teuk.org

MB710 — Spark Learns to Read the Great Hall Before Casting 🪄⚡

in Mediabot · started by TeuK · 2d ago

TeuK · 2d ago

Mediabot’s Spark system could already revive a quiet room, react to a concrete conversation hook, open a collaborative event, or add a short ambient action. What it could not yet do was answer the most important question before acting: how large and balanced is the audience that is actually present?

MB710 gives Spark that missing sense of proportion. A nearly empty room now receives patience and restraint. A small exchange gets a lighter, carefully bounded invitation. A lively, balanced conversation can unlock richer events and shorter breathing pauses without relaxing the evidence or safety gates.

The result is not a louder bot. It is a bot that listens to the room before it raises its wand. 🏰

🧭 A privacy-safe audience model

The new audience layer measures participation over a bounded metadata window. It exposes only operational facts:

  • distinct human participation;
  • a recency-weighted effective audience;
  • dominant-speaker share;
  • human line rate;
  • recent bot pressure;
  • quiet and activity durations.

Message text and nicknames do not cross the policy boundary. The generation context remains deliberately small, while the larger activity window contains only what the pacing policy needs. This separation prevents provider prompts from growing merely because the bot needs a better view of channel activity.

The effective audience is intentionally stricter than a raw nickname count. If one voice owns at least 75% of the recency-weighted conversation, the room is demoted by one regime. A prolific speaker plus several occasional lines can no longer masquerade as a balanced group.

🪞 Knowing humans from automation

MB710 also adds a shared conversational identity boundary. The bot’s live nick, the existing main.BOT_NICKS list, command traffic, and direct bot triggers are classified as automation rather than human participation.

Automation is not ignored completely: it becomes bot pressure. Recent bot traffic postpones unsolicited Spark activity instead of inflating the apparent audience. The same classification is shared with Wit so both systems reason from a consistent view of the channel.

No new identity database or configuration family was introduced. The existing generic bot-nickname setting remains the operator-controlled source of truth.

🏰 Five audience regimes

One pure adaptive policy now maps the measured room into five ordered regimes:

Regime Typical room Revival pacing Momentum budget Behaviour
empty no human evidence 200% 200% no candidate
solo one effective voice 200% 200% rare contextual Reaction or Callback only
small two balanced voices 150% 150% patient, two-voice Mosaic, no Portal
social balanced conversation 100% 100% reviewed baseline
crowded large balanced audience 60% 67% shorter pauses and richer collaboration

Configured operator values remain the reviewed baselines. The adaptive policy scales them centrally and deterministically; it does not replace them with opaque model judgement.

A solo participant can receive only a rare contextual Reaction or Callback, and only after twice the normal silence with enough clean context. Fork, Portal, source-backed stories, and momentum actions remain unavailable. Small rooms are deliberately patient. Crowded rooms may recognize shorter pauses, but they must still prove stronger activity before becoming eligible.

⚖️ One budget for both Spark lanes

The long-silence revival lane and the short-pause momentum lane previously had separate cooldown paths. MB710 closes that asymmetry.

A delivered momentum action now installs the same channel pacing deadline seen by the revival lane. Existing Spark event cooldowns already block momentum in the opposite direction. Both directions therefore consume one shared budget: two independently scheduled initiatives can no longer appear back-to-back.

All mutable gates remain authoritative immediately before transport:

  • both channel capabilities;
  • both process arms when the action lane is used;
  • live IRC connection and channel membership;
  • flood suppression;
  • active game and Wit state;
  • current Spark generation and event state;
  • public speech that revokes in-flight generation.

The audience model changes proportion, not permission. 🛡️

🧩 Flash Mosaic: a collective spell with sharp boundaries

MB710 introduces Flash Mosaic, a short collective Spark event whose visible target scales with the audience:

  • two voices in a small room;
  • three in a social room;
  • four in a crowded room.

The opening is local and deterministic. It clearly advertises the only accepted syntax: +word, one word per person. Each distinct participant may contribute one Unicode word of at most 24 characters; internal apostrophes and hyphens are allowed.

Ordinary conversation, multiple words, commands, bot traffic, duplicate contributors, and late replies never enter the collector. The event closes as soon as the target is reached, or after 75 seconds when at least two valid voices participated. Zero or one contribution remains an honest miss.

The closing provider request receives only the bounded words. Contributor identities never enter the prompt. The payoff cannot rank or score anyone, ask for more input, or start another round. Its continuation is single-use, time-bounded, and guarded by the same delivery checks as every other Spark event. All collected words are destroyed after success, timeout, miss, or technical failure. ✨

🔮 Replay-calibrated momentum

The final momentum gate was checked against two anonymized channel histories: one low-activity and highly dominated, the other larger and more balanced.

That calibration exposed a subtle failure mode: two raw nicknames are not necessarily a two-person conversation. MB710 therefore makes effective audience authoritative at the orchestrator boundary. A dominant raw pair that still behaves like a solo room cannot summon an ambient momentum action. A balanced exchange remains eligible under the proportionate small-room policy.

Only aggregate envelopes entered the repository. Historical messages and participant identities were never copied into source, tests, or documentation.

📜 Operational diagnostics without conversational leakage

Candidate, generation, delivery, event, Mosaic, and Portal logs remain metadata-only. They can report the audience regime, applied pacing, target size, lifecycle counts, delivery outcome, and failure reason. They never record the generated reply, collected words, recent conversation, or participant identity.

This gives operators enough evidence to answer useful questions — why did the bot wait, why was this family selected, which budget was installed? — without turning the application log into a transcript.

🧪 Validation ledger

The implementation progressed through isolated observation, adaptive policy, Flash Mosaic, replay calibration, and a controlled development runtime pilot.

Final validation results:

  • targeted Spark, Wit, and Reanimator regression: 939/939;
  • fast development lane: 6711/6711;
  • final full suite: 17882/17882 across 898/898 files in 127 seconds;
  • full suite invoked exactly once at the final precommit gate;
  • source identity unchanged after the suite;
  • development startup, database, and IRC readiness verified with zero Spark runtime errors.

The final commit contains 31 paths with 2,903 insertions and 131 deletions:

407cd315aff4
3.4dev-20260829_121751

Its parent is exactly the revision that passed the full suite, the worktree is clean, and the pushed upstream revision matches the local commit. 🦉

🚪 Deployment status

MB710 is committed and pushed, but this article does not pretend that production has already changed. The production pilot remains a separate, guarded operation:

  1. establish read-only truth for the checkout, service, process, configuration, database capabilities, and application log;
  2. preserve the live configuration before any mutation;
  3. deploy only commit 407cd315aff4;
  4. change only missing pilot settings or capability bindings;
  5. restart once under the verified service identity;
  6. prove startup, database, IRC, and Spark readiness from the application log;
  7. observe metadata and behaviour under the real audience before widening the rollout.

No production service, configuration, database row, or channel capability was changed by the development commit.

🌙 The practical outcome

Spark now treats channel activity as a social environment rather than a binary trigger. Silence is not automatically an invitation. Nick count is not automatically an audience. A busy room is not permission to flood. Every initiative must fit the size, balance, cadence, and recent automation pressure of the conversation it is about to join.

The castle has gained no louder trumpet. It has gained a more observant portrait — one that waits, watches, and chooses the right moment to speak. 🖼️🪄

You must be logged in to reply.