Skip to content

Commit 08301b2

Browse files
authored
Merge pull request #36 from famstack-dev/okf-conformance
Open Knowledge Format (OKF) conformance + dual-format vault links
2 parents 905cc2f + cffbb75 commit 08301b2

61 files changed

Lines changed: 1659 additions & 1149 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/admin-guide.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,8 +489,8 @@ Your family members. Generated by the installer. User accounts are seeded on the
489489

490490
```toml
491491
[[users]]
492-
name = "Arthur"
493-
email = "arthur@home.local"
492+
name = "Homer"
493+
email = "homer@home.local"
494494
role = "admin"
495495

496496
[[users]]

docs/adr/adr-002-port-mode-first.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Caddy is opt-in, activated when `domain` is set in stack.toml.
1818

1919
**Port mode (domain empty):**
2020
- Services bind to `0.0.0.0:<port>` — reachable from the network
21-
- URLs shown as `hostname:port` (e.g. `mac-arthur.local:42010`)
21+
- URLs shown as `hostname:port` (e.g. `mac-homer.local:42010`)
2222
- Caddy does not start, core only runs Watchtower
2323
- Zero DNS setup required
2424

docs/adr/adr-005-bonjour-discovery.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ One instance per famstack server. The service name is the server's
6262
human-readable name from `stack.toml`:
6363

6464
```
65-
Arthur's famstack._famstack._tcp.local.
65+
Homer's famstack._famstack._tcp.local.
6666
```
6767

6868
### Port
@@ -79,7 +79,7 @@ first API call:
7979
|---|---|---|
8080
| `uuid` | `a1b2c3d4-e5f6-7890-abcd-ef1234567890` | Persistent server identity |
8181
| `version` | `0.1.0` | famstack version (for compatibility checks) |
82-
| `name` | `Arthur's famstack` | Human-readable display name |
82+
| `name` | `Homer's famstack` | Human-readable display name |
8383
| `api` | `/api` | API base path (future-proofing) |
8484

8585
**TXT record size:** ~150 bytes. Well within the DNS-SD 8900-byte limit
@@ -229,7 +229,7 @@ The QR code fallback is more important on Android.
229229

230230
Browsers cannot perform mDNS discovery. The web dashboard has two paths:
231231

232-
1. **Direct URL.** User navigates to `http://mac-arthur.local:42000` or
232+
1. **Direct URL.** User navigates to `http://mac-homer.local:42000` or
233233
the server's IP. Works on Apple devices (Safari resolves `.local` via
234234
mDNS). Inconsistent on Android browsers.
235235

@@ -251,7 +251,7 @@ camera, requires no mDNS support, and transfers the API key in one step.
251251
{
252252
"famstack": 1,
253253
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
254-
"host": "mac-arthur.local",
254+
"host": "mac-homer.local",
255255
"ip": "192.0.2.10",
256256
"port": 42000,
257257
"key": "fs_ak_..."

docs/adr/rfc-001-dashboard-and-companion-apps.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ Key properties broadcast in the TXT record:
470470
_famstack._tcp.local.
471471
uuid = "a1b2c3d4-..." # persistent, survives IP changes
472472
version = "0.1.0"
473-
name = "Arthur's famstack"
473+
name = "Homer's famstack"
474474
api_port = 42000
475475
```
476476

@@ -508,7 +508,7 @@ How does a new device find the famstack server? Full protocol in
508508
Not found? → Show "Scan QR code" or "Enter address"
509509
4. App stores the server UUID in Keychain (persistent pairing)
510510
5. Dashboard shows a QR code at /onboard containing:
511-
{ "uuid": "a1b2c3d4-...", "host": "mac-arthur.local",
511+
{ "uuid": "a1b2c3d4-...", "host": "mac-homer.local",
512512
"port": 42000, "key": "..." }
513513
6. Phone scans QR → paired, UUID + API key stored in Keychain
514514
```

docs/agent/dev.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ Testing rules:
201201

202202
## Commit & branch rules
203203

204+
- **Check branch state before major work.** `git fetch origin` and see how the working branch relates to `origin/main` (`git log --oneline origin/main..HEAD` and `HEAD..origin/main`) before starting anything substantial, new branch or existing one alike. The branch may be older than you think: `main` advances, and a local `main` can itself be stale. Branch off (or rebase/merge onto) the latest `origin/main`; a branch left behind silently diverges and lands the PR in merge conflicts.
204205
- **Feature branches only.** Never commit to `main`.
205206
- **Semantic prefix required:** `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`, `test:`, `ci:`, `style:`.
206207
- **Message style:** short, end-user POV, present tense. *What changed and why a user cares* - not the internal refactor narrative.

docs/design/brain/engram-prototype.md

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
> Status: Design document
44
> Created: 2026-04-29
5-
> Author: Arthur + Claude
5+
> Author: Homer + Claude
66
> Depends on: [knowledge-architecture.md](knowledge-architecture.md), [knowledge-implementation.md](knowledge-implementation.md)
77
> External: https://github.com/Gentleman-Programming/engram
88
@@ -44,7 +44,7 @@ services, knowledge typing with decay, and proactive intelligence.
4444
v
4545
engram (Go binary, MCP + HTTP)
4646
├── SQLite + FTS5 full-text search
47-
├── Project-scoped storage (shared, arthur, sabrina, calendar)
47+
├── Project-scoped storage (shared, homer, marge, calendar)
4848
├── Topic-key upserts (evolving knowledge updates in place)
4949
├── Deduplication via normalized hash
5050
├── Conflict detection + judgment flow
@@ -68,9 +68,9 @@ How Family Brain concepts land on engram's data model.
6868

6969
| Family Brain | engram | How it works |
7070
|---|---|---|
71-
| Knowledge domain (`shared`, `arthur`, `calendar`) | **Project** | Each domain is a project. `mem_search` filters by project. `mem_context` returns per-project. |
71+
| Knowledge domain (`shared`, `homer`, `calendar`) | **Project** | Each domain is a project. `mem_search` filters by project. `mem_context` returns per-project. |
7272
| Knowledge type (`rule`, `fact`, `habit`, `goal`, `preference`, `context`, `event`) | **Type field** | The `type` field is a string, not an enforced enum. We use our own values. |
73-
| Wiki entry that evolves over time | **Observation + topic_key** | `topic_key="fact/insurance-adac"` -- saving with the same key upserts the existing observation, increments `revision_count`. |
73+
| Wiki entry that evolves over time | **Observation + topic_key** | `topic_key="fact/insurance-duff-insurance"` -- saving with the same key upserts the existing observation, increments `revision_count`. |
7474
| Pointer brain / compact index | **`mem_context` per project** | Returns recent sessions + observations. The agent's map of what's known. |
7575
| Cross-domain search | **`mem_search`** | FTS5 across all projects or filtered to one. Supports type/scope filters. |
7676
| Short-term memory | **Session-scoped observations** | Tied to a Kit Bot conversation session. Temporal context via `mem_timeline`. |
@@ -91,11 +91,11 @@ How Family Brain concepts land on engram's data model.
9191
id INTEGER auto-increment
9292
session_id TEXT which session created this
9393
type TEXT "rule" | "fact" | "habit" | "goal" | "preference" | "context" | "event"
94-
title TEXT short, searchable -- "Car insurance ADAC"
94+
title TEXT short, searchable -- "Car insurance Duff Insurance"
9595
content TEXT freeform -- structured however we want
96-
project TEXT "shared" | "arthur" | "sabrina" | "calendar"
96+
project TEXT "shared" | "homer" | "marge" | "calendar"
9797
scope TEXT "project" (shared within domain) | "personal"
98-
topic_key TEXT canonical ID for upserts -- "fact/adac/car-insurance"
98+
topic_key TEXT canonical ID for upserts -- "fact/duff-insurance/car-insurance"
9999
normalized_hash TEXT deduplication fingerprint
100100
revision_count INTEGER incremented on topic-key upsert
101101
duplicate_count INTEGER rolled-up exact duplicates
@@ -109,7 +109,7 @@ deleted_at TIMESTAMP soft-delete (used by decay)
109109

110110
**Topic-key upsert.** When `mem_save` receives a `topic_key` that already exists
111111
within the same project + scope, it updates the existing observation instead of
112-
creating a new one. `revision_count` increments. This is how "ADAC sent a new invoice"
112+
creating a new one. `revision_count` increments. This is how "Duff Insurance sent a new invoice"
113113
updates the existing insurance knowledge rather than creating a duplicate.
114114

115115
**Conflict detection.** When `mem_save` finds observations with similar content,
@@ -132,7 +132,7 @@ Core tools available to Kit Bot via MCP:
132132
| Tool | What Kit does with it |
133133
|---|---|
134134
| `mem_search` | "What do we know about insurance?" -- FTS5 query, filter by project/type/scope |
135-
| `mem_save` | "Remember: Sabrina is allergic to peanuts" -- save with type=rule, topic_key |
135+
| `mem_save` | "Remember: Marge is allergic to peanuts" -- save with type=rule, topic_key |
136136
| `mem_context` | Session start -- load recent knowledge for the current domain |
137137
| `mem_get_observation` | Drill into a search result for full untruncated content |
138138
| `mem_timeline` | Chronological context around an observation |
@@ -165,22 +165,22 @@ Premium: EUR 340/year
165165
Policy: KFZ-2024-XXXXX
166166
Coverage: Vollkasko + Haftpflicht
167167
Expires: 2026-06-30
168-
Source: Paperless #247, ADAC Rechnung 2026-03
168+
Source: Paperless #247, Duff Insurance Rechnung 2026-03
169169
```
170170

171171
### Rules (from conversations or manual)
172172

173173
```
174-
Sabrina is allergic to peanuts.
175-
Source: Arthur via Kit Bot, 2026-04-29
174+
Marge is allergic to peanuts.
175+
Source: Homer via Kit Bot, 2026-04-29
176176
```
177177

178178
### Events (from calendar, transient)
179179

180180
```
181-
Dentist appointment for Sabrina
181+
Dentist appointment for Marge
182182
When: 2026-04-17 10:00
183-
Where: Dr. Weber, Friedrichshafen
183+
Where: Dr. Hibbert, Springfield
184184
Source: Calendar sync
185185
```
186186

@@ -194,9 +194,9 @@ Source: Dream cycle promotion, 2026-04-29
194194
```
195195

196196
Topic keys follow a `{type}/{entity}/{slug}` convention:
197-
- `fact/adac/car-insurance`
198-
- `rule/sabrina/allergy-peanuts`
199-
- `event/calendar/dentist-sabrina-20260417`
197+
- `fact/duff-insurance/car-insurance`
198+
- `rule/marge/allergy-peanuts`
199+
- `event/calendar/dentist-marge-20260417`
200200
- `habit/family/friday-pizza`
201201

202202

@@ -255,7 +255,7 @@ After classification, POST each fact to engram:
255255
```python
256256
async def _save_knowledge(self, classification: dict, doc_id: int):
257257
person = classification.get("person", "").lower()
258-
project = person if person in ("arthur", "sabrina") else "shared"
258+
project = person if person in ("homer", "marge") else "shared"
259259

260260
for fact in classification.get("facts", []):
261261
slug = slugify(fact[:60])
@@ -326,7 +326,7 @@ $ fk knowledge show
326326
327327
$ fk knowledge search "insurance" -d personal
328328
[error] unknown domain: personal
329-
Available domains: shared, arthur, sabrina, calendar
329+
Available domains: shared, homer, marge, calendar
330330
```
331331

332332

@@ -376,7 +376,7 @@ store later means reimplementing the API contract, not rewriting the whole syste
376376

377377
1. Add engram to Kit Bot's MCP server config
378378
2. Kit Bot system prompt: explain available memory tools and when to use them
379-
3. Test: "Kit, remember Sabrina is allergic to peanuts" → `mem_save`
379+
3. Test: "Kit, remember Marge is allergic to peanuts" → `mem_save`
380380
4. Test: "What do we know about insurance?" → `mem_search`
381381
5. Test: "Kit, our insurance went up to EUR 380" → conflict detection + judgment
382382

docs/design/brain/family-memory.md

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ family/memory.git (Forgejo repo, seeded by `memory` stackl
3333
│ │ │ └── YYYY-MM-DD-<slug>-p<paperless_id>.md
3434
│ │ └── _unfiled/
3535
│ │ └── p<paperless_id>.md (when the doc has no usable date)
36-
│ └── correspondents/ (wiki pages for senders: ADAC, Booking.com, …)
36+
│ └── correspondents/ (wiki pages for senders: Duff Insurance, Booking.com, …)
3737
│ └── <slug>.md
3838
3939
├── <entity>/ (one bucket per family member; sender mxid → entity slug)
@@ -74,24 +74,26 @@ family/memory.git (Forgejo repo, seeded by `memory` stackl
7474

7575
```markdown
7676
---
77-
title: ADAC Kfz-Versicherung 2026
77+
type: document
78+
title: Duff Insurance Kfz-Versicherung 2026
7879
date: 2026-03-15
79-
correspondent: ADAC
80+
correspondent: Duff Insurance
8081
document_type: Rechnung
8182
category: Versicherung
8283
persons: [Homer]
8384
tags: [Versicherung, Fahrzeug, "Person: Homer"]
8485
paperless_id: 247
8586
paperless_url: http://docs.local
87+
resource: http://docs.local/documents/247/details
8688
processing: ai_formatted
8789
model: qwen3.5-vl-7b
8890
source: paperless
89-
added: 2026-05-20T14:23:00Z
91+
timestamp: 2026-05-20T14:23:00Z
9092
---
9193

92-
# ADAC Kfz-Versicherung 2026
94+
# Duff Insurance Kfz-Versicherung 2026
9395

94-
> **From:** [[ADAC]] · **About:** [[Homer]]
96+
> **From:** [Duff Insurance](../../../correspondents/duff-insurance.md) · **About:** [Homer](../../../../homer/about.md)
9597
9698
> [!summary]
9799
> Jährliche Erneuerung der Kfz-Vollkasko, Police KFZ-2026-987.
@@ -113,8 +115,9 @@ Notes:
113115
in Obsidian; labeled blockquote in Forgejo). Visually distinct from
114116
the OCR body below.
115117
- `Show Document` is a per-document link composed from `paperless_url`
116-
+ `/documents/<id>/details`; frontmatter `paperless_url` keeps the
117-
base URL so scripts can compose other deep links.
118+
+ `/documents/<id>/details`. The same URL is stamped into the OKF
119+
`resource` field; frontmatter `paperless_url` keeps the base URL so
120+
scripts can compose other deep links.
118121
- Sections inside the callout use `**Bold labels**` instead of `##`
119122
headings — Obsidian renders them as section starts within the callout,
120123
and callouts don't nest H2s cleanly.
@@ -123,19 +126,19 @@ Notes:
123126

124127
```markdown
125128
---
129+
type: bookmark
126130
title: Local-LLM benchmarks roundup
127-
kind: bookmark
128131
date: 2026-05-17
129-
persons: [Arthur]
130-
tags: [local-llms, benchmarks, "Person: Arthur"]
131-
source_uri: https://example.com/llms
132+
persons: [Homer]
133+
tags: [local-llms, benchmarks, "Person: Homer"]
134+
resource: https://example.com/llms
132135
model: qwen3.5-vl-7b
133-
added: 2026-05-17T09:00:00Z
136+
timestamp: 2026-05-17T09:00:00Z
134137
---
135138

136139
# Local-LLM benchmarks roundup
137140

138-
> **About** [[Arthur]]
141+
> **About** [Homer](../../../about.md)
139142
> **Captured** 2026-05-17 · **Kind** bookmark
140143
> **Source** <https://example.com/llms>
141144
@@ -148,8 +151,8 @@ added: 2026-05-17T09:00:00Z
148151
```
149152

150153
Notes:
151-
- `kind: note` keeps the user's pasted body in a collapsed
152-
`> [!quote]- Original paste` callout below the summary. `kind: bookmark`
154+
- `type: note` keeps the user's pasted body in a collapsed
155+
`> [!quote]- Original paste` callout below the summary. `type: bookmark`
153156
has no body — the URL plus the digest IS the entry.
154157
- No "Action items" section on captures. A bookmark to a Reddit thread
155158
is not a todo; pasting links shouldn't flood the system with chores.
@@ -160,14 +163,14 @@ The classifier writes one note per filed document into Paperless's
160163
note slot (FTS-searchable):
161164

162165
```
163-
Jährliche Erneuerung der Kfz-Vollkasko bei ADAC. Police KFZ-2026-987,
166+
Jährliche Erneuerung der Kfz-Vollkasko bei Duff Insurance. Police KFZ-2026-987,
164167
Beitrag EUR 340 jährlich, fällig zum 01.04.
165168
166169
- Versicherungsnummer: KFZ-2026-987
167170
- Beitrag: EUR 340,00
168171
- Fälligkeit: 2026-04-01
169172
170-
ADAC → Homer
173+
Duff Insurance → Homer
171174
172175
<!-- archivist-bot -->
173176
```
@@ -196,7 +199,7 @@ shapes:
196199
{
197200
"source": "docs",
198201
"type": "document.filed",
199-
"summary": "ADAC Kfz-Versicherung 2026 filed (#247)",
202+
"summary": "Duff Insurance Kfz-Versicherung 2026 filed (#247)",
200203
"actor": "@homer:home",
201204
"ts": "2026-05-20T14:23:00Z",
202205
"data": {"paperless_id": 247, "title": "", "topics": [...], ...}
@@ -213,7 +216,7 @@ envelope as a content field:
213216
"type": "m.room.message",
214217
"content": {
215218
"msgtype": "m.text",
216-
"body": "Filed: ADAC Kfz-Versicherung 2026 (#247)…",
219+
"body": "Filed: Duff Insurance Kfz-Versicherung 2026 (#247)…",
217220
"format": "org.matrix.custom.html",
218221
"formatted_body": "<p>…</p>",
219222
"dev.famstack.event": { …envelope… }
@@ -361,7 +364,7 @@ classifier `persons:` list takes precedence.
361364
User replies to a bot's filing message with a correction:
362365

363366
```
364-
[bot] ✅ Filed: ADAC Kfz-Versicherung 2026 (#247) — Versicherung | Homer | …
367+
[bot] ✅ Filed: Duff Insurance Kfz-Versicherung 2026 (#247) — Versicherung | Homer | …
365368
[user reply]: das ist eigentlich Marges Versicherung, nicht Homers
366369
```
367370

docs/design/brain/interaction-patterns.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
> Status: Design note — future direction, no implementation yet
44
> Created: 2026-06-09
5-
> Author: Arthur + Claude
5+
> Author: Homer + Claude
66
> Depends on: [topic-rooms.md](topic-rooms.md) (room-state-as-intent, the seed of this design), [knowledge-architecture.md](knowledge-architecture.md), [wiki-engine.md](wiki-engine.md)
77
88
## Why this exists
@@ -50,7 +50,7 @@ Reactions run in **both directions** — the user reacts to signal intent to the
5050
| 👎 | "Bot, your classification was wrong" — opens a reply-thread correction prompt |
5151
| 📅 | Surface this for the calendar / reminder bot (once it lands) |
5252

53-
A 🔖 on Homer's message means "save this." A 👎 on the bot's `Filed: ADAC camping addendum` means "you got the topic wrong." A 🗑 on the bot's own capture confirmation means "undo." Each binding maps to an existing handler the archivist already implements; the reaction is just a different trigger.
53+
A 🔖 on Homer's message means "save this." A 👎 on the bot's `Filed: Duff Insurance camping addendum` means "you got the topic wrong." A 🗑 on the bot's own capture confirmation means "undo." Each binding maps to an existing handler the archivist already implements; the reaction is just a different trigger.
5454

5555
#### Bot reacts to the user's message to signal processing state
5656

@@ -86,10 +86,10 @@ Bounded intent set (so the prompt stays tight and dispatch stays deterministic):
8686
| Intent | Example | Dispatch |
8787
|---|---|---|
8888
| save | `@archivist save this https://...` | `_handle_capture` |
89-
| forget | `@archivist forget that ADAC stuff` | redaction + tombstone |
89+
| forget | `@archivist forget that Duff Insurance stuff` | redaction + tombstone |
9090
| search | `@archivist what did we note about camping?` | `_handle_search` (existing) |
9191
| reclassify | `@archivist this is actually Marge's, not Homer's` | `_handle_reply_reprocess` (existing) |
92-
| remind | `@archivist remind me about the ADAC renewal in November` | reminder bot when it lands |
92+
| remind | `@archivist remind me about the Duff Insurance renewal in November` | reminder bot when it lands |
9393
| status | `@archivist what have you filed today?` | digest |
9494

9595
A thin LLM pass classifies the mention's intent into one of those slots, then dispatches to the existing handler. The user does not learn a command syntax — they ask naturally; the LLM bridges to the existing surface.
@@ -151,7 +151,7 @@ That alone gives the family a real-feeling per-message knob without ripping out
151151

152152
## Status of this document
153153

154-
A design note, not a prescriptive plan. Captures the direction agreed in the 2026-06-09 session as a marker so future-Arthur and future-Claude do not have to rederive the conclusion. When the first layer ships, this document graduates into a proper design doc — until then, it sits here as the canonical reference for "we know the routing is fragile; here's the direction we are taking when we get to it."
154+
A design note, not a prescriptive plan. Captures the direction agreed in the 2026-06-09 session as a marker so future-Homer and future-Claude do not have to rederive the conclusion. When the first layer ships, this document graduates into a proper design doc — until then, it sits here as the canonical reference for "we know the routing is fragile; here's the direction we are taking when we get to it."
155155

156156
## Related
157157

0 commit comments

Comments
 (0)