Skip to content

feat: add creator workbench release-gate evidence#5846

Draft
rgd451 wants to merge 127 commits into
nexu-io:mainfrom
rgd451:cw-10-release-smoke-evidence
Draft

feat: add creator workbench release-gate evidence#5846
rgd451 wants to merge 127 commits into
nexu-io:mainfrom
rgd451:cw-10-release-smoke-evidence

Conversation

@rgd451

@rgd451 rgd451 commented Jul 18, 2026

Copy link
Copy Markdown

Scope

This draft contains the local Creator Workbench delivery accumulated across CW-01 through CW-10, including CW-10 desktop release smoke evidence. It is intentionally a draft because upstream main has advanced substantially since the local shared base, so this is not a small CW-10-only diff.

CW-10 Highlights

  • Machine-readable G6-G10 release-gate evidence with artifact SHA-256.
  • Windows full smoke checks for content preservation, checksum mismatch, and metadata-unreachable recovery.
  • Release workflow evidence artifacts survive successful cleanup.

Local Validation

  • e2e/tests/release-gates-evidence.test.ts: 29 passed
  • E2E TypeScript typecheck
  • tools/pack/tests/release-workflows.test.ts: 1 passed

CI Limitation

The official Windows full smoke requires the upstream repository's release secrets, signing configuration, and artifact storage. It should be run by an upstream maintainer after reconciling and merging this draft.

No production user data or media was used.

Codex Worker added 30 commits June 30, 2026 18:00
Codex Worker and others added 25 commits July 16, 2026 15:09
- Split TasksView 99-test single file into 5 isolated files (page/creator-content/release/performance/release-schedule, 99 tests total) sharing tasks-view-test-helpers.ts; each file uses jsdom env with afterEach cleanup (cleanup + restore fetch/confirm + restoreAllMocks + useRealTimers) to stop cross-test memory accumulation.
- Fix creator content selector multi-match with findAllByText/getAllByText.
- packaged: extract platform-agnostic isPackagedDataDirAbsolute(value, platform=process.platform) so tests assert behavior explicitly per platform instead of mocking process.platform (which is bound at load on Windows).
- packaged: make desktop-project-root-gate symlink tests capability-aware (skip when directory symlink privilege is unavailable, e.g. Windows without developer mode); non-symlink assertions always run.
- docs: add CW-07B acceptance report.

Red lines honored: no app src/daemon/contracts/dep/lockfile changes, no real API/.od/assets, no merge/push.
Root cause: TasksView's `refresh` useCallback depended on `entryProjects` by
reference identity. When the caller omits the prop, the default `[]` is a fresh
array literal every render, so `refresh` was a new function each render and the
mount effect `useEffect(() => void refresh(), [refresh])` re-ran on every render,
producing an unbounded refresh loop. On the Automations surface this ran in the
background, but switching to the heavy Creator workbench dashboard made the
continuous re-renders peg CPU and never settle, so the dashboard never appeared
(timeout / OOM).

Fix (minimal, app-layer only): read the latest `entryProjects` through a ref and
key the `refresh` callback on a stable `entryProjectKey` (joined project ids)
instead of the array identity. `refresh` now runs once per distinct project set;
surface switches trigger no extra fetch, and project-set changes still re-fetch.

- TasksView.tsx: `entryProjectsRef` + `entryProjectKey`; `refresh` reads
  `entryProjectsRef.current` and depends on `[entryProjectKey]`; 5 internal
  `entryProjects.map` calls use the local `projects` binding.
- TasksView.page.test.tsx: add zero-project surface-switch stability regression
  (default Automations, stable creator-dashboard within 10s, stable switch back,
  bounded fetch count, no "Maximum update depth"). 99 -> 100 TasksView tests.
- docs: CW-07C acceptance report.

Red lines honored: no daemon/contracts/dep/lockfile changes, no real API/.od/
assets, no merge/push.
Add strict, versioned DTOs for the Creator local backup/restore feature
in packages/contracts (creator-backup.ts) and document the research
basis (electron/tauri/AppFlowy/app_backup_restore) in
docs/plans/CW-08-creator-backup-recovery-research.md.

Contracts cover: CreatorBackupManifest, CreatorBackupFile,
CreatorBackupSummary, CreatorBackupValidationResult,
CreatorBackupOperationResult, plus the daemon list/create/validate
request/response and the packaged main-process restore capability
request/response. Restore is intentionally NOT a daemon HTTP route;
it is a packaged desktop capability keyed only by backup id (paths are
always derived server-side). No runtime filesystem logic is added to
the contracts package.

Red lines honored: no daemon/packaged/web source changes here, no
real .od or asset access, no cloud/third-party APIs.
Implement desktop main-process orchestrated restore for Creator backups,
keyed solely by backupId (never by absolute source/target paths). The
orchestration reads the manifest, validates the snapshot, freezes the
daemon, captures a rollback of the live Creator JSON files, stages the
backup files atomically, restarts the daemon, and auto-rolls-back the
live files on any failure.

Changes:
- apps/packaged/src/restore.ts: injectable restore engine (freeze ->
  rollback snapshot -> atomic stage -> restart -> auto-rollback), with a
  production daemon control (graceful shutdown + re-spawn).
- apps/packaged/src/sidecars.ts: extract spawnDaemonSidecar and add
  restartPackagedDaemon for the restore restart path.
- apps/daemon/package.json: expose ./creator-backup subpath (store reads).
- packages/host: add OpenDesignHostCreatorBridge (restoreBackup), validate
  it in isOpenDesignHostBridge, add restoreCreatorBackup helper, keep the
  package independent of @open-design/contracts (mirrored local types).
- apps/desktop: creatorBackup option on DesktopRuntimeOptions and
  DesktopMainOptions, ipcMain.handle("creator:restore-backup") with
  requireMainWindowSender, preload creator bridge (no HTTP restore route).
- apps/packaged/src/index.ts: build the daemon control and supply the
  creatorBackup capability to runDesktopMain.

Tests: 7 packaged restore-engine tests (mock daemonControl + injected store
reads, real fs: success / validation fail / missing / auto-rollback /
path-unsafe), 8 host bridge tests (restoreCreatorBackup + creator
validation). Daemon creator-backup suite remains 20/20 green.
- e2e/lib/vitest/release-gates-evidence.ts: SHA-256 hashing, G6-G10
  summarizer (honest BLOCKED when failure paths unexercised), orchestrator
  merge from spec partial + artifact hashes.
- e2e/scripts/release-smoke.ts: compute artifact SHA-256, write
  release-gates-evidence.json (G10 evidence: version/commit/platform/profile).
- e2e/specs/{win,mac}.spec.ts: emit release-gates-partial.json on real
  platforms for G6-G9 signal collection.
- release-stable.yml / release-preview.yml: scope Cleanup workflow artifacts
  to -release-assets$ so smoke report + evidence survive; upload dedicated
  open-design-*-release-gates-evidence artifacts (if: always()).
- e2e/tests/release-gates-evidence.test.ts: 17 focused tests (green in-sandbox).
CW-10 审核整改闭环:
- P0: G7 不再接受 dataRootPreserved:null 即 PASS;未测量 → BLOCKED,内容发散 → FAIL,
  仅升级前后真实内容指纹一致 → PASS(指纹与遍历序/绝对路径/mtime 无关)。
- P1: Windows full profile 真实执行 G8(checksum-mismatch 回滚)与 G9(metadata 不可达离线启动)
  失败路径,断言旧版本仍健康且 dataRoot 指纹不变;core profile 与 macOS 诚实 BLOCKED(不假称 PASS)。
- P2: byteLengthOf 改 statSync 取大小,不再 readFileSync 整读大文件;SHA-256 仍走流式。
- 新增/更新 29 个聚焦单元测覆盖 G7 未测→BLOCKED、一致→PASS、发散→FAIL、G8/G9 未执行→BLOCKED、
  真实执行成功→PASS、stat 取大小不整读;e2e 类型检查与发布工作流契约测试全绿。
- 验收文档去除 “G7 健康即 PASS / CI 预期 PASS 无失败场景” 表述,记录真实失败路径证据。

无 Co-Authored-By。未 push/merge/rebase/reset/force;未触碰真实 .od/用户/运行目录;未引入 electron-updater。
CW-10 独立验收复核(2026-07-18)发现的 P0:G8(checksum-mismatch)与 G9
(metadata-unreachable)助手各自以坏 metadata URL 重启桌面后,主流程仅把正常
URL 写回 CLI 的 process.env,却未重启桌面。桌面在启动即冻结 OD_UPDATE_METADATA_URL
(独立进程,读取自身 process.env),故运行中的桌面仍持死链/篡改 URL,导致
runPayloadUpdateAcceptance -> waitForDownloadedUpdater 轮询
inspect --update-action download 时 metadata-unreachable 超时、整个 full profile
成功升级路径失败。

修复:恢复 URL 后、成功升级前增加 stop+start,使桌面继承正常 URL;覆盖
payloadFixture 与 updateMetadataUrl 两种来源。同步在验收文档 §10 记录调用链复核
与修复。无 Co-Authored-By。未 push/merge/rebase/reset/force;未触碰真实 .od/用户/
运行目录;未引入 electron-updater;未改 package.json/pnpm-lock.yaml。
@lefarcen
lefarcen requested a review from nettee July 18, 2026 02:55
@lefarcen lefarcen added size/XXL PR changes 1500+ lines risk/high High risk: apps/desktop, daemon, auth, migration, workflows, package deps type/feature New feature needs-design-review Awaiting design review (external UI change); cleared by the Odcrew App applying design-approved labels Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-design-review Awaiting design review (external UI change); cleared by the Odcrew App applying design-approved risk/high High risk: apps/desktop, daemon, auth, migration, workflows, package deps size/XXL PR changes 1500+ lines type/feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants