Updates
The user-facing half of updating the native app: Settings → Updates with the current and new version and release notes, a preference that can make updates invisible, the trace a quiet install leaves, and the difference between the build-partner era (one channel, internal notes) and a later structured rollout (channels, staged percentages, public notes, organisation policy). The low-level update (`qupdate`) exists; engineering calls go to Tyler.
New in this cycle: The update's states, preference and trace, and the two eras of rollout
Why
Every build partner installs the native app, and it will change weekly while the program moves. qcontrol already updates itself: qupdate reads a sidecar JSON CI publishes beside each binary, downloads with a checksum and replaces in place. Nothing of that is visible. There are no states a person can read, no preference, no channels, no release notes, no restart, and no word for "someone else manages this". Mark asked for that half: updates launched from Settings, invisible if the person's preference says so, the current and new version with a link to the notes, and an early era for build partners, who get our internal notes, that looks different from the structured rollout a mature product needs.
The brand's "invisible when working, visible when needed" meets its hardest case here. An update is something we do to the person's machine. Done well it costs them nothing and tells them what changed; done badly it is a restart in the middle of a demo.
Sketch: An update and its states, drawn 2026-11-11 in the design system; Mark's own drawings may replace it.
Objective
Done means: the prior art read and turned into what we copy and refuse; the model (states, preference, trace, feed, two eras) written and drawn; Settings → Updates mocked in the native skin for every state in both eras, with the tray and the trace; a shot program; the story; the calls for Mark with defaults and Tyler's dependencies listed at a review stop. Later, after the rulings: the states as stories in ../qnative, and the feed contract agreed with Tyler.
Scope
- Cycle docs:
cycles/c139.updates/(initial-prompt.md,plan.md,prior-art.md,review-1.md) - Design site:
app/pages/pages/native/settings-updates.vue,app/pages/pages/native/updates-tray.vue, the knobapp/data/c139-updates-mock.tsand what each state saysapp/data/c139-updates-view.ts, the shared knobsapp/composables/useUpdatesMock.ts, the native skin (app/components/native/Window.vue: the rail's Settings item and the footer's trace;Icon.vue: nine glyphs; newTrayMenu.vue), the sketchapp/pages/cycles/design/sketches/c139-updates.vue, the storyapp/data/stories/c139.ts,scripts/shot-programs/c139-updates.jsonand the sketch's entry inc130-sketches-design.json - Sister projects: none changed.
../qnativegets the states as stories in Phase 4;../qcontrol'squpdateis read through c130's research, never changed - Out: updating the self-hosted control plane (c134; an operator updating a server); the organisation's update policy page on the plane (later, with c134); first install and the installer (c131); downgrade
Key Changes
- kick-off (2026-11-11): created from Mark's prompt (
initial-prompt.md, verbatim). c138 was the highest cycle incycles/and on the remote, so this is c139.plan.mdwritten from c130's platform research §5, c137's plan (D9 delivery modes) and inventory (row 24,app-updatedropped), c62's records and the/partner-digestskill: the two binaries, the feed, nine states, the preference, the trace, two eras, seven rules, twelve proposed defaults, three phases after this stop, six dependencies for Tyler. - Phase 0, prior art (2026-11-11):
prior-art.md, written by a research agent in the same session. It covers seven desktop apps' update settings (Zed, VS Code, Firefox, 1Password, Slack, the Claude desktop app and Raycast) and five ways of giving some people a build first (VS Code Insiders, Chrome's channels, TestFlight, staged percentages, B2B early access), each in the same rows, with sixteen questions and a default for each.- The reading backed D1, D2, D5–D8 and D10.
- It found the model stricter than every precedent on five counts: no restart while the window is open, the sensor's sentence, a visible trace, no skip, and one channel source.
- It found the model thinner on seven. Four became D13–D16: the idle-relaunch guard, Ask me first's clock, the age line for an install that stopped updating, and "what to try" with a history that shows failures. The rest went into the plan's later era.
- Linear, Arc and Figma were too thin to table. Some vendor pages were blocked and are cited from search excerpts, marked as such.
- Phase 1, the model (2026-11-11):
plan.md§The shape, drawn as An update and its states with the c130 kit and registered inprogram-sketches.ts. The sketch shows the plumbing (the feed, the updater, the state machine, the surfaces), the path, the three states that leave it, the preference matrix, the trace and the two eras. It is captured asc139-sketch-updates.pngfor the Why and the story's hero, and## The shapesits above. - Phase 2, the mocks (2026-11-11): Settings › Updates and the tray and the trace, in the native skin (c132 medium A).
- Settings › Updates is the app's first Settings page, at the foot of the rail. It has a state card (one sentence, what happens next, the next step) with the versions of the app and qcontrol under it and Copy version info. Below are the preference as three tiles, the channel (Build partners now; Stable or Beta later) and the history with a state. The notes sit in the right column: internal now, drafted from the cycle records with each line's source and "what to try"; public later. The footer carries the trace (
0.2.0 ready,updated). - The data. Every state in both eras is set by a marked knob (
?state= ?pref= ?era= ?sensor=1 ?skip=1), since no world carries update state (c132 D6). qcontrol's version, the harness count and the source line are read from the worlds. One view function (c139-updates-view.ts) gives every surface its words, so the page, the footer and the tray cannot disagree. - Walkable. The buttons step through the states, each followed by a toast as c137 D12 rules.
- The tray page shows the menu on a desktop, the window's footer in the same state, and every state side by side.
- Registered and captured. Both pages are in
page-registry.ts(phasenative, collapsec139-updates).scripts/shot-programs/c139-updates.json(scale: 2,clip: ".native-window") ran here: sixteen captures plus the sketch, filed inpublic/cycles/design/. - The layer. Untouched. A dense
UxToggleCardis flagged for c135.
- Settings › Updates is the app's first Settings page, at the foot of the rail. It has a state card (one sentence, what happens next, the next step) with the versions of the app and qcontrol under it and Copy version info. Below are the preference as three tiles, the channel (Build partners now; Stable or Beta later) and the history with a state. The notes sit in the right column: internal now, drafted from the cycle records with each line's source and "what to try"; public later. The footer carries the trace (
- Phase 3, the story (2026-11-11):
app/data/stories/c139.ts, wired incycle-stories-mock.ts. It records Mark's four asks as his decisions and has five outcomes, with the sketch as the hero and seventeen captures. - Review stop 1 (2026-11-11):
review-1.mdholds eleven calls for Mark, each with a recommended default and the capture that shows it: the preference's default, what invisible means, inline or linked internal notes, skip, who owns the notes, one update or two, when an automatic install may restart, the version string, where Settings lives, the clock and the age line, and the era as data. Tyler's six dependencies (T1–T6) are listed separately, along with what is out of scope (updating the self-hosted plane, c134) and what was and wasn't verified.- Environment. The layer package returned 401 from GitHub Packages in this cloud session, so the site ran against a read-only clone of
q-nuxt-layer0.9.37, withpackage.jsonand the lockfile restored. Nothing went into../qnative; that is Phase 4, after the rulings.
- Environment. The layer package returned 401 from GitHub Packages in this cloud session, so the site ran against a read-only clone of
- review stop 1 walked (2026-11-13): Mark ruled the eleven calls (
review-1.md§Answered). Nine as their defaults (Automatically; a quiet trace; notes inline; no skip; one page, two rows; the guarded idle restart; tag and short SHA; Ask me first's clock and the 60-day line; the era from the feed). Two changed: the release notes are drafted automatically from the commit messages, with room for manual additions (engineering and design now, product later); App Settings is a rail item with a submenu grouping General · Updates · Notifications · Data · Developer (read with design c147: Safety & Security keeps its own Settings, App Settings › Notifications points to it; to confirm). Phase 4 (the native build) and the lab's update to calls 5 and 9 go to cloud sessions; the app couldn't start them from the walking conversation, so their briefs wait incloud-native-prompt.md(qpoint-io/qnative) andcloud-lab-prompt.md(qpoint-io/design), to start under New session → Cloud.
The shape
Documents: the plan · Mark's prompt · prior art · review 1
Drawn as An update and its states on 2026-11-11; the record behind it is plan.md.
The problem. The app will update often, on machines whose owners are watching what it costs them, and the updater we have has no face. Built late, an update becomes a dialog, a restart at the wrong moment or a silent change nobody can explain. And what a build partner should see when the app changes (our internal notes, the cycle trail, the sharp edges fixed) is not what a customer should see once the product rolls out in stages.
The core idea. One page, one state machine, three preferences, two eras. The state machine is the protocol: every state says what is true in one sentence and what happens next. Silent means nothing interrupts, not that nothing is said: a quiet install leaves a trace where the person already looks. The era is data from the feed (the channel, the notes' audience), not a flag in the app, so the structured rollout is the same page reading more fields.
The pieces.
- Nine states: up to date · checking · available · downloading (download, verify, stage) · ready to restart · installed, then what's new · failed · offline · managed elsewhere (a package manager now; the organisation's policy later). One machine per binary: the app and qcontrol, on one page with one Update.
- The preference: Automatically (the default, installed at quit, at restart, or when nobody is looking, under a guard that waits out tours, streams and sessions) · Ask me first (it says how long the update has waited, never prompts) · Manually. Checks always run.
- The trace: the footer's
v0.2.0 · updatedfor seven days, the Updates page leading with what's new, the history, one tray line while an update is ready. No inbox message (c137 row 24 stands), no OS notification, no toast. - The feed: qupdate's sidecar plus
channel,notesandsizenow;rollout,min_versionandpulledlater. - Two eras: now, one channel with internal notes inline and the trail a link away; later, Stable and Beta, staged percentages, public notes and the plane's policy.
- The mocks: Settings → Updates and the tray and the trace in the native skin, rows from the worlds, the update state a marked knob.
The pattern we follow. Modularity is purpose plus protocol: the update's purpose is a current, verified app; its protocol is the nine states; what the notes say and which channels exist are slots the feed fills. Assemblage: the pieces exist (qupdate's sidecar and checksum, c137's quiet mode and its decision to keep updates out of the inbox, the footer that names version and source, the partner digest's sources), and this cycle connects them. Replicate first: the partner era is qupdate's one latest with a face; the later era is drawn but not built.
What stays open. The calls in review-1.md: the preference's default, what silent means, inline or linked internal notes, skip, who owns the notes, one update or two, when an automatic install may restart, the version string, Settings' seat. Tyler's dependencies: signing and notarisation, qupdate or the app's own updater, the feed's new fields, the sensor's update and its gap, knowing a package manager owns the install, restart mechanics. Out of scope: updating the self-hosted control plane (c134), the organisation's policy page.
Visual record
18 captures — heroes, page slices, and full-page renders. Click to view.
Phase 2 · Settings › Updates and the tray in the native skin, every state and both eras
2026-11-11· 16 captureslatest















Sketches — the structures, drawn in the design system
2026-11-10· 2 captures

Artifacts
- initial-prompt.md
- thread: cloud-lab — prompt
- thread: cloud-native — prompt
- initial-prompt.md
- plan.md
- prior-art.md
- review-1.md