45 KiB
| title | subtitle | date | author |
|---|---|---|---|
| Château du Faune — Tracker / Journal pilot review | Findings from the first week of !journal, !goals, !tasks usage across four Signal rooms | 2026-06-02 | aiolabs / Château du Faune |
Executive summary
For the past two weeks, members of the Château du Faune have been
"going through the motions" of using !journal, !tasks, !goals,
!reminder, !buy, !sidequest, and related commands across four
Signal rooms — Operations, Animals, Gardens & Food, Events, and the
general castle room. Nothing was hooked up yet: the chats are mirrors
of what the maubot stack on the new Matrix homeserver will eventually
capture. The point was to generate signal — to find out which
verbs people actually reach for, how they phrase entries, where the
syntax gets in the way, and which features the protocol spec is
quietly missing.
This document reads that signal. It is written for both the chateau
members (who will see their words quoted back and choices made about
how the bot will treat their phrasing) and for the
aiolabs/maubot-plugins developers (who will turn the
recommendations into code and spec changes). The
community-organizer spec is the contract; the
tracker/ and journal/ plugins are the
reference implementation; the data we collected over the past two
weeks is the field test.
Top-line findings:
-
The capture habit is sticking. The bot doesn't exist yet, and people are still using the syntax — sometimes correcting each other on it. The most surprising data point is that Coco told Helena "
!journalis the required format" unprompted. Social enforcement of a syntax we haven't actually shipped is the best possible adoption signal. -
The vocabulary the community reaches for is broader than the spec. The current spec lists
!task,!sidequest,!journal,!remind,!add,!done,!list,!setup. The chats show people typing!buy,!need,!goals,!stewards,!tasks,!task(singular),!reminders(plural),!idea,!plans,!priority(inline),!side quests, and a few more. Some of these are per-room shortcuts the spec already accommodates; others want a small protocol-level addition. -
The 5-level priority scheme came directly from this pilot. Coco proposed "1 urgent / 2 crucial / 3 important / 4 future / 5 frequent/ongoing" in the operations chat on May 24. It is now §3.3.1 of the spec, exactly as proposed. This loop — observe → spec → implement → re-observe — is the one we want to keep running.
-
The bot will need to be more grammar-tolerant than the spec currently implies. Multiple verbs per message, edited messages that add content,
!-words inside bullet points used as priority markers, pinning as a "this is the current list" signal, no-prefix journals — these are all behaviors the bot doesn't catch today but should. -
The community is already designing the bot's voice. Alfred got named on May 24 ("we trusted him with resource management, safety, tool use, etc."). Photos got captioned, journals got pinned, Cocopis explained what
!tagsare to other members. The chateau is treating the bot as a collaborator before it exists. We should lean into that — bot personality is now a design surface.
The rest of this report:
- §1 What we observed, by room and by pattern
- §2 What the existing spec + plugins handle well
- §3 Spec changes proposed
- §4 Plugin changes proposed
- §5 New ideas the data surfaced
- §6 How this fits the larger omnixy / aiolabs ecosystem
- §7 A phased plan
- §8 Open questions for the chateau
1 — What we observed
1.1 Verbs in actual use
A frequency-sorted list of every !verb we saw across the four rooms
(case-folded), grouped by what the spec or current shortcut config
covers:
| Verb seen | Already in spec | Status |
|---|---|---|
!journal |
Yes (universal) | Heavy use across all four rooms |
!reminder / !reminders |
Spec verb is !remind |
Mismatch — see §3.1 |
!tasks / !task |
Spec verb is !task |
!tasks plural also appears |
!goals |
No | New — see §3.2 |
!stewards |
No (per-room shortcut candidate) | Used as a list/backlog, not a one-off task |
!buy |
Per-room shortcut, fits cleanly | Should ship pre-configured for cdf rooms |
!need |
No | Distinct from !buy in usage — see §3.2 |
!sidequest / !side quests |
Yes | Used; "side quests" with space appeared once |
!idea / !plans |
No | Speculative / design-phase items |
!priority (inline) |
No (priority is a tag) | Used as a bullet-level marker — see §1.4 |
!move |
Mentioned by Ulo as a future verb | Not in spec |
And a usage example per verb so the design instinct is grounded in actual phrasing rather than imagined phrasing:
!journal — past-tense daily log, multi-line is the dominant
form:
!journal- opened/closed, watered and fed hens, babies & pacas- put insulators on the rebars so they're ready to go for fence- mentally plotted potential hidden-in-plain-sight stable locations. I want opinions next- should scrape clean duck babes straw tmrw- should clean and dry very well sapphis wound again
Note the mix of past-tense ("opened/closed") and forward-looking
("should scrape clean tmrw") bullets in the same !journal. People
do not bucket their day cleanly. §3.4 addresses this.
!goals — a list of current intentions, often nested with
sub-categories:
!goals & notes next week for garden/kitchen crew
GARDEN- documentation & journaling process- prepping & starting the Lady Godiva pumpkin patch.…
KITCHEN- forage, harvest & food processing resource improvements (ex. cherries into vinegars…)- filling the shop up (& soon looking into certifying our kitchen/lab)…
!goals lists evolve over days — Coco's gardens !goals on May 27
and June 2 are the same list, refined. This is the strongest
argument we found for replaceable-event semantics (§3.3).
!reminder — a future-pointed list, often with embedded
@-mentions and !priority markers inside bullets:
!goals this week/soon- attempt to secure alpaca deposit & arrival of the boys- !priority confirm if teeth & nails will also be done by the shearer 'sometime in july'- !priority diagnosis of sapphis skin condition be made by a vet in person.!reminder following shearing, immediately start sapphis skin infection protocol- fencing add in doors & handles. Start soon on setting up 2nd stable paddock
Look at that message carefully: it is one !goals entry, with
!priority and !reminder appearing inside bullets as inline
markers, not as new commands. This is the single most important
parser decision we have to make — see §4.1.
!buy — shopping list, sometimes added-to over days via edit:
!buy- roll out flypaper for stable(s)- door handles for electric (or from laura)- la fourche order, sesame & produce will be thursday, 28th- buy more pans & x2 induction adapters
!need — semantically distinct from !buy. Means "stock is
low" rather than "purchase this":
!need puppy & cat food, hay & straw soon
Coco used both in the same week. The distinction matters because
!need items become !buy items only after someone agrees to act
on them, where !buy is already a decision.
1.2 Cadence patterns — the recurring chore problem
The operations chat opened with a chores list dominated by recurring items with fuzzy intervals:
pacas:- every ~3 days scoop manure- every ~3 days fluff bedding- every 2 wks to 1 month - change out whole bedding- daily fresh water- daily light green/yellow hay- training - max 1x/day - approach with treats in a bucket…
hens & ducks:- am let out, pm close in- every ~3 days fresh water & food- every 1 week change out straw- spend time with the puppies every day
Coco flagged the problem herself: "weird thing is tasks that are every few days or variable timeframes?"
The spec partially anticipates this with priority:5 ("frequent /
ongoing"), but priority:5 is a marker, not a cadence. "Every 3
days" and "daily" are different cadences and the bot should know.
RFC 5545 RRULE is the canonical answer; NIP-52 doesn't yet
codify recurrence (§11 of the spec lists this as open). A
lightweight stopgap is proposed in §3.5.
1.3 Multi-verb messages
Helena posted in the Gardens & Food room:
!journal• bigger Team meet and on board of Marta what we did the last weeks…• weeding• getting fresh alpaca manure and distributing• collecting seeds for next year planting
!task- research thing for rain tank- update online garden map- check on sprouting pumpkin seeds and plant when ready
This is one Matrix message but two distinct entries — a
!journal and a !task list. The current tracker dispatch regex
matches the first verb at start-of-message and stops. The plugin
will silently drop Helena's !task block.
This is a real bug, not a theoretical one — Helena was the first person who naturally typed in this shape, and the bot would have lost the task list. §4.2 fixes it.
Skye independently did the same thing on the same day:
!goals !tasks- [ ] organise conversation about image ai making with pat and coco- [ ] Look into creation of the funding via our socials…- [ ] For flyers/posters the !goals is to make one for pats new events app for ariege…
!goals !tasks on one line is yet another shape: two verbs sharing
one body. Likely "this entry belongs to both lists" — but the spec
needs to say so explicitly.
1.4 Inline !priority and !reminder markers
Returning to Coco's May 27 !goals:
- !priority confirm if teeth & nails will also be done by the shearer 'sometime in july'- !priority diagnosis of sapphis skin condition be made by a vet in person.!reminder following shearing, immediately start sapphis skin infection protocol
!priority and !reminder are appearing inside body content as
bullet-level annotations, not as commands. A naïve parser that
matches !\w+ anywhere in a message would interpret these as new
commands and produce four entries from one message.
The fix is the rule the journal plugin already enforces: a !verb
counts as a verb only if it is at the very start of the message
(or, with §4.2 in place, at the very start of a top-level block).
Everything else is body content with inline tags.
But "inline tags" is itself a feature worth keeping: a bullet
starting with !priority is a natural way to mark that bullet
as urgent within a larger list. The bot can:
- Treat the inline
!priorityas a tag on the bullet body (preserves the user's intent). - Leave the parent entry's priority alone (the user didn't priority the list; they priority'd one item in it).
A renderer can then surface that bullet as priority-1 within the parent entry. This is a richer model than the spec currently sketches, but it matches what users are actually doing. §3.3 proposes the wire format.
1.5 Pinning as state
Across all four rooms, the dominant !goals / !tasks / !stewards
messages are pinned to the room. When the list evolves, the new
version is pinned and the old one is unpinned. Matrix has native
support for this (m.room.pinned_events).
We propose treating "the latest pinned message matching !goals
from a given room" as the current state of that group's working
list. This gives every room a queryable "what's on our plate
right now" view without requiring users to remember an item id.
§3.3 + §4.5 develop this.
1.6 Implicit subjects — animals, people, places
The animals room is full of entries like:
- thinking of long-term solutions for pups barking and neighbors.- 45 min in the alpaca paddock with both pups, no electricity.- carefully choose feeding station(s) so they are isolated and don't compete with any other animals(and elsewhere)
lets clean sapphis wound again soon?also just realized the shearer will come in july
The community has named entities — Sapphi, Loki, Leia, Tango, Morrigan, the alpacas, the pups, the hens, the south paddock, the orchard, the coop — that recur across many entries. A useful query is "show me everything mentioning Sapphi this month" or "what tasks involve the south paddock?".
NIP-52 already supports ["p", "<pubkey>"] for people. Animals
and places need a convention — see §3.6.
1.7 Inline @-mentions = informal assignment
- location & plans for stable, cont. @coco- closing the main property gate? guardian dogs sign @coco- pruning & landscaping @Thomasss**]- following a budget per person for food orders, picking up produce @Skye 🌟
People mention each other inline to mean "this bullet is yours". The
bot can extract these into structured ["p", …] tags and a
renderer can surface a per-person "your bullets" view. §4.6.
1.8 Cross-group routing ambiguity
Skye said in the Events room:
"organise a mini meeting to talk about ai image making etc with pat/coco …. I'm not sure which chat to put these social things in hehe"
Some items belong to multiple groups. The current 1-room ↔ 1-community mapping makes this expensive — you'd have to type the same entry twice. Coco's answer ("i think events would be the fitting place") is the human workaround; the bot should help. §5.2 proposes optional multi-room fan-out.
1.9 No-prefix journal-shaped content
Lots of messages look like journals without using any command:
today plan for me:- working in other groups on animals and operations
Today's plan for me:- making bulk buckwheat zucchini burgers some for today and rest in freezer
journalstarted but did not complete: bathroom clean, mapping stables, fencing the internal 150m paddock
The chateau is explicitly standardizing on !journal (Coco
corrected Helena on this in real time). So we should not make
the bot fuzzy-match — they want explicit syntax. But the data
suggests an opt-in "capture every non-command message in this
specific room" mode could be valuable for very-low-friction rooms
(e.g. a private journal room per member). Default: off. §5.1.
1.10 Capitalization, punctuation, language
The same intent appears as !journal, Journal:, journal, !journal:,
Today plan for me, today plan:, sometimes mixed with French.
The bot's regex needs to be:
- case-insensitive on the verb (
!Journal==!journal) - tolerant of a trailing colon (
!journal:is fine) - bilingual on body content (already true — body is opaque text)
The current _CMD_RE = re.compile(r"^!(\w+)(?:[ \t\r\n]+(.*))?$", re.DOTALL)
in tracker.py:52 does match !Journal because \w is
case-insensitive in unicode mode, and the dispatch already calls
.lower(). But it does not match !journal: because the colon
follows the verb with no whitespace. One-line fix in §4.3.
1.11 Edits matter
Two distinct edit patterns appeared:
A. Edit-to-append. Coco edited a !journal post-hoc and
commented: "just added that i also fed puppies 2x today". The
intent is "this is the same entry, with more content".
B. Edit-to-correct. Coco scheduled a vet appointment for "June 5 @ 14h", then edited the same entry to "May 30 @ 15h" with the note "updated to May 30 @ 15h because they need the vaccination within the month".
The tracker's current known-quirks note (tracker/README.md:133)
says:
"Edited messages don't re-trigger the bot. Matrix sends edits as a separate
m.replaceevent that maubot doesn't pass to handlers. Type a fresh message instead of editing."
This is solvable — m.replace events are visible to maubot; the
handler just needs to be wired. §4.4.
2 — What the existing spec and plugins handle well
Before proposing changes, let's mark what's already right. The pilot validates a lot of the design.
2.1 The split between universal verbs and per-room shortcuts
The spec says: every implementation must recognize the universal
verbs (!task, !journal, etc.); per-room shortcuts (!buy,
!harvest, …) expand to them. The data agrees: every room developed
its own dialect (animals uses !journal heavily, operations uses
!buy and !stewards, events uses !goals). A single plugin
serves all of them.
We just need to pre-configure the cdf rooms with sensible
shortcuts so members don't have to !setup add buy task #buy on day
one. §4.7.
2.2 The passive regex / multi-line story
The journal plugin's switch to @command.passive with a regex was
right. Every multi-line entry we observed (and many one-line ones)
would have been silently dropped under @command.new. The CLAUDE.md
footgun is real and the plugin avoided it.
2.3 The 5-level priority scheme
priority:1..5 with the labels urgent / crucial / important / future
/ frequent-ongoing came out of the pilot. The renderer plan is to
surface labels rather than numbers; the wire tag stays priority:N
for sort stability. The data didn't push back on this — Coco's
proposal landed exactly as written.
2.4 Sidequests as a separate kind
!sidequest (with a 🎯 emoji ack) gives a distinct surface for
"would be cool to do" items. Coco's "!side quests lists which are
different from the rest of the tasks" is exactly the use case. The
spec already excludes sidequests from default !list output, which
is the right default.
2.5 The Matrix-only Phase 1 posture
The tracker is matrix-only for v1 — no Nostr publishing yet. This
turns out to be the right call: the four-week dataset shows the
community is still finding its vocabulary. Publishing to a public
relay before the vocabulary stabilizes would make schema migrations
visible to anyone subscribed. Stay matrix-only until the verb set is
stable, then bridge.
2.6 The journal plugin's append-only stance
The spec's "!done on a journal entry is undefined behavior;
implementations SHOULD reject it" matches the data: nobody tried to
close a journal. They edit, they re-journal, they pin — they don't
close. Good call.
3 — Spec changes proposed
These are protocol-level additions to docs/community-organizer-spec.md.
Each is small. None breaks existing conformance — they extend, they
don't refactor.
3.1 Plural aliases for universal verbs
!reminders and !tasks should be accepted as equivalents of
!remind and !task. !sidequests likewise. This is a one-line
parser change; it costs nothing and removes a footgun (users will
naturally pluralize when a list is multi-item).
Spec change: in §3.1, add a row: "Implementations MUST accept the bare plural form of each verb (
!tasks,!sidequests,!reminders) as equivalent."
3.2 New universal verbs: !goals and !need
Both verbs got real, repeated, distinct-from-existing usage. Both deserve protocol-level status, not per-room shortcut status, because:
- They had identical meaning across all four rooms. A bakery co-op reading this spec should be able to use them without re-configuring.
- The shortcut mechanism is for vocabulary the community invented
(e.g.
!harvest,!brewery).!goalsand!needare not vocabulary inventions — they're a category the spec missed.
| New verb | Purpose | Underlying kind |
|---|---|---|
!goals <text> |
A list of current intentions for the author/group/period. Replaceable per (author, room, period?). |
31922 with ["t", "goals"] |
!need <text> |
A supply that is running low. Distinct from !buy (which is "I will purchase this"). Default lifecycle: open → !buy (converts to task) or !done. |
31922 with ["t", "need"] |
!goals deserves §3.3 (replaceable semantics) since the goals lists
visibly evolved over days in the pilot.
3.3 Replaceable-event semantics for !goals (and stewards lists)
NIP-52 kind 31922 is a parameterized replaceable event keyed by
d-tag. Today the tracker assigns a unique d per entry. For
!goals (and the per-room !stewards list pattern), we want the
opposite: the latest !goals from a given (author, room) pair
should replace the previous one.
Spec change: in §3.3, add: "Implementations MAY designate certain verbs as replaceable per
(author, room, period?). When a verb is replaceable, the bot reuses the samed-tag for successive captures, so the relay retains only the latest version. Recommended replaceable verbs:goals,stewards."
The period qualifier lets !goals this week and !goals next week
coexist. Suggested encoding: a period: tag (e.g. period:2026-w22).
For v1 we keep it simple — no period qualifier, latest wins.
The pinning UX hooks straight in: when a !goals message is the
latest replaceable entry from its author, the bot can ask Matrix to
pin it (and unpin the previous one). This makes the room's pinned
message a live mirror of the relay state.
3.4 Forward + retrospective in a single !journal
The data shows people blend "did X" and "will do Y tomorrow" in the
same !journal. The spec currently says journals are past-tense and
append-only. Rather than fight the user, we accept the blend.
Spec change: in §3.1, clarify: "
!journalis append-only; implementations MUST NOT close journals. Bodies MAY contain forward-looking statements; the classifier MAY surface these as candidate tasks at review time but MUST NOT auto-create derived task entries."
The "candidate task" idea is a v2 nicety: a weekly digest that pulls
"should…" bullets out of journals and offers them as !task
candidates. Not in v1.
3.5 Recurrence tags (lightweight, pre-RRULE)
For the chore-list problem (every ~3 days scoop manure, daily fresh water), we propose a frequency: tag namespace that lives
inside the existing ["t", …] mechanism. Renderers parse it.
Suggested values:
| Tag | Meaning |
|---|---|
frequency:daily |
Once per day |
frequency:weekly |
Once per week |
frequency:3d |
Every 3 days |
frequency:2w |
Every 2 weeks |
frequency:as-needed |
No fixed cadence; on demand |
This is a stopgap. When NIP-52 or a sibling NIP defines proper
recurrence, we migrate. For now, the eink renderer can group
frequency:daily items into a "today" panel and frequency:weekly
into a "this week" panel without parsing RRULE.
Spec change: in §3.3, add: "
frequency:<spec>is reserved for recurrence hints. Recommended values:daily,weekly,Nd(every N days),Nw(every N weeks),monthly,as-needed. Implementations MAY define additional values."
3.6 Subject tags — animals and places, not just people
NIP-52 has ["p", <pubkey>] for people but no convention for
non-human subjects. We propose a namespaced t-tag:
| Tag | Meaning |
|---|---|
subject:animal/sapphi |
Animal named Sapphi |
subject:animal/loki |
Animal named Loki |
subject:place/south-paddock |
A named place on the property |
subject:object/electric-fence |
A named asset/object |
A community can define its own subject vocabulary via !setup:
!setup subjects animal/sapphi animal/loki animal/leia
!setup subjects place/south-paddock place/orchard
When typing, members can reference subjects with a @-prefix as
shorthand:
!journal cleaned @sapphi's wound, fed @hens at noon
The bot expands @sapphi to subject:animal/sapphi tags and
preserves the original text in the body. Renderers can then offer
"recent entries about Sapphi" without the bot needing to do NLP.
For people the existing ["p", "<mxid-or-pubkey>"] already works;
inline @person:name (or just @-mentions resolved through the
Matrix room's member list) feeds straight into that.
3.7 Inline !verb markers within a body are tags, not commands
This is half a spec change, half a clarification:
Spec change: in §3.3, add: "A
!verboccurring at the start of a message (or, with multi-verb support, at the start of a top-level block) is a command. A!verbappearing inside body content is body content and MAY be extracted by the bot as aninline:<verb>tag on the parent entry. This preserves user intent without spawning ghost entries."
So Coco's - !priority diagnosis of sapphis skin condition… bullet
gets recorded as part of the parent !goals entry, and the parent
gets an inline:priority tag. A renderer can surface that bullet
with priority styling.
3.8 Multi-line entries with sub-headers
A small content-format convention so renderers can do something
sensible with Coco's GARDEN / KITCHEN sub-headers:
Spec change: in §10, add: "Bodies MAY use Markdown-style headers (
#,##) as in-body section markers. Renderers MAY surface them as visual groupings. The body remains a single content blob; sub-headers do not split the entry."
4 — Plugin changes proposed
These are concrete edits to tracker/, journal/, and a small
amount of wiki/ if we want cross-plugin discovery. Each maps to a
specific file path so the work is sized.
4.1 Parse inline !verb markers as tags, not commands
tracker/tracker.py:184 — the dispatch handler matches a verb at
start-of-message. Today, anything else is unmatched and the message
is dropped (correct). We extend: after dispatching the top-level
verb, scan the body for inline !verb occurrences and add them as
inline:<verb> tags on the recorded entry. Implementation is a
single pass over the body before recording.
This makes Coco's - !priority … bullets actually do something
useful at the entry level without inventing ghost entries.
4.2 Split multi-verb messages
tracker/tracker.py:52 — the _CMD_RE regex anchors at
start-of-string and captures everything to end-of-string. We change
to a two-pass parse:
- Split the message at every line that starts with
!verb(and only such lines — bullets like- !priority …are NOT split points). - Each split block becomes its own captured entry.
Helena's !journal … !task … message becomes two entries. Skye's
!goals !tasks on a single line stays as one entry but gets both
tags applied. This requires a second regex for the multi-verb-one-line
case.
The order matters: split first on newline-prefixed !verbs, then on
the single-line multi-verb case.
4.3 Tolerate trailing colon and case on verb
tracker/tracker.py:52 — change the regex to allow an optional
trailing colon and explicit case-insensitive flag:
_CMD_RE = re.compile(r"^!(\w+):?(?:[ \t\r\n]+(.*))?$", re.DOTALL | re.IGNORECASE)
(The .lower() already happens in dispatch; the regex flag is for
unicode \w consistency. Trailing colon is the visible change.)
Apply the same change to journal/journal.py:34 for _JOURNAL_RE.
4.4 Handle Matrix edits
tracker/tracker.py — register a handler for m.room.message events
with rel_type == "m.replace". The handler:
- Looks up the original event id in the items table (we need to start recording it — schema change below).
- If the original is a captured entry, treat the edit as a body
update on that entry. Bump a
last_edited_ts. - Reply with a small ack ("✏️ Updated entry
42").
Schema change: add mx_event_id TEXT column to items, indexed.
This is a real change to upgrade_table — add as upgrade_v2.
tracker/README.md:133 — strike the "Edited messages don't
re-trigger the bot" caveat.
This is the single change that unlocks the most observed user behavior. People do edit, and treating edits as no-ops loses substantial information.
4.5 Detect pin events; mark replaceable verbs as pinned
tracker/tracker.py — subscribe to m.room.pinned_events. When a
captured entry's source Matrix message becomes pinned, mark the
entry as pinned=true. When a !goals entry is recorded, the bot
itself asks Matrix to pin the message (and unpin the previous
!goals from the same author).
This makes the pinned-message UX a transparent mirror of the relay state, without users needing to manually pin/unpin.
(This requires the bot to have pin-event permission in the room. The admin can grant it via Element. Document in the README.)
4.6 Extract inline @-mentions as p-tags
tracker/tracker.py — alongside the existing _TAG_RE extraction
for #tag, add an _MENTION_RE extraction for @user. Resolve
against the Matrix room's member list (best-effort; if it doesn't
resolve, store the literal string).
The recorded entry gets ["p", "<mxid>"] tags for each resolved
mention, and keeps the @user substring in the body for human
readability. A renderer can then offer a "your bullets" view per
person.
4.7 Ship sensible default shortcuts for the cdf rooms
tracker/tracker.py — add a one-time bootstrap that, on first
!setup (or first capture) in a room whose name matches a known
chateau room, pre-populates shortcuts. Suggested defaults:
| Room name | Shortcuts |
|---|---|
| Animals | !buy task #buy, !chores task #priority:5, !vet task #vet, !need need |
| Gardens | !buy task #buy, !harvest task #harvest, !plant task #plant, !need need |
| Operations | !buy task #buy, !steward task #steward, !repair task #repair, !need need |
| Events | !host task #host, !ticket task #ticket |
These are starting points, not a final list. Communities edit them
via !setup once they're in.
A safer way to ship this is a default_shortcuts.yaml config the
plugin reads, so changes don't need a code redeploy.
4.8 New universal verbs implementation
tracker/tracker.py:56 — add to UNIVERSAL_VERBS:
UNIVERSAL_VERBS = {
"add", "task", "tasks", "sidequest", "sidequests",
"remind", "reminders", "done", "list", "setup",
"goals", "need", "needs",
}
(Plural aliases per §3.1.)
Add _handle_goals and _handle_need handlers. !goals uses
replaceable-event semantics (§3.3) — for the matrix-local v1, this
means upserting on (user, room, kind='goals') rather than
inserting. One row per author per room.
!need records a kind='need' item that stays open until
either !done (we got some) or another verb explicitly converts it
to a !buy task.
4.9 Frequency tag parsing in !list
tracker/tracker.py:302 — when listing items, group by
frequency: tag so the chore-list renders as:
**Daily (3):**
- `5` fresh water for alpacas
- `7` fresh water for ducks
- `12` open & close hens
**Every 3 days (2):**
- `19` scoop alpaca manure
- `23` fluff alpaca bedding
**Weekly (1):**
- `4` change out hen straw
This is rendering, not protocol — the spec just stores tags.
4.10 Replace the tracker/README.md quirk note
After §4.4 lands, strike the edit caveat. Add a paragraph on the new pin behavior, the new universal verbs, and the multi-verb splitting.
5 — New ideas the pilot surfaced
5.1 Opt-in "private journal room" mode
For a per-user private journal room (one bot account, one human
member), the prefix friction adds nothing — every message is
journal content by definition. We can add a per-room flag
auto_journal: true (default false) that records every plain
message as a !journal entry. This is opt-in per room and the
bot acks loudly the first time it activates so nobody is surprised
by it.
For shared rooms — which is everywhere in the pilot — the default
stays explicit-prefix-only, matching Coco's "!journal is the
required format" enforcement.
5.2 Multi-room fan-out
Skye's "I'm not sure which chat to put these social things in"
suggests an entry can sometimes belong to multiple rooms. We
propose a +#room syntax:
!task +#events +#general organize image-AI brainstorm with pat and coco
This records the entry in both communities. The same entry has
two a-tags (one per NIP-72 community). Renderers in either room
see it. !done closes it in both.
Implementation: parse +#<roomname> tokens out of the body, resolve
to room ids the bot is also a member of, and insert one row per
target room with a shared link_id. v2 work, not v1.
5.3 Photo / link / media in entries
Helena's "checked feathered babies" entry was actually a photo +
caption. Thomas shares YouTube links. Coco shared a PDF on toxic
plants. The body field today is text; the bot can capture media
attachments by storing their mxc:// URI in a media JSON column.
A renderer can fetch and display.
Especially valuable for the eink panel — a photo of the daily chores list, a graph of fed/watered checkmarks, the duck-pool-water-runoff diagram.
5.4 Calendar feed for timed entries
Pat already saw the vet appointment on the castle calendar — "nice
i already see it on the castle calendar". This integration should
be documented: where it lives, what feeds it. If it's manual, it
should be automated; if it's automated, it should be tested for
all kind 31923 timed entries.
The natural shape: an iCalendar feed at
https://docs.ariege.io/calendar.ics produced from the bot's
timed-entry table. Castle members subscribe in their calendar app
of choice.
5.5 Daily / weekly digests
The pilot showed the value of summary. Coco pins a current
!goals. Ulo posts meeting summaries. Helena writes "homework"
recaps. The bot can produce these on a cron:
- Morning digest (per room): "Yesterday's journal entries (3), Open tasks this week (12), Goals pinned (1)."
- Weekly digest (Sunday evening): "This week's completed tasks (28), Open carry-over (15), Journal highlights (a sampling)."
This is a content surface, not protocol. The data is already there.
Implementation = a cron handler + a markdown template + posting to
the room. Maubot has cron support via asyncio + croniter.
5.6 Bot personality — Alfred
The community named the bot Alfred (the butler). Replies should match: a slightly formal, helpful, occasionally dry tone.
Concretely:
- Current acks:
📥 Logged for @alice. - Alfred-flavored:
Very good, @alice. Logged.
A personality config field with default | alfred | minimal
lets other adopting communities pick. Keep default deadpan and
neutral.
This is low-priority but it costs nothing and the data shows the community will engage with the bot more if it feels like a collaborator. "What should we name our assistant?" — "Alfred would be my go to" — "doiittt" is a community taking ownership of the tool before it exists.
5.7 LLM fallback inside the chateau network
The spec's classifier conformance level 2 is LLM fallback. The chateau has an existing Ollama setup or can run one on the same host as maubot. The fallback fires only when:
- The user typed
!add(explicit ambiguity), - The rules classifier returned
unclassified, - The LLM is reachable.
If any condition fails, the entry stays in the inbox until human-sorted (level 0 fallback). The architecture stays self-hostable.
Smallest reasonable model for this is in the llama3:1b /
phi3:mini size range — runs comfortably on the maubot host.
5.8 Wiki / docs lookup inside the tracker context
The wiki plugin already exists. Inside a tracker reply, if an entry
mentions e.g. "recycling", the bot could surface a [?] hint:
"Related: docs.ariege.io/spaces/waste-recycling". One-line link,
ignorable.
This makes the chateau's docs site organically discoverable from chat without anyone needing to remember URLs. Implementation: inside the tracker's record path, fire a quick keyword query at the wiki plugin's index and append top-1 result if confidence is high.
6 — How this fits the larger omnixy / aiolabs ecosystem
The Château pilot is one community using one piece of the stack. The broader picture:
6.1 The protocol survives the implementation
The community-organizer spec is CC0 and references only open standards (RFC 5545 VTODO, NIP-52, NIP-72, ActivityStreams). If the maubot plugin disappears tomorrow, the events on the relay are still readable by any NIP-52 client. The chateau's organizational memory is not coupled to maubot. That's the design property we're protecting.
6.2 Nostr bridge (Phase 2)
Today the tracker is matrix-only. When the vocabulary stabilizes (probably 2-4 more weeks of pilot), Phase 2 bridges to Nostr:
- Bot writes captured entries to a community Nostr relay.
- The relay can be private (auth-gated) or public per the
publishposture config. - Renderers (the eink panel, a future webapp dashboard) subscribe to the relay and surface the data.
This is the unlock for the inky-impression panel in the foyer — the data shape it consumes is exactly the events the bot will be producing.
6.3 Identity — the signer abstraction
Today everything is signed by the bot. The spec's §7.2 / §12
develop the per-user-signing endgame: a sidecar
nsecbunkerd on the same host, the bot holding only scoped NIP-46
connection tokens.
At chateau scale (10-20 members), this is overkill for v1. We run
v1 (trust the bot, author tag carries the human MXID) for as long
as the community is small and physical-trust-bounded. We migrate to
per-user signing when:
- More than one community is using the same bot account, or
- An external party (visitor, woofer, neighbor) needs to write entries without being a fully-trusted member, or
- LNbits #18 (the bunker integration) ships and we want a single identity story across the stack.
The signer abstraction is already in the spec, so the migration is design-for-it-now, do-it-later.
6.4 LNbits / Lightning
Two Lightning hooks the pilot suggests:
Marketplace / payable buy items. A !buy item could optionally
carry a price and produce a Lightning invoice via LNbits when
clicked through. "Roll-out flypaper — €12 — pay" with the invoice
generated against the chateau's funding wallet. Useful for outside
contributors who want to chip in a specific item.
Visa funding stream. Coco's alpaca funding stream (€23k over time) is exactly the kind of recurring-pledge use case LNbits has. This is a partnership channel between the tracker and the LNbits extension at the marketplace level, not v1.
6.5 Events app
Coco's events-app side-project is in the pilot data: "developing the app & biz plan for tech company of an ariege-wide calendar of events app". The tracker's NIP-52 31923 events are the right shape to feed that calendar. The webapp consumes NIP-52 already (per the bunker spec discussion). One data shape, two surfaces: the bot records, the events app displays.
6.6 Continuwuity homeserver
The Matrix homeserver running this is Continuwuity, deployed via
deploy/server-deploy/modules/services/matrix.nix. The maubot
daemon registers via the admin-room token flow (see
~/dev/CLAUDE.md Matrix-homeserver section). All bot accounts in
this report (@journalbot, future @trackerbot, @wikibot, etc.)
are regular Matrix users on that homeserver.
The bot-as-user pattern means a chateau member can DM the bot
privately (e.g. for personal !journal entries the public room
shouldn't see). The current journal plugin already supports this —
just invite the bot to a 1-1 room.
6.7 Wiki cross-cutting
The wiki plugin (!ask, !doc) reads docs.ariege.io. The
chateau's documentation should grow alongside the tracker — when a
new community-life protocol gets agreed on at a meeting (e.g.
"who feeds the cat"), it should land in docs.ariege.io/spaces/...
and be !ask-able. The pilot showed several decisions that would
benefit from durable documentation: the chickens' opening time, the
puppy training schedule, the vet's number.
This argues for a small tracker → wiki integration: when a
!journal entry contains a decision (heuristically: contains
"we decided" / "rule" / "from now on"), the bot pings the room with
"This looks like a durable decision — would you like to file it
as a docs page?". One-click → wiki page draft.
7 — Phased plan
A 5-phase rollout that keeps each step small, deployable, and reversible.
Phase 0 — Verb normalization and edit handling (next 1-2 weeks)
Small parser / dispatch changes. No schema migrations beyond
mx_event_id.
- §4.1 inline
!verbmarkers as tags - §4.2 multi-verb-per-message splitter
- §4.3 trailing-colon + case
- §4.4 edit handling (schema v2: add
mx_event_id) - §4.8 new universal verbs (
!goals,!need, plural aliases) - §4.10 README updates
After Phase 0, the bot won't drop any of the entries we observed.
Phase 1 — Replaceable goals and pinning (2-4 weeks)
- §3.3 replaceable-event semantics in spec
- §4.5 pin/unpin behavior on
!goalsrecording - §4.7 default shortcuts for cdf rooms
- §4.9
!listgrouping by frequency
After Phase 1, !goals becomes a living list per author and the
chore-recurrence model is at least visible to renderers.
Phase 2 — Subjects, mentions, recurrence (4-6 weeks)
- §3.5
frequency:tag in spec - §3.6 subject tags (animals, places)
- §4.6 inline
@-mention extraction - §3.7, §3.8 grammar clarifications in spec
- §5.5 daily/weekly digests
After Phase 2, the eink panel can render meaningful views without needing protocol changes.
Phase 3 — Nostr bridge (6-10 weeks)
- Wire the tracker's local SQLite to a Nostr publisher.
- Subscribe to events tagged with the bot's communities for bidirectional sync.
- Eink panel goes live against the relay.
Phase 4 — Per-user signing and identity (when LNbits #18 ships)
- Operator-IdP + sidecar bunker per spec §12.
- Chat-handle ↔ pubkey binding via LNbits.
- Bot acquires scoped NIP-46 tokens per member.
BotSignerbecomes the fallback only.
8 — Open questions for the Château
Things the team should weigh in on before we lock the next phase:
-
Verb names. Is
!goalsthe right word, or!intentions/!focus/!agenda? Same for!needvs!stockvs!low. The bot will accept what the community uses — but the spec name will stick. -
Default shortcuts per room. §4.7 lists candidates. Anything missing? Anything wrong? Specifically: does the Animals room want
!vetand!medas separate kinds, or one!health? -
Subject vocabulary. Which animals, places, and assets are worth naming as subjects? Suggested first pass: animals — Sapphi, Loki, Leia, Tango, Morrigan, plus group names (alpacas, hens, ducks, pups, hatchlings). Places — orchard, south-paddock, coop, garage, kitchen, lab, dependence. Assets — tractor, electric-fence, van, irrigation.
-
Calendar integration. Today something turns dated journal entries into castle-calendar items. Who owns that pipeline? Should the bot own it? Should we publish an
.icsfeed off the maubot host? -
Photo / media capture. Does it matter that journal entries capture the photos attached to them, or is text enough for v1? (Materially affects storage and the eink panel.)
-
The "Alfred" persona. Yes / no / opt-in per room?
-
The private-journal room mode. Would members value a 1-1 DM with the bot where every message is auto-journaled, or does the explicit
!journaleverywhere feel cleaner? -
LLM fallback. Comfortable running a local model on the same host that classifies
!addentries? Or stay rules-only? -
Cross-room fan-out. Do members value
+#room1 +#room2syntax, or is "I'll just repost in the other room" fine?
Appendix A — Glossary
- Verb — A
!-prefixed word at the start of a message that the bot recognizes as a command (e.g.!journal,!task). - Tag — A
#-prefixed word inside a message that gets attached to the entry as metadata (e.g.#buy,#priority:1). - Subject — A
@-prefixed word that names an entity (animal, place, asset) the entry is about. - Shortcut — A per-room alias that expands to a universal verb
- tags (e.g.
!buyexpands to!task #buy).
- tags (e.g.
- Replaceable event — A NIP-52 event keyed by a
d-tag, where newer events overwrite older ones with the same key. Used for living lists like!goals. - Inbox — Where
!addentries land when the classifier can't determine a kind. Cleared via!sortor!reclassify. - Bot — The maubot plugin instance attached to a Matrix client
account (e.g.
@journalbot:ariege.io). - Renderer — Any output surface (eink panel, webapp dashboard, mobile notification) that consumes captured events.
Appendix B — File map
Concrete files this report's proposals would change:
| File | Change |
|---|---|
docs/community-organizer-spec.md |
§3.1 plural aliases, §3.2 new verbs, §3.3 replaceable, §3.5 frequency, §3.6 subjects, §3.7 inline markers, §3.8 sub-headers |
tracker/tracker.py:52 |
Regex updates (case-insensitive, trailing colon) |
tracker/tracker.py:56 |
UNIVERSAL_VERBS additions |
tracker/tracker.py:184 |
Dispatch — multi-verb + inline tag extraction |
tracker/tracker.py |
New _handle_goals, _handle_need, _handle_edit |
tracker/tracker.py (upgrade table) |
upgrade_v2 — mx_event_id, link_id, pinned columns |
tracker/classify.py |
Optional — LLM fallback wiring |
tracker/README.md:133 |
Strike the edit caveat, document new behaviors |
journal/journal.py:34 |
Regex update consistent with tracker |
wiki/wiki.py |
Optional !ask-from-tracker integration |
End of report.