Answer the review: mockup data invented throughout, later milestones' scope marked proposed, design 59 says where it is replaced, playbook 10 aligned with 04 and 07

This commit is contained in:
jochen
2026-10-22 19:19:52 +02:00
parent 5d745d04db
commit eddd7ba684
6 changed files with 72 additions and 49 deletions
+2 -1
View File
@@ -826,7 +826,8 @@ and no session (ADR 0278), in its plain sense.
(ADR 0516 §1).
- **promise** — what a mail says someone will do: *you promised*, *waiting on others* or *on its way*, with who and
when (ADR 0516 §1).
- **read later** — the mark of a mail worth reading that asks nothing (ADR 0516 §1).
- **read later** — the flag of a mail worth reading that asks nothing, which a mail of any mark may carry (ADR
0516 §1). Not a *mark*.
- **handled** — what the operator marked done on the operator's list; it changes nothing in the mailbox (ADR 0517
§1).
- **action log** — mail reading's record of every act of the operator on the mail page, never mail text, kept a
+11 -9
View File
@@ -20,7 +20,8 @@ model from the lead's brief. The operator picks; nobody else does.
## Steps
1. **Gather what the page must carry.** Read the as-is of what it replaces and the real shape of its data from the
1. **Gather what the page must carry.** A page whose direction needs research first starts at playbook
[01](01-research.md); this playbook then draws it. Read the as-is of what it replaces and the real shape of its data from the
mesh (how many items, how long a line, what is missing in practice), the operator's complaint in their own
words, and a short survey of how others solve it (a handful of products, one line each on what changes for
the person). Write it into the work folder; nothing goes on the mesh.
@@ -33,13 +34,14 @@ model from the lead's brief. The operator picks; nobody else does.
two, or a change; the next round draws only that. Three rounds without a pick mean something the operator wants
is missing: ask what, before drawing again.
4. **Make the pick the reference.** Copy it into the design's `NN-mockup/`, with every name, address, employer,
mail address and amount of the operator's own replaced by invented ones: hq is public. Say in the design that
mail address, domain, provider and amount of the operator's own replaced by invented ones: hq is public. Say in the design that
the reference is a direction, and link it.
5. **Write what is new as decisions,** each with the operator's Approve where it changes what they see, then the
design and its milestones. The design's acceptance tests end with the operator using the page live.
6. **Hold the build to it.** Playbook [07](07-feature-branches.md)'s review reads the built page against the
reference (a screenshot at each width beside the mockup), and the milestone is done only when the operator has
used the page.
6. **Hold the build to it.** The lead gives playbook [07](07-feature-branches.md)'s reviewer the reference with
the built page, at a phone's and a desktop's width, as part of what the review reads against the issue. The
operator using the page is the milestone's live proof, made before the next milestone starts (playbook
[04](04-build-handoff.md)).
## Bounds
@@ -58,7 +60,7 @@ model from the lead's brief. The operator picks; nobody else does.
## How it is checked
- A to-be design of a page the operator uses links its reference mockup in `NN-mockup/`, and that mockup holds
none of the operator's own names, addresses or amounts (read by the reviewer of the design's pull request).
- The milestone's review report shows the built page beside the reference at a phone's and a desktop's width.
- The design's last acceptance test is the operator using the page, and it is proven before the milestone's
issues are resolved.
none of the operator's own names, addresses, domains, providers or amounts (read by the reviewer of the design's pull request).
- The milestone's review read the built page beside the reference at a phone's and a desktop's width (its
report says so).
- The design's last acceptance test is the operator using the page, proven before the next milestone starts.
+4 -4
View File
@@ -67,8 +67,8 @@ mesh-mail (mail-store, once for the mesh — the control-node)
module claiming it needs `node-notifier` held on the same machine (ADR 0378 §7). It is assigned today to two
machines, the laptop and the workstation (live read of each machine's modules, 2026-10-20); the control-node
and the home server hold no instance of it.
- **`mesh-mail-reader`** is a module of its own (`modules/mesh-mail-reader`), also built from `mesh-mail`'s
source. It claims `mail-reading`, a fourth seat `mesh-mail`'s own manifest declares beside its three mail
- **`mesh-mail-reader`** is a module of its own (`modules/mesh-mail-reader`), with its own Go module and
source (`go.mod`, `cmd/mesh-mail-reader`), importing nothing of `mesh-mail` (`callers.go`). It claims `mail-reading`, a fourth seat `mesh-mail`'s own manifest declares beside its three mail
seats, held once for the mesh (ADR 0459 §1, §2). It is assigned to the same machine as `mesh-mail`, under
its own account, `mesh-mail-reader` (`runs-as`; confirmed live, 2026-10-22). It is covered whole in §8.
- None of the four seats is named `mesh-*`. A caller reaches them by seat (`mail-store.<verb>`,
@@ -146,7 +146,7 @@ mesh-mail (mail-store, once for the mesh — the control-node)
state (`/send-status`), a mail correction (`/mail-correct`) and a reading-lesson undo (`/mail-undo`) — plus
the sign-in callback (`/signed-in`). Every changing form (the send, a correction, an undo) carries a token
bound to the session (`server.go`, `csrf.go`).
- **The accounts page now opens on mail reading, above the classical list** (ADR 0459 §13, ADR 0515 §5, issue
- **The accounts page now opens on mail reading, above the classical list** (ADR 0459 §13, issue
1430, 1523; `accounts.go`). It asks `mail-reading.status` first; not answering at all makes the whole
section say mail reading is unavailable and why, and nothing else here is asked — the classical list below
still renders regardless. Otherwise it shows, in order: the mail that matters (`mail-reading.entries`, mark
@@ -176,7 +176,7 @@ mesh-mail (mail-store, once for the mesh — the control-node)
- **It keeps no database of its own.** Nothing on disk beyond its own settings; it reaches mail only through
`mail-store`'s verbs, calling as `<machine>.mesh-mail-web`, and reads one thing directly besides —
`mesh-mail`'s account bucket, for folders and counts, of an account its own grant already let it ask about
(ADR 0440 §4, §6). Its manifest now also invokes `mail-reading`'s six verbs (ADR 0459 §13, ADR 0515 §5): it
(ADR 0440 §4, §6). Its manifest now also invokes `mail-reading`'s six verbs (ADR 0459 §13): it
reads `entries`, `groups`, `lessons` and `status`, and writes a correction or an undo with `correct` and
`undo` — writes that land in `mail-reading`'s own database, never in anything `mesh-mail-web` keeps itself.
+7 -1
View File
@@ -20,6 +20,8 @@ decisions:
- "ADR 0461"
- "ADR 0462"
- "ADR 0278"
- "ADR 0515"
- "ADR 0518"
---
# 59 — The mail web client
@@ -165,7 +167,7 @@ mail-store (mesh-mail) ── MAIL: mail.<account>.message.added ──▶ mesh-
with no further Approve: it is the signed-in operator's own act. The page lists the reading lessons, undoes one
(later mail reading only), and shows reading lessons per 100 read mails per week, which answers whether mail
reading learns the operator's way.
- **The page.** Above the classical list it shows the mail that matters at the top, the mail groups, and the scam
- **The page** (replaced by design [63](63-the-mail-web-ui-with-mail-reading-and-owly.md)'s operator's list, ADR 0515 §5). Above the classical list it shows the mail that matters at the top, the mail groups, and the scam
warnings in a place of their own, each with why; the classical list (accounts, folders, search, one mail) stays
and always opens. `mesh-mail-web` reads these through `mail-reading`'s verbs and still keeps no mail state
(ADR 0378 §5 and ADR 0440 §4 as ADR 0459 §13 changes them); it writes the operator's corrections with
@@ -195,6 +197,10 @@ mail-store (mesh-mail) ── MAIL: mail.<account>.message.added ──▶ mesh-
## 8. The mail conversation (ADR 0462)
**Replaced by design [63](63-the-mail-web-ui-with-mail-reading-and-owly.md):** Owly answers mail questions through
mail reading before threads exist (ADR 0518, changing ADR 0462 §6); the conversation below is what Owly moves onto
once threads exist.
A mail conversation is a thread (ADR 0383), run by the thread handler (ADR 0384), with a mail context: the framing
that a mail is data, the tools `mail_search` and `mail_read` only, under a caller of the thread's own named in `grants`
(ADR 0472 §4; issue 1419), the operator's real senders and folder names, and the reading lessons. The operator writes a mail
File diff suppressed because one or more lines are too long
@@ -16,6 +16,8 @@ decisions:
- "ADR 0472"
- "ADR 0378"
- "ADR 0278"
- "ADR 0359"
- "ADR 0361"
---
# 63 — The mail web UI with mail reading and Owly
@@ -30,8 +32,8 @@ reading and Owly judge better over time. The classical list stays one click away
The page has no name of its own: it is `mesh-mail-web`'s page, the mail page. Its reference is the mockup the
operator picked on 2026-10-22, kept beside this design as [`63-mockup/mail-page.html`](63-mockup/mail-page.html), a
direction and not a pixel specification; its mail is invented, and the names, addresses and amounts in it are
not the operator's.
direction and not a pixel specification; its mail is invented, and no name, address, employer, domain, provider
or amount in it is the operator's.
## 1. What it builds on
@@ -42,9 +44,13 @@ lessons. What runs today is the as-is [18](../00-as-is/18-the-mail-modules.md).
unusable on 2026-10-22: it shows mail groups over a classical list, so the operator still reads each mail to know
what it asks.
This design replaces design 59's milestone 4 (the mail conversation on a thread): Owly answers before threads
exist (ADR 0518) and moves onto a thread once they do. Design 59 keeps its own last steps (test 13 live, issue
1418, and Betterbird's removal, issue 806).
This design replaces design 59's milestone 4 (the mail conversation on a thread) and its page of mail groups:
Owly answers before threads exist (ADR 0518) and moves onto a thread once they do, and the page opens on the
operator's list (ADR 0515 §5). It is a design of its own, not an amendment of design 59, by the operator's choice
on 2026-10-22: design 59 is the mail web client and mail reading as first built and closes with its own last steps
(test 13 live, issue 1418, and Betterbird's removal, issue 806); this one is the page rebuilt from a visual design
(playbook [10](../../00-META/process/10-visual-design.md)), in six milestones of its own. Design 59 says where it is
replaced.
## 2. The operator's list (ADR 0515, ADR 0516)
@@ -52,19 +58,19 @@ exist (ADR 0518) and moves onto a thread once they do. Design 59 keeps its own l
at most 3 promises (*you promised*, *waiting on others*, *on its way*, with who and when) and whether the mail is
*read later*. Each line is the model's own sentence, at most 120 characters, and never quotes the mail. A batch
holds at most 6 mails, so its larger answer stays within 40 s (ADR 0516).
- **The page opens on the list.** A greeting says what mail signals told the operator's phone today; then
- **The page opens on the operator's list.** A greeting says what mail signals told the operator today; then
*today*, *this week* and *later* (tasks by their due date), *you promised*, *waiting on others*, *on its way*,
*good to know*, *read later*, *handled today* with undo, and the scam warnings in their own place (ADR 0515 §1).
- **Modes choose accounts.** *Work*, *Personal* and *Everything* each show the accounts `mesh-mail-web`'s setting
`modes` names (ADR 0515 §4).
- **Phone first.** One column on a phone; a wide screen adds the reading pane, and Owly beside the list (ADR 0515
- **Phone first.** One column on a phone; a wide screen adds the reading pane, and Owly beside the operator's list (ADR 0515
§2, §3).
- **All mail is the classical list.** Accounts, folders, search and one mail stay a view the operator can always
open; a correction of mail reading is made from the reading pane (ADR 0515 §5).
- **One script and one stylesheet from its own origin.** The page stays rendered on the server; the script makes
handling, undo and Owly work without a reload and talks only to the page's own origin. A mail's body stays
escaped text, and an attachment stays a download until milestone 2's decision (ADR 0515 §6).
- **The list starts full.** After the delivery, mail reading reads the last 14 days of inbox mail once more
- **The operator's list starts full.** After the delivery, mail reading reads the last 14 days of inbox mail once more
(ADR 0516 §5).
## 3. Handling and the action log (ADR 0517)
@@ -86,18 +92,21 @@ exist (ADR 0518) and moves onto a thread once they do. Design 59 keeps its own l
answers from those mails and names only mails it was given. A question the mails do not answer is answered so.
- **On another node.** Owly's judgements run on the node `ask-node` names (the workstation by default), never on
the node of the batches and the issue tracker, so ADR 0459 §15's spacing holds unchanged. An answer takes up to
about 90 s; the page says what Owly is doing meanwhile.
about 90 s, 130 s behind the morning briefing; the page shows how long Owly has been waiting.
- **The morning briefing** is one judgement a day from the last 7 days' mail entries, read aloud by the browser's
own speech on the operator's click.
- **Nothing of the conversation is kept** but the question, in the action log. A follow-up is answered fresh until
Owly moves onto a thread (issue 880, then issue 1419 for the thread's caller).
- **On the page:** Owly is a panel beside the list on a wide screen and a sheet on a phone, with suggestion chips
for the questions the list makes likely.
- **On the page:** Owly is a panel beside the operator's list on a wide screen and a sheet on a phone, with suggestion
chips for the questions the operator's list makes likely.
## 5. Owly writes (milestone 4)
**Proposed scope, not yet decided.** This section is what the mockup shows; its decision is written in
milestone 4's prepare step, before any of it is built, and the section is then rewritten to it.
Owly offers three short reply options for a mail that asks a question, a draft in the mail's own language, a new
mail from a sentence ("mail Marie that I'll pick the photos tomorrow"), a nudge for a promise the operator waits
mail from a sentence ("mail Lena that I'll pick the photos tomorrow"), a nudge for a promise the operator waits
on, and an answer to an invitation. Every one is the operator's to change, and goes out only through `mail_send`
on the operator's Approve on Telegram (ADR 0440 §6, ADR 0361 §2). Drafting is outside every decision so far (ADR
0462 §7 leaves it to issue 1259), and a reply needs `In-Reply-To` and cc (issue 1257): the decision is written in
@@ -112,15 +121,19 @@ milestone 4's prepare step, tracked by issue 1864.
the decision; `mesh-mail-web` then calls `mail-store`'s new verb. *Not now* keeps a sender quiet for 30 days.
- **mail-store's writes:** `archive`, `report`, `restore` (the same day's undo) and `unsubscribe`, by the mail's own
one-click way (RFC 8058, to a public address only) or as a mail send on the operator's Approve. `mesh-mail`
answers them only for the mail web client, which calls them only from the page's Approve form, so nothing else
on the mesh can change the mailbox. Flag, delete and draft stay with issue 730.
- **Teaching in the chat.** "Stop telling me about Strava" becomes a reading lesson, shown under *Owly learned*
with an undo; *remind me tomorrow* and the read-later feed come with it, and the action log's counts reach the
batches. Whether a lesson taught in words needs more than ADR 0459 §8 decides is settled in milestone 5's
prepare step, tracked by issue 1866.
answers them only for the mail web client, which calls them only from the page's Approve and undo forms, so nothing
else on the mesh can change the mailbox; an undo writes an *undone* line through `decide`. Flag, delete and draft stay with issue 730.
- **The action log's counts reach the batches** and Owly's questions, in a part of their own (ADR 0517 §6 to §8).
- **Teaching in the chat (proposed scope, not yet decided).** "Stop telling me about Strava" becomes a reading
lesson, shown under *Owly learned* with an undo. Whether a lesson taught in words needs more than ADR 0459 §8
decides is settled in milestone 5's prepare step, tracked by issue 1866, before it is built. *Remind me tomorrow*
and *read later* are milestone 1's (ADR 0516, ADR 0517).
## 7. Fast on the desktop (milestone 6)
**Proposed scope, not yet decided:** its decision is written in milestone 6's prepare step, tracked by issue
1867, before it is built.
Keyboard shortcuts (`j` and `k` move, `x` ticks, `r` opens the reply options, `/` jumps to Owly, `?` lists them)
and bulk actions (tick several, handle or archive them at once, each archive still on the approval inbox's
Approve). Tracked by issue 1867.
@@ -144,7 +157,7 @@ Approve). Tracked by issue 1867.
followed by the next batch (ADR 0516 §4).
3. After the delivery the last 14 days of inbox mail are read once, and a restart does not read them again
(ADR 0516 §5).
4. The mail page opens on the list: the greeting with today's mail signals, the sections in their order, scam
4. The mail page opens on the operator's list: the greeting with today's mail signals, the sections in their order, scam
warnings in their own place, the modes from `modes`, and *All mail* opening the classical list (ADR 0515).
5. Handling a task moves it to *handled today*, undo returns it, remind hides it until the next day, and each act
leaves one line in `actions` with no mail text; a line older than 365 days is removed (ADR 0517).
@@ -152,45 +165,46 @@ Approve). Tracked by issue 1867.
`connect-src 'self'`; a mail body with `<script>` and a remote image is shown as text (ADR 0515 §6).
7. Tests 1, 2, 4 and 5 run in one integration test that starts `mesh-mail-reader` and `mesh-mail-web` whole
against the real bus and store, with a fixed judgement (issue 1860).
8. Live: the operator uses the list on the phone and on the desktop for a day.
9. (Milestone 2.) A photo, a PDF's pages, an invitation, a sheet and a zip's list open in place, as its decision
8. Live: the operator uses the operator's list on the phone and on the desktop for a day.
9. (Milestone 2, proposed until its decision.) A photo, a PDF's pages, an invitation, a sheet and a zip's contents open in place, as its decision
says (issue 1861).
10. (Milestone 3.) `ask` answers naming only mails it was given, says so when nothing answers, never judges on the
batches' node, and records the question with no answer text; the morning briefing is one judgement a day from
the entries alone (ADR 0518).
11. (Milestone 3.) Live: the operator asks three questions on the phone and the desktop, and each answer names
real mails.
12. (Milestone 4.) A reply option, a draft and a nudge each reach the operator's Approve on Telegram, and nothing
12. (Milestone 4, proposed until its decision.) A reply option, a draft and a nudge each reach the operator's Approve on Telegram, and nothing
is sent without it (issue 1864).
13. (Milestone 5.) A suggestion appears in the approval inbox; Approve archives the mail, undo restores it,
*Not now* is recorded and not suggested again for 30 days; a one-click unsubscribe refuses a private address;
`mesh-mail-reader` invokes no write verb (ADR 0519).
14. (Milestone 5.) The per-sender counts reach a batch's question within 4 KiB, after the whole of the reading
lessons (ADR 0517 §6); a lesson taught in the chat changes the next batch and is undone from *Owly learned*.
15. (Milestone 6.) Each shortcut does what section 7 says, and a bulk handle of five tasks is five lines in the
14. (Milestone 5.) The per-sender counts reach a batch's question in a part of their own of at most 4 KiB, the
batch's senders first, and the reading lessons keep their 12 KiB (ADR 0517 §6); a lesson taught in the chat
changes the next batch and is undone from *Owly learned* (proposed until its decision).
15. (Milestone 6, proposed until its decision.) Each shortcut does what section 7 says, and a bulk handle of five tasks is five lines in the
action log.
## 10. Milestones
| # | Outcome, in one sentence | Proves | Repositories and their parts | Depends on |
|---|---|---|---|---|
| 1 | The operator opens the mail page on the phone or the desktop and sees what needs them, ticks it off, undoes it, and switches between Work and Personal | tests 1 to 8 | mesh-catalog: `mesh-mail-reader`'s tasks, promises and read later (1857), handling and the action log (1858); `mesh-mail-web`'s list (1859, with 1850); the integration test (1860); one entry per message (1849), the health's first state (1580) | — |
| 1 | The operator opens the mail page on the phone or the desktop and sees what needs them, ticks it off, undoes it, and switches between Work and Personal | tests 1 to 8 | mesh-catalog: `mesh-mail-reader`'s tasks, promises and read later (1857), handling and the action log (1858); `mesh-mail-web`'s operator's list (1859, with 1850); the integration test (1860); one entry per message (1849), the health's first state (1580) | — |
| 2 | Photos, PDFs, invitations, sheets and zips open in place on the mail page | test 9 | mesh-catalog: `mesh-mail`'s previews and `mesh-mail-web`'s viewer (1861), after its decision | 1 |
| 3 | The operator asks Owly about their mail and hears a morning briefing | tests 10, 11 | mesh-catalog: `mail_search` made fit (1433); `mail-reading`'s `ask` (1862); Owly on the page (1863) | 1 |
| 4 | Owly writes reply options, drafts, new mail and nudges, each sent on the operator's Approve | test 12 | mesh-catalog: drafting and replies (1864), after its decision | 3 |
| 5 | Owly suggests tidying into an approval inbox, and learns from what the operator teaches and does | tests 13, 14 | mesh-catalog: `mail-store`'s writes and the approval inbox (1865, answering 730 for its four verbs); teaching, reminders, read later and the counts (1866) | 3 |
| 6 | On the desktop the operator works the list from the keyboard and handles several items at once | test 15 | mesh-catalog: shortcuts and bulk actions (1867) | 1 |
| 6 | On the desktop the operator works the operator's list from the keyboard and handles several items at once | test 15 | mesh-catalog: shortcuts and bulk actions (1867) | 1 |
**Milestones 1 to 6 and their issues, confirmed by the operator on 2026-10-22.** Each milestone is one release of
`mesh-catalog` (playbook [07](../../00-META/process/07-feature-branches.md)), built one at a time, the smallest useful
one first. Their issues, in their order (each depends on the one before unless said):
- Milestone 1: 1857 (tasks, promises, read later), 1858 (handling and the action log; after 1857), 1859 (the list
- Milestone 1: 1857 (tasks, promises, read later), 1858 (handling and the action log; after 1857), 1859 (the operator's list
on the page, with 1850; after 1858), 1860 (the integration test; after 1859); 1849 and 1580 depend on none.
- Milestone 2: 1861 (a decision first, ADR 0440 §5).
- Milestone 3: 1433 (depends on none), 1862 (`ask`; after 1857), 1863 (Owly on the page; after 1862 and 1859).
- Milestone 4: 1864 (a decision first; after 1863).
- Milestone 5: 1865 (after 1863; answers 730 for archive, report, restore and unsubscribe), 1866 (after 1858 and
- Milestone 5: 1865 (after 1863; answers 730 for archive, report, restore and unsubscribe), 1866 (after 1857, 1858 and
1863).
- Milestone 6: 1867 (after 1859).