Development chronicle β mb609 to mb613 Β· Multilingual AI recap, persistent achievement progress, tunable rarity and truthful async state
This development arc improves two parts of Mediabot that look unrelated at first: AI recaps and achievements.
They actually share the same design goal: what the user sees should accurately reflect the state Mediabot is really using.
AI recap now follows the same language rules as ai summary. Achievement progress now survives restarts, uses configurable thresholds, shows the next goals directly on IRC, and correctly returns progress calculated inside async workers back to the parent process.
No database schema change was required.
recap ai now follows the same language policy introduced for ai summary.
Examples:
recap 2h ai
recap 2h ai fr
recap ai lang=en
The important part is not merely that both commands support English, French and Spanish.
They now use the same implementation.
The shared Claude API exposes helpers for:
language token extraction
channel/default language resolution
model language names
localized service messages
Conceptually:
explicit lang=en|fr|es
β
βΌ
channel language
β
βΌ
main language / English fallback
ai summary and recap ai therefore cannot quietly develop two different interpretations of the same channel.
The recap prompt also stopped asking the model to guess βthe same language as the conversationβ. On a bilingual IRC channel that was inherently ambiguous. Mediabot now tells the model exactly which language to use.
Unlocks were already persistent.
The counters leading to them were not.
Several values lived only in memory:
horoscope consultations
compat checks
mood reads
duel wins
More seriously, trivia and quotegame progression used the score of the current game session.
That made goals such as a large number of correct trivia answers effectively reset between games.
mb610 adds a persistent progress ledger alongside the existing achievement data:
{
"version": "2",
"profiles": {},
"progress": {
"trivia_correct": {},
"duel_wins": {},
"msg_count": {}
}
}
Progress is scoped by normalized nickname and channel:
Teuk on #Chan
teuk on #chan
β
same progress identity
Legacy flat achievement files remain readable and are upgraded transparently on the next save.
The registry is bounded as well: oversized progress maps prune the weakest entries while protecting the counter that has just been updated.
Achievement thresholds used to be scattered inside checking code.
They now live in the achievement catalogue itself.
That gives Mediabot one source of truth for:
definition
display
validation
unlock condition
Thresholds can also be overridden in configuration:
[achievements]
TRIVIA_CHAMPION=200
LEGEND=120000
Invalid, missing, zero or negative overrides fall back to the catalogue default.
The harder tiers were rebalanced, for example:
| Achievement | Old | New default |
|---|---|---|
| Trivia Champion | 100 | 300 |
| Quote Master | 50 | 150 |
| Duel Master | 50 | 150 |
| Karma Legend | 100 | 250 |
| Polyglot | 5,000 | 7,500 |
| Polyphony | 5 channels | 8 |
| Legend | 100,000 | 150,000 |
Entry-level achievements remain welcoming.
And an achievement already unlocked is never revoked merely because its threshold becomes harder later.
Persistent counters are much more useful when users can see them.
The normal achievement view now includes the nearest goals:
π teuk β 2 / 24 achievements:
π¬ Chatterbox | π First Steps
Next: π Wordsmith 980/1k (98%)
| βοΈ Duel Warrior 9/10 (90%)
| π Karma Star 41/50 (82%)
A new detailed view exposes the ladder:
!achievements progress
Example:
π teuk on #quebec β 2/24 unlocked, 18 in progress:
[===========.] π Wordsmith 980/1k (98%)
[==========..] βοΈ Duel Warrior 9/10 (90%)
[=========...] π Karma Star 41/50 (82%)
[=====.......] π Trivia Champion 137/300 (45%)
[=====.......] π’ Megaphone 4.2k/10k (42%)
Goals which are already numerically complete but have not yet been registered as unlocked are not presented as βnext objectivesβ.
Achievements for which Mediabot has no honest measurable progress β such as some timing or streak conditions β stay explicitly non-measurable instead of receiving invented percentages.
The partyline .status view also exposes achievement registry state:
Achv: N profile(s), M progress counter(s)
and reports unsaved changes when applicable.
The final audit found an important runtime distinction.
Heavy achievement checks run inside a forked worker.
A direct call like:
set_progress(...)
inside the child only modifies the child processβs copy-on-write memory.
Without an explicit return path:
PARENT
β
βββ fork βββΊ CHILD
β
βββ calculates msg_count
βββ set_progress(...)
β
βββ exits
progress disappears
The corrected path is:
PARENT
β
βββ fork βββΊ CHILD
β
βββ calculates msg_count
βββ calculates channels_active
β
βββ returns bounded result
β
βΌ
PARENT
β
βββ set_progress(msg_count)
βββ set_progress(channels_active)
βββ normal persistence
This makes mb612βs promise true in the actual asynchronous runtime, not just in direct unit calls.
The worker deliberately receives a minimal bot object with an isolated database handle.
That isolation is good, but it also meant configuration-backed achievement thresholds were unavailable there.
mb613 snapshots the effective thresholds before the fork.
So:
[achievements]
LEGEND=200000
POLYPHONY=12
is respected both by the parent and by the async worker.
The result is one consistent achievement contract regardless of which process performs the expensive calculation.
The final pass also closes several smaller truthfulness gaps:
channels_active;790_mb608_ai_summary_language.t is actually removed;No extra database query was introduced merely to draw progress bars: values already calculated by the existing checks are reused.
This round deliberately did not repeat the entire twelve-thousand-assertion suite after the final audit fix.
The Claude development passes had already exercised the broader suite, including:
mb609 β 12145/12145
mb610 + mb611 β 12190/12190
mb612 β 12222/12222
The final review concentrated on the affected language, persistence, threshold, presentation and async-worker tests, including the new mb613 guard.
This keeps the final pre-commit loop focused while still testing the exact boundaries changed by the audit.
For AI features:
one channel
one resolved language
one implementation
For achievements:
activity
β
persistent progress
β
configurable target
β
visible next goal
β
unlock
And that progression now remains true across:
game sessions
bot restarts
forked workers
configuration overrides
The castle no longer keeps only a cabinet of trophies.
It keeps the road that leads to them.
The scoreboard survives when the candles go out, the rare cups demand a worthy journey, and the notice board shows exactly how far remains.
Even when a distant clerk counts the records in another room, the result now comes back to the Great Hall before it is written into the ledger.
And the portraits that summarize the evening finally speak with one shared voice.
You must be logged in to reply.