← Qnative (provisional) · c13

initial-prompt.md

c13. Safety & Security: Findings

From the design c147 session (2026-11-13, night), on Mark's word "continue c147 to qnative": build c147's Phase 5 here as qnative's next cycle, every step; Mark Peterson's answers (../design/cycles/c147.findings-common-tongue/peterson.md) amend it later. The brief is design's qnative-brief.md; the session's instructions, verbatim:

Build design c147's Phase 5 in the native app at /Users/mark/web/qpoint/qnative (Rust, GPUI): replace c4's Messages section (Inbox, Messages settings) with Safety & Security → Findings · Settings, as qnative's next cycle. Mark said to go ahead ("continue c147 to qnative"), so build every step; Mark Peterson's answers (peterson.md) will amend it later.

The steps, from the brief: 0. Design side. In scripts/derive-world-findings.mts, add each policy's configuration (its list entries, detectors, floor or threshold, as governance-policy-config.ts holds it per policy) to each /api/policies item as config. Re-run npx tsx scripts/derive-world-findings.mts. Commit only that script and app/data/worlds/findings/*.json in design, with message c147: the sidecar carries each policy's configuration (Phase 5 step 0).

  1. types::findings, from finding-shape.md, with a drift test that deserialises every sidecar and checks the event kinds and resolutions against finding-shape.md's tables, as c4's test reads bones.md.
  2. The nozzle. Add the routes /api/policies, /api/findings and /api/plane-settings to types::routes. Synthetic answers from bundled sidecars: copy them to crates/fixtures/world/findings/, and add a small sync script mirroring design's scripts/sync-worlds.sh in reverse. Plane answers from the plane in the same shape, with the fixture plane answering from the sidecar. Local answers from step 3.
  3. The detector in Rust, for local mode (review 3, call 6c). Port app/data/scenarios/detect.ts plus the part of applicability() that gives one person's mode. Its test: over each synthetic world's sensor data, it reproduces the lab's sidecar findings (ids via the fingerprint, outcomes, events, recurrence counts). If an exact match proves impossible for a stated reason, record the difference in the cycle and test what does match. The local configuration has no policies yet (qnative c11, Config File), so local mode raises none and says so.
  4. The person's events (asked-it, asked-access, acknowledged, reported-mistake). Store them locally (repurpose c4's SQLite store), queued for the plane and idempotent by id. They never move a status.
  5. The pages via /native-port:
    • Findings: From HQ first; Observed in five columns with no SLA; Prevented as one quiet card with a count and a line per thing; Resolved; the first-run noise card.
    • A finding: What happened; Why your company's policy covers this (why_plain); From HQ, with Acknowledge and the training link; What you can do (Ask for access, Ask IT, and "This was a mistake" as a quiet text action); Also under; What happened since; What's recorded.
    • Settings: the three positions, with the company's default from /api/plane-settings; what each position would announce; the kinds; the tray.
    • Use the person's words exactly as medium A has them. They are voice-checked; don't rewrite them. Use the rail Safety & Security → Findings · Settings.
  6. Retire c4's UI. The Inbox page, the Messages settings page and the message store's UI go. The OS notification trait, the tray, quiet hours and Focus stay. The noise positions drive the delivery modes:
    • a new Observed finding notifies at When it matters and Teach me;
    • a new Prevented finding notifies at Teach me, with no banner;
    • a follow-up that asks for an acknowledgement notifies at every position;
    • recurrences never notify;
    • the tray counts only unacknowledged follow-ups. Keep cargo test green; remove or rewrite the c4 stories and tests that the retirement obsoletes, and say which.
  7. Stories and captures. Add a story per state on every world (fresh, minimal, meridian-day90, pilot), with region-text tests. Capture with design's native capture mode (npm run shots -- --native <program.json> from design), filed with surface: native.
  8. The recut is optional. If there's time, extend scripts/cut-world.py to keep the detail of sessions with policy events; otherwise leave it as an open item.

A course correction from the coordinator, mid-build (verbatim):

Before you retire c4's Inbox: qnative c9 (Trainings, 2026-11-12) already put the four published trainings in the app (crates/app/src/pages/training.rs), launched from the Inbox ("← Inbox" / "Back to the inbox" buttons, and the training-assignment messages). Don't break them:

  • Keep training.rs and its route.
  • Make the finding's "Your company suggested a short training" card open the in-app training when c9 has it for that training id (T-MCP-1 is among the four). Fall back to the browser link only when it doesn't.
  • Change the training page's back button to return to the finding ("← Findings", or the finding it came from).
  • Record in the cycle that this departs from c147 Q5 ("the lesson and quiz stay out of the native V1"), because c9 shipped them for a demo. That's a call for Mark, so list it as open, not decided. Also: qnative c7 (Web Rail) has an open PR that restyles the rail like the web app's (uppercase section headers, no icons). Build the Safety & Security section in main's current rail style, and note that c7's restyle will need to cover it.

Captured: 2026-11-13 — the c147 Phase 5 executor, from the design session's brief.

Qpoint Brand Style Guide