← Qnative (provisional) · c4

review-1.md

Review stop 1: the messaging slice

2026-11-11. qnative c4, design c137 Phase 3: the V1 slice of the message channel, built in the brief's five steps on the pipes c2 made. What to look at, the figures, the calls for Mark. The record of each step is in CYCLE.md.

How to try it

  • The inbox on the pilot world. cargo run -p app -- --data synthetic --world pilot, then Messages › Inbox in the sidebar (the count beside it). The open required censure sits first though it is the oldest of the day; a row opens its card; Acknowledge ends the censure and the toast says HQ sees it; the fold at the bottom holds the ended ones. Settings opens the Messages page: the four positions per kind, the tray switch, quiet hours, mutes, the required count, what this build can post, what this app records.
  • The tray. The menu's Inbox item reads "Inbox (4): From HQ: stop using a personal ChatGPT account for work" and the icon carries the count as its title; Off on the tray switch empties both; the inbox still fills.
  • The two flows, without a pointer. QPOINT_SPIKE_DRILL=2 delivers the local enforcement notice two seconds in (synthetic worlds only); QPOINT_SPIKE_CONNECT=2 runs the identity confirmation as if Connect had just finished against hq.example (it asks the OS for alert permission once, which a bundle shows as the system prompt).
  • Through a plane. cargo run -p fixture-plane -- --world pilot --port 47612, then cargo run -p app -- --data plane --plane-url http://127.0.0.1:47612: the ten arrive over HTTP from /api/messages into ~/Library/Application Support/io.qpoint.desktop/inbox.sqlite (QPOINT_INBOX moves it), the new ones delivered, the seen ones adopted as they are. Over --world meridian-day90 the plane holds none, so the app composes the confirmation itself, once; a second launch finds it in the file.
  • The real notification. macOS posts only for a bundle, so scripts/bundle-dev-app.sh wraps the release binary in target/Qpoint-dev.app (ad hoc signed). Run its executable with QPOINT_DATA=synthetic QPOINT_WORLD=pilot: the Messages page then says "allowed" or "not asked yet" with the "Allow notifications" button (asked once; the OS prompt is the OS's), and a drill at Normal posts a banner. priority stays an ordinary notification until a signed build carries the entitlement (call 4).
  • The stories. cargo run -p stories -- --only app-inbox and the other nine (app-inbox-empty, -card, -acknowledged, -expired, -withheld, -drill, -connected, app-messages-settings, -tuned); QPOINT_NOW=2026-11-11T22:30:00Z pins the clock so the captures read the same tomorrow. Thirteen are in design's atlas under thread c4-messaging.

What was built, in one table

PieceWhereState
The bones as types, the ten examples as a fixture, the drift test against bones.mdtypes::messages, fixtures/messages/bones-examples.jsondone; 5 + 2 tests
The inbox store: SQLite beside the settings, §5's transitions, expiry, the required count, a delivery record per messagemessages::store, messages::deliver, messages::clockdone; 11 tests
The OS notification behind one trait; the macOS port with the interruption level per post; the entitlement read from the signaturemessages::notify, notify::macosdone on macOS; Windows and Linux say "not available here"
The inbox page: the lift, the card, the actions, the toast, the honesty line, the foldapp::pages::inboxdone
Messages, the settings pageapp::pages::messages_settingsdone
The tray's count and one line; the sidebar count; a notification click opens the cardapp::tray, app::shell, app::messagingdone
Messages as a resource of the nozzle; the inbox syncs from ittypes::routes::MESSAGES, nozzle, fixture-plane, app::messaging::syncdone; synced once at open and on a world switch
The identity confirmation on Connect; the enforcement notice by drillapp::messaging::connected, ::drilldone; Connect itself is c131's page, not built
Stories, captures, the budgetstories, captures/messaging.json, belowdone

The figures

  • Tests: the workspace's suite passes (types 5, fixtures 7 with the strict drift test, messages 11, nozzle 10, app 11 and the rest); run cargo test --workspace.
  • Stories: 10 new, 13 captures published (thread c4-messaging).
  • Budget: strobe, release builds, c1's recipe (5 s to settle, 60 s recorded, QPOINT_DATA=synthetic QPOINT_WORLD=pilot), interleaved with the tree as it stood before the slice (273ada7, the last commit before it that builds: c5's groundwork commit carried this cycle's Repo::world() ahead of the trait method it calls, so the two commits between do not compile on their own). The readings were taken while this session worked on the same Mac, so they are not the quiet readings c3 took on an idle machine; the two builds were read back to back under the same conditions.
BuildModePrivate memory (strobe)Physical footprint (footprint)RSSCPU, idleWakes/sRecording
273ada7 (before)window, overview62.2 MB62 MB76 MB0.002% of one core (1.20 ms in 60 s)0.83rec_1d0efa
2c01ebf (the slice)window, overview83.3 MB83 MB88 MB2.43% of one core (1456 ms in 60 s)212rec_f10f1b
2c01ebf (the slice)window, Inbox (ten messages)63.5 MB64 MB79 MB0.15% of one core (90.3 ms in 60 s)25.9rec_aba199
273ada7 (before)tray only23.3 MB23 MB47 MB0.003% of one core (1.85 ms in 60 s)0.88rec_25b5b5
2c01ebf (the slice)tray only (four waiting)23.0 MB23 MB48 MB0.01% of one core (3.04 ms in 60 s)0.73rec_d700fd
2c01ebf (the slice)window, Inventory overview (second round)68.5 MB69 MB—0.06% of one core (34.3 ms in 60 s)6.39rec_088645
2c01ebf (the slice)window, Inbox (second round)61.8 MB62 MB—0.02% of one core (12.6 ms in 60 s)2.96rec_fa9be6

Binaries: before 23.9 MB, the slice 24.9 MB (+0.99 MB: the messages crate, its SQLite binding and the notification bindings, the two pages, c5's two pages and c3's stream core together).

  • The inbox at rest costs nothing measurable. The second round read the Inbox at 61.8 MB, 0.02 % of a core and 3 wakes a second, the baseline's overview at 62.2 MB, 0.002 % and 0.8; the first inbox round (63.5 MB, 0.15 %, 26 wakes) was taken while this session was building on the Mac. The Inventory overview on the slice build read 68.5 MB, 0.06 %, 6.4 wakes.
  • The Status landing draws at rest. The slice build opened on its landing, Status (c5's page, on main since 04531db), read 83 MB, 2.43 % of a core and 212 wakes a second for the whole minute, with 1.76 s of CPU by the five-second mark: something on that page asks for frames continuously. It is not this cycle's (the Inbox and the overview on the same binary read quiet) and is handed to c5 by message; it is the one number in this table that is not a rest reading.
  • The tray at rest is 23 MB on both builds, with the inbox holding the pilot world's ten messages and four of them waiting (the count in the icon's title, the Inbox item's line); the record is SQLite in memory for a synthetic world, and nothing polls.
  • The readings were taken while this session worked on the Mac, not under c3's idle-Mac rule; the two builds were read in one session, back to back. strobe's insights found nothing to flag in any recording.

Findings for the specification (design c137)

  1. required_reason is not in bones §1. §6 says the card carries HQ's reason line above the soft ceiling; the field is added here as optional and recorded as drift to resolve in bones.md.
  2. Reply is not an action kind. E6 names "Acknowledge · Reply · See the server"; §4's seven kinds have no reply. Here Reply rides contact-it with its own label.
  3. The ten speak of Acme and MBP-2291 (Dana Whitfield at HQ, Mark Parson), while the worlds are Meridian's (priya-x1, nina-mbp). The fixture is verbatim, as the voice fixtures should be; a recut of the examples onto the Meridian cast is a design task (c137 or c132).
  4. The connected world is not bundled. The fixture names it (nine of the ten) and the seed rule is ready; pilot carries the ten today and the quiet default none. When c131 cuts connected, the inbox follows with no code.
  5. Dismiss has no sender. §4 says dismiss exists only for info and ends it; nobody lists it. The app adds Dismiss on info cards the way it adds Acknowledge when owed.
  6. seen is "opened". A row click opens the card and marks the message seen, so the lift moves it from the new band to the seen band on the next look. Clicking the OS notification does the same.

Calls for Mark

  1. The delivery words. D9 gives three modes (quiet · normal · priority) and the brief adds "off · inbox"; the inventory had four positions (off · inbox · tray · notify). Built as a ladder of five: Off keeps a kind in the inbox and nowhere else; Inbox counts it in the tray (its badge and one line); Quiet and Normal add one notification at passive or active; Priority is reserved to required messages (time-sensitive with the entitlement, else active) and the person's own controls stop at Normal. The defaults map the inventory's: notify → Normal (censures), tray → Inbox (enforcement notices and the rest), inbox → Off (HQ notices). Accept these five words, or rename the second rung "Tray" so "Inbox" can mean the inventory's quiet inbox?
  2. The mailto's it_contact source. qcontrol's configuration has no such field (qconfig was searched); the fixture's E2 carries mailto:it-help@acme.example in its action's target. Proposal: an it_contact string in qcontrol's config file, served by the /api/config route c131 D17 asks for, so a local notice's Contact IT reads it; until then the card says "This machine's configuration names no IT contact. Connect to HQ to reply from here."
  3. The OS crates. macOS: objc2-user-notifications 0.3.2, the bindings GPUI's own platform uses (one copy in the binary), because GPUI's show_system_notification cannot set the interruption level. The store: rusqlite 0.32 linking the system SQLite on macOS and bundling one on Linux and Windows. Time: chrono. Not written, behind the same trait: Windows (tauri-winrt-notification or the windows crate's toasts; needs an AppUserModelID and a Start-menu shortcut, so it waits for packaging, c131 Phase 4) and Linux (notify-rust over zbus with the urgency hint). Choose now, or leave them to packaging?
  4. What the entitlement question needs from a signed build. priority posts time-sensitive only when the process's signature carries com.apple.developer.usernotifications.time-sensitive; the app reads it at start and the Messages page says which. That entitlement is restricted on macOS: the capability must be enabled on the App ID in the Qpoint developer account and the build signed with Developer ID and a provisioning profile that embeds it. An ad hoc bundle (the script) has none, so it proves the port and the prompt, not the break-through. Ask for the capability now, so c131 Phase 4's first signed build answers it.
  5. Sync cadence. The inbox pulls /api/messages once at open and on a world switch; nothing polls. The real plane's stream (or a pull interval) is c134's contract; a periodic pull here is a few lines once the cadence is ruled.
  6. The tray's one line lives in the Inbox menu item ("Inbox (3): subject") and the count is the icon's title; ports §1.2 places the line under the sensor's own state line, which the Status/tray work owns. Keep it in the item until the tray's long form lands?
  7. Pushing. The brief said qnative has no remote and never to push; CLAUDE.md now names origin and says to push fast-forward after a step lands. Nothing was pushed from this cycle; the commits wait for your word.

Ruled by Mark on 2026-11-11

Walked in this session after the stop; each call took the recommended answer. Built the same evening where a ruling asked for code.

#CallRulingWhat followed
1The delivery wordsInbox · Tray · Quiet · Normal, each word saying where the message goes; no position sounds like hiding. Priority stays reserved to required.Built: the ladder renamed in types::messages::Delivery (today's Off is Inbox, today's Inbox is Tray), the hold reasons with it, the settings page's note, the honesty line ("Notices from HQ is set to Inbox"), the guide's map. A settings file or an inbox row that still says off reads as Inbox. Four captures retaken and republished.
2The IT contact's sourceA field in qcontrol's configuration, it_contact (a mailto or URL), served by the /api/config route c131 D17 asks for.Built: the bridge's EffectiveConfig carries it_contact (hand-written until D17's routes are generated); the pilot world's config names mailto:it-help@meridian.dev, the quiet default none. A local notice's Contact IT opens the configuration's contact, never the message's own target (bones §4), and says so plainly when none is named. The ask for qcontrol's engineer: the field in the config file, and /api/config serving it.
3The Windows and Linux portsWith packaging, c131 Phase 4: Windows toasts need the installed app's AppUserModelID and Start-menu shortcut; Linux (notify-rust over D-Bus) comes with it.Nothing to build now; the trait is ready and both platforms say "not available here".
4The time-sensitive entitlementAsk for the capability now, so the first signed build answers it.The ask for whoever holds Qpoint's Apple developer account: enable Time Sensitive Notifications on the App ID (provisionally io.qpoint.desktop; it moves with c0's name) so a Developer ID build's provisioning profile carries com.apple.developer.usernotifications.time-sensitive. The app already reads it from its signature and says which.
5Sync cadenceLeave it to c134. The inbox pulls at open and on a world switch until the plane's push or pull contract is ruled.The pull for local and plane now runs on the background executor (it was a blocking read on the main thread at launch); a synthetic world still reads at once from memory.
6The tray's one lineIn the Inbox item for now; it moves under the sensor's line when the tray's long form lands with the Status work.Nothing to build.
7PushingSettled before the walk by the new rule (push your own commits, fast-forward only).The stop's commits were pushed (6c13512). This evening's (6fceb1c, 4ccf511) went out with c3's Phase 3 when c5 pushed 045eed1..4ccf511 on your word, a fast-forward.

Not built, and why

  • Contact IT as a thread (replies back and forth) and the operator's side: c134's. In local mode the mailto opens the mail app, one way (D13).
  • Acknowledge from the notification: off by ruling (D13). The notification's body opens the card.
  • The Connect page (c131 Phase 2): connected() is wired for it; today a plane-mode launch and QPOINT_SPIKE_CONNECT call it.
  • The OS notification mocked per platform as captures (c137 D8): the macOS one can be seen through the bundle; Windows and Linux have no port yet to capture.
  • The violation tour (c131 D15): the drill is ready for its simulate step; the tour's JSON and its stops come next.
  • A reading on an idle Mac: the readings below were taken on a working machine; repeat c3's quiet recipe before quoting them beside its numbers.

Qpoint Brand Style Guide