Developer Mode
The app's developer mode, and the Events page above it. Live (qdash's live viewer, replicated on the sensor's current event schema and improved), Monitor (Kamal's monitor TUI, replicated), Sensor (the data switch as a working control), Config (three modes), Guide (how to hook a live sensor). Developer mode is an extension behind one Cargo feature, so a build can carry none of it; where it is allowed, the person can still turn it off. Events, the curated layer of meaning over the same stream, is an ordinary page.
New in this cycle: The lean build
Why
The two tools a developer uses to watch the sensor work are leaving or locked inside it: the live viewer lives in qdash, which is leaving qcontrol, and the monitor TUI is the sensor's own process in a dev build. This app is where they go. A customer who measures CPU and memory must pay nothing for them, so the cost is measured, the mode can be switched off, and a build can ship without it. Kamal then points the pages at a sensor on his machine, which works only if what the app expects from the sensor is written down feed by feed.
Objective
Done means, phase by phase (design's plan has the detail and a review stop after each):
- Measure and seam. The eager construction of the Dev views fixed; Tools and Components moved behind an extension seam; allowed versus on; lean and full builds read in four states with the README recipe; the four-line burden test applied; the decision written up for a Rust expert's review.
- The Guide, v0, and the stream core. The seven pages in
guide/;typesfor the event envelope and the monitor shapes;subscribeon the nozzle; the scenario model. - Sensor. The source changeable while the app runs; worlds, conditions and streams; attach to this machine or an address, with the ladder;
--check-sensor. - Live. Parity with qdash
/liveby cross-language test vectors, then seven improvements; readings under a stream. - Events. Mark's design, built on the same stream.
- Monitor. Six views on synthetic data; honest gaps on a real sensor; the TUI's keys.
- Config. Manual, Qplane, Endpoint (a starter, fetched once).
- Hand-off. The Guide made final and moved to
docs/dev/; a session on Kamal's machine.
Scope
- Here:
crates/devmode(new: the seven Dev pages, behind the featuredev);crates/nozzle(subscribe, conditions, the runtime swap);crates/types(the event envelope, the monitor shapes);crates/fixtures(stream scripts, more worlds);crates/app(the extension seam: one generic route, one registration line; the Events page);crates/stories(a story per page state);cycles/c3.developer-mode/guide/(the Guide while it is a proposal).
- Read, never changed:
../qcontrol(the live viewer incrates/qdash/ui/app, the monitor TUI incli/src/commands/monitor/ui/terminalonmain). - Out: the feeds themselves, which are asked of the sensor's engineer; the plane's credential exchange; the Status and Connect pages.
Key Changes
- kick-off (2026-11-11): this record and the Guide v0: seven pages written as proposals from two surveys of qcontrol (the live viewer and its backend; the monitor TUI) and this repository at c2's review stop 3. No code. Phase 0 builds on c2's Tour stretch commit (
9d37433). - Phase 0, measure and seam (2026-11-11), at review stop 0 (review-0.md):
- Developer mode is an extension the app does not know about. The protocol is
layer::extension, the registry isapp::extensions, and oneRoute::Ext(path)replaces the two Dev routes. A new crate,crates/devmode, holds Tools and Components and is carried only with--features dev, through onecfginmain.rs. The default build is lean. - Allowed (debug,
--dev,QPOINT_DEV=1, full build only) versus on: a checked item in the tray menu, remembered in the app's first settings file (app::settings). - The eager construction is fixed: Dev pages are built when opened and dropped when left.
scripts/check-lean.shchecks the dependency graph and eight strings, with the full build as its control; CI runs it on three OSes once a remote exists.- The burden test passes on all four lines (line 3 on this Mac; CI not yet run), so B holds.
- Read (strobe, an idle Mac, two rounds):
- Binary: lean 23.2 MB, full 24.3 MB (+1.07 MB).
- At rest: 60–63 MB quiet in every state with no Dev page shown (lean, full not allowed, full on, full turned off), at 0.002–0.006% of a core.
- The Components page shown: 65.0 and 65.3 MB.
- So the lean build buys about a megabyte on disk and nothing measurable at rest; looking at a Dev page costs a few MB.
- Developer mode is an extension the app does not know about. The protocol is
- Phase 1, the stream core (2026-11-11, on Mark's night ruling: Phases 1–3 in sequence, the calls collected at the end of Phase 3; built in
../qnative-c3onc3/phases):- The connection (
crates/nozzle):sseis a WHATWG event-stream parser, incremental, tested in every chunking.streamholdsSubscription, an async channel a page awaits with no timer. Under it,connectspeaks HTTP/1.1 directly to qdash's/api/events/stream, with the web viewer's reconnect schedule, and turns 403 and 503 into honest Refused states with the sensor's own reason;playdrives the synthetic scripts. Dropping a subscription closes its socket within a 250 ms tick.Repo::subscribe()sits on top. The plane says it has no stream. - The scenario model (
nozzle::scenario): world, condition and stream. Six conditions; one per process. - The data model (
crates/types): the envelope and the four Monitor shapes are TypeScript beside the Guide (guide/types/), generated byscripts/ts-to-rust.py --from. Each field is marked read from code (with its qcontrol file and line) or proposed.eventsholds the vocabulary: 14 families, entity ids, severity, and RFC 3339 nanoseconds both ways. - The stream scripts (
fixtures::streams): quiet, coding-session, mcp-heavy and file-storm, written to qevents' payloads as read from code. The full reference is filed inresearch/qevents-payloads.md. - The stream core (
crates/stream, new):ingestports qdash'singestEvent,ingestParseError,sortedEventsandparseRunLog. It is held to the web by cross-language vectors: qdash's own TypeScript, bundled read-only, run over a 615-line corpus with edge lines (scripts/live-vectors.sh). All 615 agree, and so does the sort order. - Guide page 3 is now Live Activity: connection methods, the ladder, the data (read or guessed), the pipeline, the states and six asks. Page 6 records the built scripts.
- 87 workspace tests pass, with no warnings.
- The connection (
- Phase 2, Source (2026-11-11):
- Dev › Source (
crates/devmode/src/source.rs) is the plan's Sensor page, named Source because c5's V1 Sensor sits under This machine. It offers synthetic data (a world, a condition, a stream and its rate) or a real sensor on this machine or at an address. A choice applies at once through the one re-open path and is saved; the next start applies it unless a flag or the environment says otherwise. A story covers each rung, plus synthetic and an address. host(new crate) answers the Rust expert's question 2. It holdsRepoHandle,Generation,repo,generationandreopen, moved out ofapp::router(which re-exports them), and aStoreof saved values the app installs oversettings.json. The extension protocol gains an optionalstarthook.- The condition wrapper (
nozzle::scenario::Conditioned): six conditions, each drawn through the real pipes. - The ladder (
nozzle::ladder): Not found (including a stale lock), Found, Answering, Streaming, Lost and Refused, tested against fake sensors on loopback. - The doctor,
app --check-sensor [--sensor-url …]. Run for real on this Mac, it found a stale lock (pid 54415). Against the seedqdash serveon :7882 it reached Refused with qdash's own 503 sentence. Local::atattaches to an address, and the footer sayssensor at …. The macOS data dir is fixed (com.qpoint.qcontrol).- Guide pages 2, 3 and 6 now say what is built.
- Dev › Source (
- Phase 3, Live Activity (2026-11-11):
- Dev › Live Activity (
crates/devmode/src/live.rs) is qdash's/liveon the sensor's current envelope: a state line, a harnesses row, Events and Tally, a rail of severity, harnesses and families, a virtual table that follows the live edge, a detail pane, retention (5k, 20k or 100k), and file mode (open a JSONL run log; return to live). The page owns its subscription inside a task, so leaving the page ends the feed. - The seven improvements:
- a real pause, with a count of what is new;
- honest states (connecting, live with the rate and the last event's age, reconnecting with the reason, refused, no sensor, ended, filtered to nothing);
stream::buffer: a ring of raw frames, a light head, incremental facets and view, rows on demand;- a tally by process, session or type, beside qdash's own;
- filters for severity, harness and family, process and session, with search over the whole record;
- keys (↑↓ j k, space, t, Esc), milliseconds, clock or ages, and Export JSONL;
stream::maskon the summary, the preview, the JSON and the copy.
- Parity by cross-language vectors, all regenerated byte-identical by
scripts/live-vectors.sh:- ingest and previews: 614 records;
- presence: 99 checkpoints;
- the tally: 63 views and 126 CSVs, byte for byte;
- entity-meta and the projections: filters, counts, trees, chips, rows.
- Four modules were ported by subagents against the vectors. The web quirks are kept, each marked.
- Stories: eight,
app-dev-live*. - Readings under a stream (README Footprint, Guide 07, review-3.md):
- As first built, the page cost 28–34% of a core at 100 and 1,000 events a second, nearly all of it main-thread drawing at about 10 ms per redraw.
- Leaving it returns the app to rest (0.003%, 6 threads).
- The page now gathers arrivals for 250 ms and caches the rows on screen, so it redraws at most 4 times a second, the monitor TUI's cadence. The readings at that rate are owed.
- The recipe is
scripts/footprint/.
- CI: Linux and Windows had failed on the stories crate. c5's cloud session fixed the cause, the crate's manifest (
3725719), along with two Windows failures in c3's ladder and events fixture. Run 17 is green on all three systems, and it came into c3 by merge (78238ff), replacing c3's per-system exclusion. Phase 3's first run, on c5's push of4ccf511, failed on Windows in the projections tests: the corpus read as CRLF counted one line more. Fixed in948a9b5(.gitattributeskeeps the vectors LF; the trim no longer assumes LF), not yet pushed. - The calls: fourteen, in review-3.md (the fourteenth, the lean check after c6's merge, ruled (b) and closed by qpoint-io/qnative#2,
2c435e4).
- Dev › Live Activity (
- The Monitor's shapes reconciled with the bridge (2026-11-12, design c143, on Mark's word): Guide 4 had asked for richer copies of three shapes c131 D17 already names (SensorState without a pid, Resources as totals, LogLine without a target), plus health beside SensorState's
degradedand targets beside EffectiveConfig. Now one ask per route:/api/sensorcarries the Monitor's fields: the monitor's pid, a row per process in its tree with 1 Hz samples behind?samples_since=,healthwith the last error (SensorState'sstateanddegradedare its rollup), and the log'stargetandseqbehind?log_after=./api/config's EffectiveConfig carries the loaded targets, behaviors and include globs.- The Monitor keeps two routes of its own,
/api/monitor/workersand/api/monitor/processes(guide/types/monitor.ts;crates/types/src/monitor.rsregenerated). No dashboard URL: the app already holds the address it reached. - The fields are design's bridge (
app/data/worlds/bridge/types.ts), mirrored incrates/types/src/bridge.rs, all optional, so V1's Sensor page and the bridge files are unchanged. Two tests pin it: absent reads as not served, and each served field lands. Guide pages 3 and 4 say so; question 3 asks whether the sensor samples always or only with a reader.
- The firehose in qdash's grammar (2026-11-13,
f19e679, pushed; design c138): Mark found qdash's/live"cleaner, better color coding, filtering". It was compared against main's/live@8677b44edon this cycle's corpus, run from a read-only checkout on:3031. The Events view now draws as qdash's does:- each type as its family's chip (
family_chip, from main'sfamilyTone); - 44 px zebra rows, with time, line and summary in mono and the summary as
key=valueparts; - a column header;
- qdash's filter card in place of the rail: the search, severity, active filters with Reset, and Harnesses and Events chip rails with counts.
The seven improvements stay. Still open from design c138's Phase 3: the status pill, presence cards, the buffer cluster, the scroll-away pause, direction, the JSON tree, the tally pivots, drag and drop, and the Audit log. They're listed indesign/cycles/c138.developer-mode/live-parity-plan.md. - each type as its family's chip (
Visual record
18 captures — heroes, page slices, and full-page renders. Click to view.
Phase 3 · Live Activity: qdash's /live on the current envelope, improved
2026-11-11· 7 captureslatest






Phase 2 · Dev › Source: where the data comes from, and the ladder
2026-11-11· 6 captures





Phase 0 · developer mode behind the seam, lean by default
2026-11-11· 5 captures



