Skip to content

feat(diary): keep every diary entry as a card the family can correct - #132

Merged
arthware-dev merged 17 commits into
mainfrom
feat/diary-cards
Sep 24, 2026
Merged

arthware-dev merged 17 commits into
mainfrom
feat/diary-cards

Conversation

@arthware-dev

Copy link
Copy Markdown
Contributor

Summary

  • Every memory in the memories room becomes a card in the family vault (family/diary/entries/): the words as recorded, the files, and a title, summary, facts, people and ontology topics read by the household's model. The diary pages are built from the cards, so a correction shows everywhere.
  • The archivist posts each new card in a thread under its memo once a day, with one short notice. A family member corrects a card by replying in that thread, typed or spoken; the correction is committed to the vault under their name and the card is theirs from then on.
  • Also: six family-life topics in the ontology, transcription in the household language, stack memory prompt shows every vocabulary block, and bots can join rooms another stacklet owns.

Merge with rebase: each commit stands alone and is its own release-notes line. The ontology commit carries an Upgrade: footer for existing vaults.

A whisper server started with a fixed language decodes every clip as
that language, so an English voice message sent to a server set to
German came back as a German translation.

The transcriber now states the household language (`[core] language`)
on every request, cut to the ISO-639-1 code whisper expects. Without a
configured language whisper still detects it. A household that records
in more than one language gets every clip decoded as its configured
language.
`FAMSTACK_TTS_URL` points `tools/family-memories/generate.py` at an
OpenAI-compatible speech service other than the ai stacklet's, for a Mac
that does not run it.
The `> [!summary]` block with summary, facts and action items is the
shape every model-read vault record carries. It lived in the archivist's
`vault_entry`, where the diary records that come next could only reach
it by importing across stacklets. It moves to `stack.briefing`, which
the archivist now imports.

No behaviour change.
The diary existed only as generated wiki pages, so a wrong name or date
could not be corrected: the next compile wrote the page again. Each
entry now becomes a card of `type: diary` in the vault, at
`family/diary/entries/YYYY/MM/YYYY-MM-DD-<id>.md`, shaped like a
captured note: the words as recorded, the files, and a title, summary,
facts, people and topics read out of the entry by the configured model.
The diary pages are compiled from the cards alone.

- A card someone edited in Forgejo or Obsidian is never overwritten.
  `stack memory diary` lists it as kept, and the pages show the edit.
- Tags use the ontology's topics and `Person: <name>`, as documents do.
  A name that is not a household member is dropped.
- Cards are committed in one commit per sender, authored by them. A
  file changed in Forgejo since it was read fails the commit instead of
  being overwritten. An unchanged room commits nothing.
- A card whose messages were deleted in the room is removed, but only
  after a run that read the whole room (not with `--limit`).
- The cards stay in the brain for search and the agent; the wiki does
  not publish `diary/entries/`.
The seed ontology was written for documents. On the demo memories room
the diary's reading fell back to Child and Memory for nearly every
entry, because music, sport, hobbies, celebrations, friends and family
life had no topic.

Six topics join the seed, in German and English: Music, Sport, Hobby,
Celebration, Friends and Family Life. Documents can carry them too (a
music school invoice is Music), and the docs taxonomy gains the same
tags. None of their names or synonyms is used by another topic or
document type.

Upgrade: an existing vault keeps its own `ontology.toml`. Preview the
change with `./stack memory ontology --dry-run`; `./stack memory
ontology` replaces the vault's file with the seed, so merge any
hand-made topics first.
`stack memory prompt` showed only the topics and document types, in
English unless told otherwise. It now prints every block a model is
given from the family's pages: topics and document types, family
members with their synonyms, and correspondents with their aliases.
Each block names the prompts that receive it. The language defaults to
the household's.

Family members and correspondents are generated pages and live in the
brain. The document classifier still looks for them in the vault, where
there are none, so the output says it receives neither today.
A bot could be joined only to the one room its `bot.toml` declares, and
the bot runner creates that room and joins the admins to it. A room that
belongs to another stacklet, such as the memories room, could not be
joined that way without being recreated or getting members it should
not have.

`join_rooms` in `bot.toml` lists such rooms. The bot runner joins the
bot to each one on every start when it exists, never creates it, and
joins no one else.
Every bot decodes every voice message in its rooms before any handler
sees it: whisper runs and the bot shows as typing. A bot present in a
room for only part of what happens there caused both for messages it
then ignored.

A bot can now decline a voice message by room and message before the
decode. Declined voice messages reach no handler. Every bot still
decodes everything unless it says otherwise.
A diary card could be corrected only by editing it in Forgejo or
Obsidian. `stack memory diary correct <entry> --by <person> --event <id>
--text <words>` applies a family member's correction to the card as it
is in the vault: title, people, topics, summary, facts and, when the
correction states one, the date. The recorded words never change.

- The vault commit is `correct: <title>`, authored by that person, with
  their words in the body. A new date moves the card in the same commit.
- A corrected card is the family's from then on: the nightly compile
  leaves it alone, as it does a hand-edited one.
- Replies in a card's thread in the memories room never become diary
  entries or replies on the page.
- `stack memory diary --json` reports every card, its thread root and
  whether its thread already holds a card notice, for the archivist.
The diary's cards lived only in the vault, so the family never saw what
was read out of their memories and had no easy way to put it right.

The archivist now joins the memories room and, once a day (07:30 local
time by default, `diary_job_at` in its `bot.toml`), posts each new card
as a notice in a thread on the entry's message, laid out like its other
filing replies, then one notice with the count and a link to the diary.
The first one also explains how to correct a card. A reply in a card's
thread, typed or spoken, corrects it: the archivist reacts, applies it,
posts the corrected card in the thread and confirms.

- Everything else in the memories room is left alone: no filing, no
  search, no welcome, and voice memos are not decoded by the archivist.
- All posts are notices, which Element does not push to phones.
- On its first run the archivist posts cards for the last 14 days only
  and counts the rest, so an existing room is not flooded.
- The job runs on the household's clock, catches up when the machine
  slept through its time, and waits 30 minutes after a failed run.
The diary pages showed each entry under its sender's name, so what a
card says about an entry, and any correction made to it, never reached
the page the family reads.

Each entry now opens with its card's title, then who recorded it and
what it is, then the summary as a short narrative line, then the words
as recorded, all of them. A message spoken to one person keeps no
summary and is shown whole, as before.
Asked for "Label: value" facts, the model labelled them by kind
("Action", "Event", "Date", "Person") and repeated the summary, the date
and the people as a form.

A fact is now labelled by who or what it is about ("Maggie: first
tooth", "Place: Springfield Lake"), milestones come first, and an entry
may have none. Facts labelled only by kind are dropped.
The user guide still called the diary an upcoming update. It now says
how the Memories Room works: saying the date and whom a memo is for, the
nightly reading and the morning cards, correcting a card by replying in
its thread, and what the diary pages show.
The README and the admin guide knew the memory stacklet only as the
family wiki. The README now lists the family diary among what famstack
does today and on the roadmap. The admin guide says how the diary runs:
the nightly intake, the morning cards and when they post, corrections,
where the cards live, and the commands to run it by hand.
The welcome in the Memories room described a collection of recordings.
It now says that the memories become a family diary to read back, and
that nothing leaves the home.
The page a family sees before anything is recorded now says that a card
appears under each message in the morning, and that replying to it
fixes a name, a date or a fact.
ADR-011 gains an update: diary entries are records in the vault, the
diary pages are projections of them, and a corrected card is the
family's. The content pattern note records what was built and where it
differs from the proposal.
@arthware-dev
arthware-dev merged commit a42d7cd into main Sep 24, 2026
1 check passed
@arthware-dev
arthware-dev deleted the feat/diary-cards branch October 7, 2026 11:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants