Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
1c38fd6
fix(voice): transcribe in the household language
arthware Sep 24, 2026
aa1de28
test: render the memories corpus with any speech endpoint
arthware Sep 24, 2026
41af4db
refactor: share the briefing callout between vault writers
arthware Sep 24, 2026
c0081cd
feat(diary): keep every diary entry as a card in the memory vault
arthware Sep 24, 2026
c3adb93
feat(memory): add family-life topics to the ontology
arthware Sep 24, 2026
abafbeb
feat(memory): show every vocabulary block in stack memory prompt
arthware Sep 24, 2026
5a42581
feat(core): let a bot take part in rooms another stacklet owns
arthware Sep 24, 2026
e26fc69
feat(core): let a bot skip voice messages it has no use for
arthware Sep 24, 2026
9aea0a7
feat(diary): correct a diary card and keep the correction in the vault
arthware Sep 24, 2026
ce55f04
feat(archivist): post diary cards in the memories room
arthware Sep 24, 2026
9cb0482
feat(diary): head each diary entry with its card's title and summary
arthware Sep 24, 2026
cd12e72
fix(diary): keep only facts worth looking up on a diary card
arthware Sep 24, 2026
8a60de1
docs: describe the family diary in the user guide
arthware Sep 24, 2026
945a82a
docs: describe the family diary in the README and admin guide
arthware Sep 24, 2026
b8ccb08
feat(messages): mention the family diary in the Memories welcome
arthware Sep 24, 2026
6fbcace
feat(diary): mention the morning cards on an empty diary
arthware Sep 24, 2026
7b4ae8d
docs: record the diary card decisions
arthware Sep 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ The reference implementation runs on a Mac Studio M1 in our living room at Lake
> [!TIP]
> **New in 0.3: your family server gets a memory.**
> The `memory` stacklet curates a wiki of your family life out of the documents, notes, and voice memos you drop in the chat. Browsable, searchable, Obsidian-compatible, on your own Mac. Ask a question in the chat and get an answer with sources.
> **And a family diary.** famstack turns the voice messages and photos you post in the Memories room into a diary you read back month by month, in your own words. Each memory gets a card in the chat; reply to it to fix a name or a date.
> It's in daily use on our own server, first tagged as [`v0.3.0-beta.1`](https://github.com/famstack-dev/famstack/releases/tag/v0.3.0-beta.1). [Read the introduction](https://famstack.dev/blog/famstack-0-3-beta/).

## What you get today
Expand All @@ -45,6 +46,7 @@ The reference implementation runs on a Mac Studio M1 in our living room at Lake
- **Photo library and mobile backup** that replaces iCloud Photos for the whole family (Immich).
- **Document archive with OCR** that you photograph from your phone and the local AI files for you (Paperless-ngx).
- **Your family wiki**: an Obsidian-compatible second brain, generated from the documents, notes, and voice memos you file (memory).
- **Your family diary**: voice messages, photos and notes from the Memories room, read back month by month in your own words. Correct any memory by replying to its card in the chat (memory).
- **Local AI engine** on Apple Metal GPU: voice transcription, text-to-speech, document classification (oMLX + Whisper + Piper).
- **A bot runtime in chat** that automates the small stuff: filing receipts, transcribing voice memos, status reports.
- **Email into the family brain**: point a mailbox at a chat room and new mail (with its attachments) lands there for the archivist to file, newsletters and marketing filtered out (IMAP, read-only, private).
Expand Down Expand Up @@ -205,6 +207,7 @@ Document filing, photo backup, family chat with voice memos, and the family memo
| Bot runtime (archivist-bot, scribe-bot, stacker-bot) | :white_check_mark: Live |
| Private Git server (Forgejo) | :white_check_mark: Live |
| Family wiki generated from your documents (memory) | :construction: 0.3-beta |
| Family diary from the Memories room (memory) | :construction: 0.3-beta |
| Document Q&A with citations, in chat | :construction: 0.3-beta |
| Voice memos become searchable notes | :construction: 0.3-beta |
| Topic rooms: the room name is the filing system | :construction: 0.3-beta |
Expand Down
7 changes: 6 additions & 1 deletion docs/admin-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ You will see two rooms:

- `#Family Chat`: where the family talks. Photos, voice memos, life.
- `#Server Room`: where the server talks back. Status, alerts, install confirmations.
- `#Memories`: a place to store your memories, voice diaries, stories, funny moments.
- `#Memories`: a place to store your memories, voice diaries, stories, funny moments. With the `memory` stacklet it becomes the family diary (see [Memory](#memory-memory-optional)).

### 5. Connect your phones

Expand Down Expand Up @@ -545,6 +545,8 @@ Setup seeds the vault with three things: the classification ontology (the topics

The wiki maintains itself. A curator sidecar (`stack-memory-curator`) watches the vault: when new filings settle it regenerates the pages of the family members involved plus the home page (a couple of LLM calls, a few minutes after the burst), and once a night it rebuilds everything — topic pages, cross-references, the lot — while the GPU has nothing better to do. `./stack memory wiki` stays available as the manual trigger, and `[memory]` in `stack.toml` holds the knobs (see [Configuration](#configuration)). Edits happen in Forgejo (every wiki page links to its source), so the commit log doubles as the household's learning history.

**The family diary.** Everything posted in `#Memories` becomes a diary entry. Each night the curator transcribes the new recordings, has the AI read each entry (a title, a summary, the people, topics from the ontology, facts), writes one card per entry to the vault under `family/diary/entries/`, and rebuilds the diary pages in the wiki from those cards. At 07:30 local time the archivist posts each new card as a quiet notice in the thread under its memory, and one short notice with the count (`diary_job_at` in the archivist's `bot.toml` sets the time; it catches up after a night the Mac slept through). A family member corrects a card by replying in its thread, typed or spoken; the correction is committed to the vault under their name, and a corrected or hand-edited card is never overwritten by a later run. The archivist says nothing else in `#Memories`. The user guide has the family's side: [The Memories Room](user-guide.md#the-memories-room).

| | |
|---|---|
| Wiki port | `42070` (domain mode: `memory.<your-domain>`; `wiki.<your-domain>` redirects there) |
Expand All @@ -559,6 +561,9 @@ Useful commands:
./stack memory lookup <text> # which topic or doctype does a term resolve to?
./stack memory correspondents # inspect the correspondent layer
./stack memory pull # fast-forward the local vault after Forgejo edits
./stack memory diary # take in the Memories room now instead of tonight
./stack memory diary --dry-run # show what would be written, write nothing
./stack memory prompt # the vocabulary the models are given, per prompt
```

---
Expand Down
15 changes: 15 additions & 0 deletions docs/adr/adr-011-vault-brain-projection.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,18 @@ Cost: a page filed seconds ago is findable after the next mirror tick,
not at once. Read-your-writes is tested for todos only
(`tests/e2e/test_demo_rig_e2e.py`), so no stated invariant changes.

## Update 2026-09-24: diary entries are records

A diary entry is a thing that happened, so it is now a record in the
vault: one card per entry of `type: diary` under
`<bucket>/diary/entries/`, written by the diary compile through the
Forgejo API. The month, year and index pages stay projections in the
brain and are rebuilt from the cards alone. The wiki does not publish
`diary/entries/`, while search and the agent read the cards through the
brain like any other record.

A card the family corrected (by replying in its thread in the memories
room) or edited by hand is theirs: the compile never overwrites it, and
the vault commit that changed it names who did. The diary is therefore
the one chat filing not rebuilt by replaying its thread (see
`docs/agent/dev.md`, "Reprocessing replays the source").
2 changes: 2 additions & 0 deletions docs/agent/dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ famstack/

Reprocessing re-derives from the source, never from the vault file. For a chat filing the source is the **whole thread** - the original message **plus its reply chain** (corrections) - folded in timeline order. Machine-derived vault state must stay reproducible this way; only user hand-edits are irreducible. See [adr-010](../adr/adr-010-event-pipeline.md).

The diary is the exception. A reply in a diary card's thread is applied to the card once, recorded in the vault commit that applied it (`correct: <title>`, authored by the person), and the corrected card is the family's from then on: the compile leaves it alone, like a hand-edited card. The card thread is never replayed into the card. See [vault-format.md](../design/brain/vault-format.md) (`diary`).

## Stacklet anatomy

Required:
Expand Down
19 changes: 18 additions & 1 deletion docs/design/brain/content-pattern.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
# One content pattern for the brain

Status: proposed, 2026-09-19. Nothing is built yet.
Status: built for the diary, 2026-09-24 (famstack #132). Decisions taken
in building it, where they differ from the proposal below:

- Entry unit: the message group (one recording, photo or note with its
joined fragments and replies). Longer occasions ("Roadtrip 2026") are
a later layer above the cards, not bigger cards.
- One compiler, changed in place, not two compared side by side: with
the entry unit unchanged, a module test pins that the pages built from
cards lose nothing of the entries.
- Cards live at `<bucket>/diary/entries/YYYY/MM/YYYY-MM-DD-<id>.md`, out
of the wiki's way; `type: diary` (vault-format.md).
- Tags are the ontology's topic names and `Person: <name>`, as on
documents, not `Topic:<name>`.
- The archivist, not a memory bot, posts the cards (once a day) and takes
corrections in their threads, reusing its correction handling.
- A correction is applied once to the card in the vault and recorded in
the vault commit under the corrector's name; the corrected card is the
family's and is never recompiled. The thread is not replayed into it.
Related: [open-knowledge-format.md](open-knowledge-format.md),
[vault-format.md](vault-format.md), [diary-journal.md](diary-journal.md),
ADR-011 (vault as database, brain as projection).
Expand Down
42 changes: 42 additions & 0 deletions docs/design/brain/vault-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ cheap).
- `note` — a captured note (verbatim paste).
- `bookmark` — a captured URL.
- `email` — a folded email thread.
- `diary` — one entry from the memories room (a recording, photo or note,
with its joined fragments and replies).

**Entities & structure** (generated projections; MUST carry
`generated: true`):
Expand Down Expand Up @@ -135,6 +137,46 @@ message is preceded by an idempotency marker comment
`<!-- mid:<Message-ID> -->` in the body (not frontmatter). `resource`
may carry the mailbox/thread reference.

### `diary`
One file per entry at
`<bucket>/diary/entries/YYYY/MM/YYYY-MM-DD-<entry_id>.md`.
The diary pages in brain are compiled from these files and nothing
else, so a correction made here reaches every page.
The records are mirrored into brain like every source file, so search
and the agent read them, but the wiki does not publish `diary/entries/`.

| Field | | Notes |
|---|---|---|
| `type` | R | `diary` |
| `title` | R | |
| `timestamp` | R | when the entry's first message reached the room. |
| `date` | R | the day it happened (spoken date, else the day it was sent). |
| `entry_id` | R | short hash of the first message's event id; the path's identity. |
| `date_basis` | O | `spoken` \| `sent` \| `uncertain` \| `corrected` (a family member's correction set it). |

A correction is a reply in the card's thread in the room. It is read
again on every compile, applied to the card, and recorded in the vault
commit (`correct: <title>`, authored by whoever wrote it), not on the
card; its event id joins `event_ids`.
| `description` | O | one sentence. |
| `persons` | O | list. |
| `tags` | O | list. |
| `filed_by` | O | Matrix localpart of the sender. |
| `addressee` | O | who the message is spoken to, as it names them. |
| `medium` | O | `voice` \| `image` \| `video` \| `file` \| `text`. |
| `mode` | O | `monologue` \| `dialogue` \| `note`. |
| `duration_ms` | O | integer. |
| `resource` | O | Matrix permalink of the first message. |
| `event_ids` | O | list; every message folded into the entry. |
| `media` | O | list; site paths of the archived files. |
| `model` | O | |
| `digest` | O | hash of the file as the compiler wrote it. A file that no longer matches was edited by a person, and the compiler leaves it alone. |

The body holds the briefing callout, then `## Quotes`, `## Replies`,
and last the family's own words under `## Transcript`, `## Text` or
`## Caption`. The words come last so nothing in them can be mistaken
for a section.

### `person` (generated)
| Field | | Notes |
|---|---|---|
Expand Down
1 change: 1 addition & 0 deletions docs/stack-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ reformat = true
| `name` | Display name in Matrix. |
| `room` | Room alias to create/join. Optional — omit for bots that only respond to DMs/invites. |
| `room_topic` | Topic set on auto-created room. |
| `join_rooms` | Aliases of rooms another stacklet owns that the bot takes part in. Joined on every start when they exist; never created, and no one else is joined to them. |
| `settings` | Arbitrary key-value pairs passed as kwargs to the bot constructor. |

Module convention: strip `-bot` from the ID → `archivist.py` → class `ArchivistBot`.
Expand Down
59 changes: 52 additions & 7 deletions docs/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ What that gets you:

- **A wikipedia of your family.** Documents, notes, links and voice memos become a curated wiki of your family life. Searchable, browsable, owned by you.
- **Paperwork that files itself.** Photograph a letter, send it to chat, done. OCR'd, tagged, findable forever.
- **Your family's memories, kept.** Your kids' voices, the funny things they said, bedtime stories in their own words. Record them in the chat and famstack turns them into a family diary you read back month by month. Your personal family story at your fingertips.
- **Answers instead of folder hunting.** Ask "when does the car insurance renew?" and get the answer, with sources.
- **Never miss a thought.** Voice memos become clean, filed, searchable notes.
- **Nothing leaves the house.** No cloud, no subscription, nobody else reading your family's life. It all runs on your own Mac.
Expand All @@ -14,19 +15,24 @@ This guide is for everyone in the family: what to type, what comes back, and wha

Setting the server up, or keeping it running? That is the [Admin Guide](admin-guide.md).

> [!TIP]
> **Try the Memories Room.** Record a voice message for your kids tonight, and tomorrow morning it is in your family diary. After four months of recording memos and our kids' voices, it has already become one of our most valuable artifacts. [How it works](#the-memories-room)

## How do I...?

| You want to | Go to |
|---|---|
| Record the kids, keep the stories | [The Memories Room](#the-memories-room) |
| Read the family diary | [The family diary](#the-family-diary) |
| Fix a name or a date in a memory | [Put a memory right](#put-a-memory-right) |
| File a letter, receipt or contract | [File documents](#file-documents) |
| Find a document again | [Ask questions](#ask-questions) |
| Save a link, note or PDF for later | [Capture rooms](#save-anything-capture-rooms) |
| Collect everything about one project | [Topic rooms](#topic-rooms) |
| Get email into the family chat | [Email](#email) |
| Capture a thought without typing | [Voice memos](#voice-memos) |
| Fix a wrong tag or title | [Correct the bot](#correct-the-bot) |
| Fix a wrong tag or title | [Correct bot mistakes](#correct-bot-mistakes) |
| Browse what the family knows | [The family wiki](#the-family-wiki) |
| Record the kids, keep the stories | [The Memories Room](#the-memories-room) |

---

Expand Down Expand Up @@ -142,7 +148,7 @@ Driving home and something crosses your mind: hold the mic button, talk, done. T

---

## Correct the bot
## Correct bot mistakes

The archivist gets things wrong sometimes. Wrong family member, too generic a tag, a title that misses the point. You fix it by replying.

Expand All @@ -157,6 +163,8 @@ Anything you write in the filing's thread counts as a correction, so you can als

This works for captures too: reply to a bookmark or note confirmation and it gets re-filed with your hint.

Memories work the same way, in the thread under each memory: see [Put a memory right](#put-a-memory-right).

---

## Ask questions
Expand All @@ -182,19 +190,56 @@ If the first pass isn't enough, it tells you it's looking deeper and reads the a

Everything the archivist files becomes more than a pile of documents: the memory stacklet renders it as a wiki of your family life. A home page, a page per family member, topic pages, a page per correspondent (the insurance company, the school, the doctor's office).

Open it at `http://<mac-ip>:42070` (or `wiki.<your-domain>` if the admin set up a domain). It updates itself as things get filed.
Open it at `http://<mac-ip>:42070` (or `memory.<your-domain>` if the admin set up a domain). It updates itself as things get filed.

Every page has an edit link: edits happen in Forgejo (the family's private git server), so every change is tracked and nothing is ever lost. If you use Obsidian, you can clone the vault and browse it there; it's all plain Markdown.

---

## The Memories Room

One of the most valuable things you can do with famstack has nothing to do with documents.
> Needs the `memory` stacklet. Voice messages need the `ai` stacklet; the cards in the room need the archivist (`docs`).

One of the most valuable things you can do with famstack has nothing to do with documents. If you try one thing, make it this room.

The Memories Room keeps what photos can't: your kids' voices, the funny things they said, bedtime stories in their own words. We record a voice diary once or twice a week at the dinner table: what was funny, what was special, what the kids want to tell their future selves. Holiday diaries, first days at school, a birthday message. We wish we had started with our first son.

famstack does more than keep them. Every night it transcribes what you recorded, works out the date and who it was for, and writes it into a family diary you can read back month by month, with every recording one tap away. You don't type, tag or file anything. This is the feature that keeps gaining value.

A few habits help:

- **Say the date.** Start a recording with "Today is the third of March" and famstack files the memory on that day, even if your phone uploads it a week later. Without a date, the day you sent it counts.
- **Say who it is for.** Start with "Hi Bart, ..." and famstack files the memory as a message to Bart. The diary shows it whole, as a letter.
- **Reply to add to a memory.** The diary keeps your reply, or a caption under a photo, with the memory.

The archivist does not reply to anything you post there.

### What happens overnight

Every night, famstack reads the new memories: it transcribes the recordings, and your own AI reads each one for a title, who it is about, a short summary and the facts worth finding again ("Maggie: first tooth", "Swimming badge: 25 metres"). famstack files each memory as a card in the family's archive.

In the morning, the archivist puts each new card in the thread under its memory, and one short note in the room:

> **archivist**: ❤️ 3 new memories in the family diary. [Open the diary]

Both are quiet messages, so no phone buzzes. A memory you post today gets its card tomorrow morning.

### Put a memory right

The AI mishears names and gets things wrong. Correct it in the memory's thread, the way you correct a document: open the thread under the memory, and reply to its card, typed or as a voice message.

> **archivist**: 📔 **Sandcastle at the lake** · Sunday, 20 September 2026 ...
> **you** (in the thread): It was Lisa who built the tower, not Bart. And it was the 19th.

The archivist answers with 👀, puts the corrected card in the thread, and confirms with ✅. You can correct the title, the date, who it is about, the summary and the facts. The recorded words themselves stay as they were.

famstack saves your correction in the family's archive under your name, and the card is yours from then on: the nightly run never changes it back. To correct it again, reply in the same thread.

### The family diary

The Memories Room is a place to record your family's life. Voice messages, photos, text. We record a voice diary once or twice a week at the dinner table: what was funny, what was special, what the kids want to tell their future selves. Holiday diaries, first days at school, bedtime stories in their own words.
Open it from the note's link, or from the family wiki's home page (**Family Diary**). You read it month by month: a short opening for each month, then every memory under its day, with its title, who recorded it, a short summary, the words as they were said, the photos, and the recordings to play. For a long recording you see a few lines worth keeping, and the full transcript is one click away. A message spoken to one person appears whole.

Start collecting these. They become valuable just as they are. Voice transcription already works; an upcoming update will weave the Memories Room into the family wiki as a chronicle: "Remember? One year ago...", "Lisa's third birthday...". Everything stays on your Mac. Your memories are just yours.
Transcription and reading run on your household's own AI, so nothing leaves your home. Your memories are just yours.

Start now. You will wish you had started earlier.

Expand Down
Loading
Loading