Expand description
Calls screened on a phone (docs/android.md, “Calls”; docs/research/call-screening.md, section 8).
Android asks Sioul about each call, as its “Caller ID & spam app”, and
waits for the answer before the phone rings: the answer must come in
milliseconds, from Java alone (android/…/Calls.java), never from Sioul’s
library. So Sioul writes ahead, in its state folder, a table
(calls/table.json): who each number is (by phones::key), the floors
that always ring, Expecting a call as your devices last said it,
and the coming days cut into frames, each with whether each row of the
people you know rings then (the Calls rows of the matrix of what reaches
you, attention: the times, Free time’s cells, and the layers, today’s
slots of time for you and do-not-disturb from its switch or a focus
session) and whether it is work or admin time; and, from version 2, the
call screening (screening): what becomes of the numbers nobody knows,
apart from the matrix, from do-not-disturb and from every state of yours.
Java decides in this order (version 2): what always rings (an emergency
number or its callback; a day after you call an emergency number); your
blocked numbers, refused; a second call within 15 minutes, which rings;
the people you know, by the frame for now; everyone else by the
screening, its hours and Expecting a call. No table, or past its frames:
it rings. Always through (everywhere::People) is no floor: its people’s
numbers are written as rows of their own (“always-safe”, their own row
read where Always through says “as their list”), never a blocked one:
blocked beats Always through (docs/attention.md, Q3). A table of version 1
(an older Sioul’s, until this one writes its own) is still read in its own
order: “Let every call through” before a second call, then strangers and
hidden numbers by their frame’s rows as everyone else.
A refused call goes to your voicemail. Java writes every incoming call it
screened, declined or let ring (rang), in a file of its own
(calls/held.jsonl); Rust copies each into this phone’s own log,
calls/log/<device>.jsonl (carry_into), which the sharing carries,
sealed, a line at a time, to your other devices (the part “Calls”). Every
device reads every phone’s log (read_logs): the Porch lists the declined
calls calmly, at the next time those callers may reach you, never counted
(lines); a person’s sheet shows their calls of the month (history).
Seen is each device’s own log of lines (calls/seen/<device>.jsonl,
mark_seen), every device’s read together (read_seen): seen on one,
gone from all. A call is kept KEPT_DAYS: each device takes its own lines
out after that (trim_own), and the sharing takes them out everywhere.
Expecting a call (once “Let every call through”, the same press) is
pressed on any device: each device’s own table in do-not-disturb’s switch
file (state/do-not-disturb.toml, shared) carries its last press,
[device.<id>.calls]; the latest press anywhere holds. While it lasts,
numbers nobody knows and hidden numbers ring; never the blocked, an
automated caller, a number that cannot be a caller’s or one whose
verification failed. The phone’s notification writes its press in a file
of its own (calls/through-here.json) that Java reads at once and Rust
carries into the switch (merge_local).
Structs§
- Decision
- What Java answers, and why.
- Device
Part - The calls’ part of one device’s table in the switch’s file.
- Floors
- The numbers that always ring.
- Frame
- A stretch of time and, for each row of the Calls matrix, whether it rings.
- Held
- A call screened, as Java wrote it (Calls.held) and as a phone’s log keeps
it: declined (held, sent to voicemail) or let ring (
rang). The log’s line leaves out what stays on the phone (the number as the network gave it, its presentation) and every empty field (logged). - Incoming
- A call as Java sees it (Calls.decide), what it knows beside the table.
- Layers
- What holds on top of the clock’s times, ahead (docs/attention.md, §1.6):
today’s slots of time for you (
attention::Slots), and do-not-disturb from its switch or a focus session, from, and until when (none: until turned off; the table is written again when it changes). - Line
- One line of the list: a caller, in one context, one day, on one phone.
- Lister
- What the list needs besides the calls.
- Made
- What a table is made of.
- Message
- A voicemail left, as the list says it (
voicemail::Voicemail, linked). - OwnRow
- A row of the calls’ table for the people’s own rows: its name in the
frames (“own-0”), the own rows a number reads in their order
(
porch::Senders::person_rowsof that number: its cards’ first, then the number’s), and who its list makes that number. Numbers that read the same rows with the same list share one. - Prefix
- A prefix on a list, and who a number starting with it is.
- Region
Rules - A country’s way of writing numbers, as Java needs it (
phones::Region). - Seen
- The calls seen, by id.
- Seen
Line - One press of Seen on a device: when (ms), and the calls of its line.
- Table
- What Java reads (Calls.Table). Times are Unix milliseconds.
- Through
- A press of Expecting a call (once “Let every call through”): when (ms, the pressing device’s hybrid clock), on or off, until when (ms; 0: until turned off).
Constants§
- AFTER_
EMERGENCY_ HOURS - Every call rings this many hours after you call an emergency number (research 7.1).
- CALLED
- The numbers this phone called lately, by their key, with when (ms; Java’s,
never shared): kept only while the screening counts them, and only for
the days they count (
prune_called). - DAY_MS 🔒
- A day, in milliseconds.
- DEVICE_
PART 🔒 - The key of the calls’ own part in a device’s table of the switch’s file.
- EMERGENCY
- When this phone last called an emergency number (Java’s).
- FOLDER
- The calls’ folder, in the state folder.
- FRENCH_
OVERSEAS 🔒 - The French plan’s overseas numbers, by the three digits after the 0 (as
phonesreads them). - HELD
- The calls screened, declined or let ring, one JSON line each (Java’s,
this phone’s alone: Rust copies them into its log,
LOG). - KEPT_
DAYS - A call is kept this long (days), on every device: its phone takes it out of its log after that, and the sharing takes it out everywhere.
- LATE_
DAYS - Another device’s line kept this long past
KEPT_DAYS(days) is taken out by any device: its phone, gone for good, never will (trim_others). - LISTED_
DAYS - A call refused stays on the list this long at most (days), seen or not.
- LOG
- The folder of the phones’ logs of the calls they screened, one file per
phone (
<device>.jsonl), written by that phone alone; shared. - REPEAT_
MINUTES - A second call within this many minutes rings (research 7.3).
- ROWS
- The rows a frame says, as Java looks a caller up (version 2): the people you know, and Always through read against each state (“always-neutral”: someone on the list whose own row is neutral; “always-stranger”: someone on the list in none of your address books, known by the list). Numbers nobody knows and hidden numbers are the screening’s. A table of version 1 also said “stranger” and “hidden”.
- SEEN
- The calls seen on the list, as this phone kept them before Seen was
shared: read once into its own seen log, then gone (
adopt_older_seen). - SEEN_
LOG - The folder of the calls marked seen, one file per device, written by that device alone; shared.
- TABLE
- The table Java decides from.
- TABLE_
DAYS - How many days the table’s frames cover, from today’s midnight: it is written again long before, at each change and each step.
- THROUGH_
HERE - This phone’s press of Expecting a call (once “Let every call through”) on the notification (Java’s).
- VERSION
- The table’s shape: Java reads this one and version 1 (another one: every
call rings). Version 2 carries the screening apart (
screening), Expecting a call (expecting), and frames with the people you know only.
Functions§
- adopt_
older_ seen - This phone’s calls seen before Seen was shared (
SEEN): one line of its own seen log, then the older file goes. Nothing to do once it is gone. - always_
numbers - The numbers of the people Always through, each as a row of its own read
against who the number is (
judge: “always-safe”), whole numbers only; never a blocked number: blocked beats Always through. - append_
private 🔒 - Adds lines at the end of a file of this device’s own, made yours alone (0600, in a 0700 folder, on Unix). The caller holds its lock.
- capitalized
- The first letter in capital: a sentence that starts with a context’s words.
- carry_
into - Java’s new calls copied into this phone’s own log (
own), under its lock, read again there: those whose line is not in it yet (by its id), never a blocked caller’s, nor one pastKEPT_DAYS(taken out already, it would come back). Two processes copying at once never write a line twice. Returns how many lines were written. - column_
of 🔒 - The column a moment is said by: a layer that holds, else the time’s (the pause, sleep, Free time, the hours; work when work and admin are both open, or no hours are set).
- content
- The table as written, without its time: two tables that say the same are the same.
- context 🔒
- “while you slept”, “during work”: what the time was, in a few words.
- day_
words 🔒 - “Monday 5 October”, “yesterday”, “today”: a day, as the lines say it before a capital is put to the sentence.
- decide
- Java’s decision (Calls.decide), step for step: the order’s reference, tested here. Outgoing: rings (to an emergency number, Java marks the moment). Incoming, version 2: what always rings (an emergency number, a day after you called one, an older table’s do-not-disturb list); the blocked; for a number nobody knows, what the screening keeps out whatever else (a number never shown as a caller’s, a failed verification, an automated caller); a second call within 15 minutes; the people you know (your lists, your address books, the phone’s contacts, a number you called lately, Always through), by the frame for now, a number called lately beyond its row only while you expect a call; everyone else by the screening: Expecting a call, then what the screening lets ring by itself (off, resting in your work and admin hours, its rule), never where your contacts’ row declines (review of part 2, 19 October 2026: F3, F4, F7, F8). Version 1: the blocked, “Let every call through”, a second call, the frame’s row for everyone. Nothing to decide from: it rings.
- device_
files 🔒 - Every device’s file of a shared folder (
*.jsonl), each with its device’s name, by name. - emergency_
keys - Emergency numbers, crisis lines and callback numbers of every country
Sioul knows (
data/crisis-lines.toml), keyed as each country writes them, and as the person’s country would. - file_
safe 🔒 - A device’s name as a file’s: letters, digits,
-and_. - folder
- The calls’ folder.
- frames
- The frames from
fromtountil, each with whether each row rings then (ROWS): the clock’s own frames (reach::Clock::frames), cut where a layer begins or ends; two in a row that say the same are one. - frames_
with frames, with a row for each person’s own row too (own): whether their call rings then, their row read over their list’s (Attention::decide).- history
- A person’s calls of the last month (
keys, their numbers as Sioul keys them), newest first, from every phone, rang or declined: one sentence each, for their sheet, never a count. Each says the phone only when several phones share their calls. A blocked caller’s never come: their calls never leave their phone. - history_
line 🔒 - “Tuesday 6 October at 23:10, while you slept: declined, sent to voicemail.”, “Today at 06:48, while you slept: it rang. A second call within 15 minutes rings.”
- incoming_
key - A caller ID as Java keys it (Calls.key, the same steps):
phones::keyfor what a caller ID holds (no extension, no “(0)”). The tests check that the two agree. - is_
false 🔒 - is_zero 🔒
- later 🔒
- The later of this phone’s own press and your devices’ latest (by when each was pressed).
- length
- “0:42”: a voicemail’s length.
- line 🔒
- lines
- The list, oldest first: the declined calls not seen yet on any device,
of the last two weeks, whose callers may reach you now; never the blocked;
one line per phone, caller, context and day. A call that rang is never a
line: it is said under the line of the declined calls it followed.
callsare every phone’s (read_logs), oldest first;messagesmaps a call’s id to its voicemail. - local 🔒
- mark_
seen - Calls marked seen on this device: one line in its own seen log under
root, which the sharing carries to the others. Returns the line’s time, to undo it (unmark_seen). - merge_
local - The phone’s own press, from its notification (
through-here.json), carried into its table once: with Java’s stamp, which came after every press the phone knew then. Whether anything changed. - message_
words - What the list says of a voicemail linked to a call.
- older_
than 🔒 - A line older than
daysbeforenow_ms, by itsat; a line that does not read is kept. - own_
file - A device’s own file in one of the calls’ shared folders (
LOG,SEEN_LOG) underroot, the calls’ folder:<folder>/<device>.jsonl, its name in the sharing (a UUID made once). - own_
rows - The people’s own rows for the calls’ table (decision 16; review of part 6,
F2 to F4), number by number, as a text from that number reads them: each
number a person’s row covers (a card’s every one, a
tel:row’s), judged alone (judge_number), the rows it reads (person_rows, those set), one table row per distinct rows and list. A blocked number, or one nobody knows, drops only itself. In the numbers’ order: never a map’s. - part_of
- A device’s calls part; nothing there: none pressed.
- people_
keys - The numbers of the people on the do-not-disturb list, whole numbers only (
People::admits_number). - person_
of 🔒 - A frame’s row: its person, on the Always through list or not.
- phone_
words - The phone a call came to, said on another device: “your phone” when one
phone shares its calls with this device, “your other phone” on a phone
when one other does, else “your phone (GS290)” by its name among your
devices (
phones: each phone’s id with its name; “” for this device’s own). - press
- A press here (ms): stamped after every press known, so that the latest wins everywhere whatever the clocks. Returns its stamp.
- prune_
called - Java’s numbers called lately (
CALLED) pruned to the days that count (days, the table’scalled_days): never more thanscreening::CALLED_DAYS, and none while the screening counts none, the file then gone; gone too when nothing is left or it does not read (review of part 2, 19 October 2026, F5). Java prunes it at each call; this, at each table made, so that nothing stays its days out while no call comes. - rang_
after 🔒 - The first call that rang from the same number after the last of
group, the same day, on any phone: none for a hidden number (two hidden calls cannot be told apart). - rang_
reason 🔒 - Why a call rang when its row alone would not say it: a second call, Expecting a call (once Let every call through), an emergency, the screening off, resting in your work hours or letting such numbers ring, nothing to decide from.
- read_
held - The calls of one file, oldest first; a line that does not read (half written) is passed over.
- read_
json - A small JSON file of Java’s; none when it is not there or does not read.
- read_
lines 🔒 - Every line of a file of JSON lines that reads; a line cut by a crash, or written by a later Sioul in a shape this one does not know, is passed over.
- read_
logs - Every phone’s log under
root(the calls’ folder), each call with its phone (device), oldest first: never a blocked caller’s (their calls never leave their phone), never one kept pastKEPT_DAYSbeforenow_ms(a phone that stopped sharing never takes its own out). - read_
seen - The calls seen on any device: every device’s seen log under
root(the calls’ folder), read together. Seen on one device, gone from the Porch of every device. - rewrite_
lines 🔒 - A file of the calls’ kept but for the lines
dropnames: written beside under a hidden name (yours alone), then put in place, under its lock. Returns how many lines went. - screens_
anywhere - Whether some device screens calls: the switch’s tables say.
- set_
part - A device’s calls part written; a part with nothing to say is taken out.
- set_
screens - This device screens calls, or no longer: written when it changed.
- shown_
number - A key as shown: “01 99 00 12 34” for a number of your own country’s ten-digit plan, else its international form.
- spacing 🔒
- The characters that only space a number out (as
phonesreads them). - spam 🔒
- What the screening keeps out of a number nobody knows whatever else
(
decide, its step 3): a number never shown as a caller’s, a failed verification, an automated caller, each while set to voicemail. - table
- The table, as Java reads it.
- through_
line - Expecting a call in words: “Expecting a call until 15:30: numbers nobody
knows ring.”, “… until you turn it off.”, or after an emergency call,
“Every call rings until tomorrow at 09:31: you called an emergency
number.”; “” otherwise.
throughandemergency_atin ms;whenwords an instant (ms). - through_
of - Expecting a call as your devices say it: the latest press of any (an “on” wins a tie); none when none pressed.
- trim_
others - Another device’s lines kept
LATE_DAYSpast their month taken out here (here: this device): a phone gone for good never takes its own out, and its calls must not stay on your other devices for ever. While it shares, it took them out long before (trim_own), and nothing differs. Returns how many went. - trim_
own - This device’s own lines kept past
KEPT_DAYStaken out of its log and of its seen log underroot(the calls’ folder): the sharing then takes them out on every device. A line that does not read stays. Returns how many went. - trunk_
zero - The country codes whose numbers drop a trunk “0” (
phones’ table). - unmark_
seen - A press of Seen undone: this device’s own line written at
attaken out of its seen log, and so out of every device’s once the sharing carries it. Another device’s Seen of the same calls stays. Whether a line went. - write
- Written beside, then put in place: Java never reads half a table.
- write_
whole 🔒