feat(desktop): default new profiles to Agent mode - #2426
Conversation
devRickyyy
left a comment
There was a problem hiding this comment.
I did not find a direct backfill or destructive write for already initialized profiles: explicit true, explicit false, and the legacy absent key remain unchanged on the normal upgrade path.
The cross-cutting concern is that fresh-profile initialization is still a client-side GET followed by a full PUT. The SQLite upsert overwrites feature_flags_json and most other preference columns on conflict, so the new default is neither create-only nor atomic. Besides the first-writer inconsistency called out inline, a concurrent full preference writer could have its configuration replaced by Desktop defaults. An authoritative daemon-side initialize-if-absent operation would address both problems.
cefbc70 to
cf6f42f
Compare
Initialize desktop preferences atomically in tuttid so concurrent writers cannot overwrite existing configuration. Preserve explicit and legacy OS modes, reconcile uncertain initialization outcomes, and pass the selected window kind explicitly into startup. Add SQLite, API, recovery, and vertical startup coverage, and document the required native platform acceptance gates. Signed-off-by: man tuo <2428184991@qq.com>
cf6f42f to
7e304f7
Compare
Signed-off-by: man tuo <2428184991@qq.com>
Signed-off-by: man tuo <2428184991@qq.com>
devRickyyy
left a comment
There was a problem hiding this comment.
复查最新提交后补充 3 个问题:两处配置/口径风险,以及一处并发测试覆盖与 PR 描述不一致。
Carry the main process workspace mode into renderer bootstrap state so failed first-run persistence cannot be replaced by an unrelated OS-mode write. Align daemon-created preference rows with the stable desktop update default and prove first-writer-wins behavior with real concurrent SQLite writers. Signed-off-by: man tuo <2428184991@qq.com>
|
CI note for head 4c3a16c: Go Lint and TypeScript Test Shard 3/3 both failed during Set up job before repository commands ran. GitHub could not download pnpm/action-setup after three attempts (429/502/503 from codeload.github.com). Local push-ready validation reached 56/56 after the unrelated rich-text timeout rerun. This contributor token does not have permission to rerun Actions, so a maintainer needs to rerun the failed jobs. |
|
复查当前 head [P2] patch-first 仍会用另一套上下文完成整个 profile 初始化健康启动中,main 会 await preference 初始化后才打开业务窗口,因此 composer/session patch 不会抢在正常初始化之前。但在初始 GET 或 initialize PUT 失败的降级路径中,main 会用内存 fallback 继续开窗口;daemon 恢复后,用户修改 composer defaults 或 local/worktree mode,就可能让 patch 成为第一笔成功写入。 这两个 SQLite patch 路径使用
因此同一个空 profile 在初始化失败后,最终完整配置可能取决于用户先改语言、composer defaults,还是 session launch mode。这个问题不是健康启动主路径,但从当前 recovery 设计和 UI 入口看是可达的。 按本 PR 的最小范围,我更建议:composer/session patch 遇到缺失 preference row 时返回明确的 not-initialized / failed-precondition,让 Desktop 完成初始化后重试。如果产品/API 必须支持 patch-first,则需要明确的 provisional-profile 或真正 canonical initialization contract,不能让局部 patch 静默决定整行其余字段。 [P2] composer patch-first 创建完整行后没有发布完整权威状态
所以 composer patch-first 成功后,DB 可能已经是 initialized/Agent/default row,但当前 main 和 renderer 仍保留启动 fallback 的另一套 snapshot;后续 full write 还可能再次覆盖这些字段。 如果保留 patch-first,建议让 store/service 返回 [P2] 未持久化 fallback 不应写 installed-version alignment marker初始化失败、复读仍不存在时,line 510 仍调用 一个可达结果是:packaged RC 的内存 fallback 为 RC并记录 marker,随后 patch-first 用 daemon 建议补一条垂直回归请把现在分散的 recovery、renderer bootstrap、patch-first 测试串成一个真实序列: 这不是要求本 PR 顺手统一所有 Go/TS defaults;重点是让“缺失记录由谁完成初始化”只有一种可预测语义。另因 Agent mode 会持久化为 |
Make daemon field-specific patches fail closed when the desktop preferences row is missing. Recover through a typed single-flight Desktop initialization path before renderer mutations, gate migration markers on confirmed durability, and cover the failed-startup-to-restart sequence. Signed-off-by: man tuo <2428184991@qq.com>
|
@devRickyyy 感谢复查。最新 head
验证结果:
本次 main merge没有改动上述 26 个修复文件。请基于当前 head |
|
@mt-hub8 這個 PR 翻默認的那一刻目前沒有任何埋點——發布後將無法區分「被默認分配到 Agent 的新用戶」和「自己切到 Agent 的用戶」,首批 cohort 的歸因會永久丟失(我們已在數據上驗證過自選擇會把留存對比污染 +10pp 級)。 我在 #2457 補了分配蓋章事件,建議你直接吸收進本 PR、同一個版本車發布(單獨發會錯過首批 cohort):
git fetch git@github.com:tutti-os/tutti.git agent/workspace-ui-mode-init-analytics
git cherry-pick 58cd1c2d19e536f6e7b4d8728bd2f6ae5c3b2cbe
吸收後我會關掉 #2457。如果你傾向保持本 PR 純淨、讓 #2457 作為 stacked PR 跟在後面合,也行——但請確保兩者進同一個 release,rc 車正在切(v0.2.27-rc.3)。 |
Report settings.workspace_ui_mode_initialized only when initializeIfAbsent actually creates the preference row, carrying workspace_ui_mode from the authoritative stored row. The creation result limits invocation to at most once while delivery remains best-effort. This stamps the assigned default so release cohorts can separate default-assigned Agent users from self-selected users and later escapes reported by settings.workspace_ui_mode_changed. (cherry picked from commit 58cd1c2) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: man tuo <2428184991@qq.com>
|
已按 #2457 的首选路径将埋点提交 本次新增:
验证:
当前新 head 会重新触发 CI 与 External PR Review Gate;请 |
|
Remote CI follow-up for
Could a maintainer please rerun the failed Windows Desktop Alpha job and re-approve the external PR gate for the current head? |
Signed-off-by: man tuo <2428184991@qq.com>
|
Latest-head status (
The only remaining blocker is the external-contributor review gate. Please have |
Summary
tuttidrule: daemon defaults enableworkspace.standaloneAgentMode, andwriteMode: initializeIfAbsentatomically inserts a complete preference row or returns the existing row unchanged.Behavior
initialized: false)truefalseThe ambiguous-write fallback answers three questions in order:
Architecture
PUT /v1/preferences/desktopremains backward compatible: omitted/replacekeeps the existing full-update behavior;initializeIfAbsentperforms the atomic create-only operation.initializeIfAbsent,tuttidapplies its Agent workspace-mode default to the normalized candidate while preserving every other flag. Desktop consumes the daemon's uninitialized response instead of defining a second fresh-mode default.INSERT ... ON CONFLICT DO NOTHING, then returns the authoritative stored row. It does not overwrite another initializer or concurrent preference writer.Verification
falsebeforetuttidenforced its own fresh-mode default.windowKinddelivered to the launch adapter for fresh, explicittrue, explicitfalse, historical-missing, and read-error states.pnpm check:changed -- --base upstream/main --push-ready: passed 18/18 selected lanes; the repository pre-push gate subsequently passed all 56 selected lanes.pnpm --filter @tutti-os/desktop build: passed, including renderer CSS contract verification.cd services/tuttid && go build ./...: passed.{"workspace.standaloneAgentMode":true}, openedview=agent, and retained the selected local project.Latest review follow-up (4c3a16c)
Platform impact and remaining native gates
The preference decision is platform-neutral, but making the Agent-only shell the fresh-profile default changes the native startup path. This macOS execution host cannot run genuine Windows or Linux GUI startup tests. The following are therefore mandatory release acceptance gates, not optional follow-ups, and are recorded in
docs/architecture/desktop-windows.md:The Windows CI build and adapter jobs for the new head are running; they provide build/platform-adapter confidence but do not replace the native GUI acceptance gate.
Checklist