Forum teuk.org

🪄 Accio Clear Sources, Reparo the Runtime! Mediabot’s Latest Maintenance Spells

in Mediabot · started by TeuK · 4d ago

TeuK · 4d ago

MB835–MB837 · Readable citations, safer conversation lifetimes, cleaner scheduling and a more dependable logbook.

The previous chapter cast Protego around Mediabot’s configuration saves. This time, the maintenance quill has travelled from the visible IRC replies to the machinery keeping the bot alive: conversation memory, periodic tasks, process ownership, command registration and logging.

One improvement is immediately visible: researched answers now tell you which website sits behind each short link. The others strengthen the rules governing what may still run, write or clean up after its original owner has gone away.

All three rounds have passed their complete validation suites on teuk.org. The database schema remains unchanged: no migrations, new tables or new columns. 🛡️

📚 MB835 — Put a name on every borrowed spell

A line of shortened URLs saves space on IRC, but it hides the identity of the sources until someone opens them. MB835 adds the website’s name directly before its link.

The layout now follows this pattern, with link identifiers omitted here:

Sources: FranceInfo [short link] | Reuters [short link]

The presentation has two distinct styles:

  • Website labels: dark grey, using IRC colour 14.
  • Verified private-service short links: light blue and underlined, using IRC colour 12.

Formatting resets separate each label, link and separator. The colour of one source cannot spill into the next part of the line.

The label comes from the original source URL’s hostname, before shortening. Familiar domains receive readable names such as FranceInfo, ANSSI, CERT-FR, Le Monde or Home Assistant. Other websites keep a bounded hostname. Domain matching respects actual domain boundaries; an unrelated address containing a familiar brand name does not inherit that brand’s label.

Article titles and model-generated labels do not decide the site identity, and creating these labels adds no HTTP or AI request.

English and French source prefixes remain supported. The existing delivery envelope is retained: up to two answer lines, followed by one compact source line containing at most two sources. Source validation, URL binding, original-link fallback and paced IRC delivery continue to apply.

Accio sources — with their bookplates attached. 📖✨

🧠 MB836 — Give each Pensieve room its own lifetime

Conversation memory needs to know whether a delayed answer still belongs to the room that requested it.

The review reproduced a subtle sequence in the memory store: a room expires, the same scope is created again, and an old request completes afterwards. Both rooms could begin with the same epoch number. That made the old ticket appear current again, allowing expired context to enter the recreated room.

MB836 gives each new room a fresh 128-bit incarnation identifier, checked alongside its epoch. A matching room name and epoch are no longer sufficient. Completion must belong to the same room lifetime.

Existing version-1 memory files remain usable. Rooms acquire the additional identifier on their next successful turn while retaining their history, speaker information and daily usage. Personal erasure still invalidates pending tickets, and a legitimate nickname change preserves the current room’s identity.

There is no manual memory reset or file migration to perform.

This defect was demonstrated through controlled memory-store calls. The IRC runtime’s existing one-job-per-channel guard remains in place; the reproduction is not evidence that ordinary live conversations were leaking.

Even a Pensieve should refuse an echo from a room that no longer exists. 🌀

⏳ MB836 — Retire a task, retire its callback

Periodic scheduling received its own inspection of the Time-Turner.

Previously, a timer callback held strong references to its task and scheduler. Removing the task could leave that object graph retained. An explicitly retained tick callback could also execute after the task had been stopped or removed, updating counters along the way.

The callback now uses weak references and checks that its task is still the current registered task and is started before recording a tick or executing work.

That also protects replacement tasks: an old timer cannot wake up and act on a new task registered under the same name.

The tests exercise real IO::Async timers and object reclamation, and deliberately invoke retained callbacks to check stale-event handling. Normal cadence, calendar scheduling, timing metrics and explicit stop/start controls keep their existing behaviour.

🔑 MB836 — Leave the new keeper’s PID file alone

A PID file belongs to a particular running owner. Its pathname alone cannot prove that ownership forever.

The reproduced failure involved an old owner retaining its open descriptor while the PID path was replaced. During cleanup, it could read its own old descriptor and then unlink the replacement path, removing the new owner’s public PID entry.

MB836 checks the acquired filesystem entry and the file identified by the held descriptor. An observed replacement is preserved; the old owner closes its own handle and reports the conflict. Acquisition also checks the path binding, and permission changes use the owned descriptor.

Stable symbolic PID aliases remain supported, including their established cleanup behaviour. Replacement files and retargeted aliases are protected by the new checks. Operators should still stop the exact instance before manipulating its live runtime files; these checks do not turn filesystem cleanup into an atomic compare-and-unlink operation.

The departing keeper hands back their own key. They leave the replacement keeper’s door intact. 🏰

🗝️ MB837 — One command name, one owner

The next pass found a gap in the command registry’s shared namespace.

Consider a command named forecast with the alias weather. Registering another canonical command called weather previously succeeded. However, dispatch resolved aliases first, so invoking weather still reached forecast. The new command appeared in the catalogue but its canonical handler was unreachable.

MB837 rejects that collision before changing command entries or alias ownership. Supplying replace cannot take another command’s alias.

Normal replacement still works. An owner may release an alias by replacing or removing its own command, after which that name can be registered independently. Public and private command sources remain separate. A refused registration preserves existing handlers, aliases and help metadata.

The PluginManager’s existing collision and authorization checks remain in place. This correction closes the lower-level registry API gap.

No two spells should occupy the same slot in the catalogue. 🪄

🕯️ MB837 — Keep the logbook open while fetching its replacement

Reopening a log should preserve a usable destination if the replacement cannot be opened.

The old sequence closed the active descriptor first. If opening the new destination then failed, subsequent file logging tried to write through a closed handle.

The logger now opens and configures the candidate before switching handles. A failed reopen still reports its error, while the previous descriptor remains available. A later successful reopen switches to the recovered destination and closes the old descriptor.

During that failure period, continued writes go to the previous open file, which an external rotator may already have renamed. The logger does not report the unavailable destination as healthy.

UTF-8 output and autoflush are retained. Regression coverage also checks ordinary size rotation, the record written at the rotation boundary, standard output and single delivery to Partyline console hooks.

The candle stays lit while the replacement lantern is being prepared. 🕯️📜

đź§Ş The O.W.L. results are in

The complete suites passed on teuk.org at each checkpoint:

Round Targeted checks Fast lane Complete suite
MB835 — source labels 1,440 / 1,440 8,289 / 8,289 23,908 / 23,908
MB836 — runtime ownership 1,660 / 1,660 8,290 / 8,290 23,993 / 23,993
MB837 — registry and logging 582 / 582 8,291 / 8,291 24,047 / 24,047

The latest full run covered 1,101 test files. All 37 source security invariants passed at each round. The fast lane remains a development check; the complete suite provides the full validation result.

Six new regression files cover these changes. The runtime and registry/logging regressions were also run against the previous implementations to demonstrate the failures they correct. These are reproduced defects, rather than inferred production incidents.

The source packages retain the established safeguards: isolated preview, private backup, mandatory validation and rollback after a failed required check. Tests also check preservation of the real Git index and private configuration, with concurrent source edits retained for inspection.

đźš‚ The next departure

MB837 has now been committed and pushed as version 3.6dev-20261018_090821. Production instance updates and normal IRC acceptance follow the established rollout, with #i/o on Epiknet through nbot as the usual acceptance channel.

These rounds bring clearer references to the conversation and tighter ownership rules to the runtime underneath it. Mediabot can keep building on a foundation where expired rooms reject stale answers, retired tasks stay retired, replacement PID files retain their keeper, command names have one owner and a failed log reopen leaves a usable logbook behind.

Accio clarity. Reparo the runtime. Protego the next adventure. 🦉✨

You must be logged in to reply.