qnative-brief.md
c147 Phase 5: the brief for qnative
Written: 2026-11-13, at review stop 3 (call 5: brief it now; Mark Peterson's answers amend it). Reader: the qnative session that builds it, as qnative's next cycle (c13 at the time of writing; take the next free number). Status: a brief, not started. Design is the driver (c130); this cycle answers design:c147.
What and why
The native app's Safety & Security section shows this machine's findings: the same record the company's plane keeps (one finding, append-only events, three writers), in the person's words. It replaces c4's message store and Inbox page and keeps c4's notification plumbing, tray and Focus handling (R6). Medium A is built and reviewed three times in design; this cycle is medium B (c132 D1).
Read first
../design/cycles/c147.findings-common-tongue/finding-shape.md: the wire shape (§1 the finding, §2 the event, §3 the kinds by writer, §4 resolutions, §5 the fingerprint, §6 up and down, §6a plane settings andwhy_plain, §8 c137's types mapped).- The rulings:
plan.md§3 (R1–R7) and §5 (Q1–Q7);review-1.md,review-2.md,review-3.md, each §Answered. - Medium A, on
:3000:/pages/native/safety,/pages/native/safety-finding,/pages/native/safety-settings(the person's view);/pages/native/findingsand/pages/native/finding-detail(the copy of the plane's S2 and S1, the operator's words). - The lab's data: the sidecars
../design/app/data/worlds/findings/<world>.json(/api/policies,/api/findings,/api/plane-settings), written by../design/scripts/derive-world-findings.mts; the plane's moves../design/app/data/plane-c147.ts; the person's helpers../design/app/composables/useNativeFindings.ts(personEvent,personStatus,nextStep,fromHq,alsoUnder,NOISE,notificationsFor). - c4's record (
cycles/c4.messaging/) for the plumbing that stays.
The rulings this builds (short)
- Rail: Safety & Security → Findings · Settings (Q1), in place of c4's Messages section.
- The person's view: open findings first under Observed, five columns (severity, the finding, the harness, when, status), no SLA clock; Prevented as one quiet card counting every stop, a line per thing with its days, "It does not count against you"; Resolved; From HQ first when the plane asked something (rulings 9–12, review 2 calls 1, 3).
- A finding: What happened · Why your company's policy covers this (
why_plain) · What you can do (Ask for access, Ask IT, "This was a mistake" as a quiet third action) · From HQ (HQ's words as written, Acknowledge; a suggested training opened in the browser, Q5) · Also under · What happened since · What's recorded. - The person never moves a finding's status (review 1, call 2): their events are notes. The policy closes a finding when the person finishes the training it assigned (review 3, 6a): the person's
training-completedgoes up, the plane'sresolvecomes down. - How much qcontrol says: one control (Quietly · When it matters · Teach me), the default from the plane per team (
/api/plane-settings), the person's choice wins, Quietly with no plane; asked once at first run (review 2, call 6). - Prevented is resolved at birth (Q4), born with
detectandpreventedin the same moment; the day window for prevented, open-while-open for Observed, repeats asrecurred(review 1, call 3). - On a standalone machine the app raises findings itself from the sensor's events (review 3, 6c).
Steps
- Design side, first (one change in the lab): the sidecar's
/api/policiesgains each policy's configuration (its list, detectors, floor or threshold, asgovernance-policy-config.tsholds it), so the Rust detector (3) can reproduce the lab's findings. Ask design's c147 session; it's a small change toderive-world-findings.mts. types::findings, written fromfinding-shape.md:Finding,FindingEvent(from,origin),EventKind(withprevented,recurred,asked-it,asked-access,acknowledged,reported-mistake,training-assigned,follow-up),Resolution(withprevented,training-completed),Policy(withwhy_plain),PlaneSettings. A drift test readsfinding-shape.md(as c4's readsbones.md) and deserialises every sidecar.- The nozzle: routes
/api/policies,/api/findings,/api/plane-settings. Synthetic answers from the bundled sidecars (crates/fixtures/world/findings/<world>.json, copied from design by a sync script, the way the worlds come the other way), in the seat c4's/api/messagesfallback holds now. Plane answers from the plane's API in the same shape; the fixture plane answers from the sidecar. Local answers from (3). - The detector in Rust (6c): a port of the lab's
scenarios/detect.tsand the part ofapplicability()that sets one person's mode, run over the sensor's events (sessions, tool calls, egress, sensitive files, MCP loads) against the local configuration's policies. Its test: for every synthetic world it reproduces the lab's sidecar (ids, outcomes, events, counts). Until the local configuration carries policies (c11, Config File, and design c146), local mode has none and raises none, and says so. - The person's events: a local store for
from: personevents (c4's SQLite store, repurposed), queued in order for the plane when connected, idempotent by event id; nothing they write moves a status. - The pages, with
/native-port, the spec measured from medium A:node scripts/spec-measure.mjs --base http://localhost:3000 --route /pages/native/safety …(andsafety-finding,safety-settings), the window clipped at.native-window. The copy of S2 and S1 is not ported: it was medium A's baseline. - c4 retired (R6): the Inbox page, the Messages settings page and the message store's UI go; the notification trait, the tray, quiet hours and Focus stay. The three positions drive c4's delivery modes: Observed (new, once per finding) notifies at When it matters and Teach me; Prevented (new) at Teach me, without a banner; a follow-up that asks for an acknowledgement at every position; recurrences never. The tray counts only what needs the person (an unacknowledged follow-up).
- Stories and captures: a story per state on every world (fresh: nothing yet; minimal; meridian-day90; pilot with HQ's follow-up and training), the region-text tests, captures filed with
surface: native, wiped against medium A (c132 D7). - The recut (review 1, call 8):
scripts/cut-world.pykeeps the detail of every session with policy events (4 in Meridian, 13 in pilot have counts but no detail), the MCP servers' versions, and the harness's consequential flag; then design re-derives.
Waiting on
- Mark Peterson (
peterson.md): what an auditor needs from a prevented finding, whether "It does not count against you" holds, who reads "This was a mistake", who sets the noise default, a real allow list, the audit line; and his confirmation of Mark's two rulings (a training closes its finding;chatgpt.comis a different provider). His answers amend this brief before step 5. - The lab, for 6a: the prototype's
foldFinding()doesn't close a finding on a completed training yet; design does it with c133's owner.
Out
The Simulation's prevented rows (c149, review 3 call 1); the plane's build (c134); the training's lesson and quiz screens (c133, Q5); email and Slack delivery (HQ's own channels).