mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 10:45:59 -10:00
studio
11
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9a999f7b7b |
docs: port the retired-Wails wording cleanup to studio
Wails stopped being the desktop shell when the Electron shell landed, but seven places on `studio` still describe it in the present tense. Six of them were already fixed on `main-v2` by #10018; they only need the same edit carried over here. - `CHECKPOINTS`: the desktop rewind control calls `controller.Rewind` over the desktop host protocol, not the Wails binding. - `TASK_CONTRACT`: the constraint keeps the desktop host JSON contract intact. - `RECOVERY`: `doctor` inspects install problems without loading the desktop shell, and macOS keeps LaunchServices launching the desktop app bundle. - `DESKTOP_CRASH_DIAGNOSTICS_RUNBOOK`: the budget is pre-shell work, and report/metric persistence runs after shell startup. - `SESSION_MEMORY_RETRIEVAL`: the example project file no longer points at `desktop/frontend/wailsjs/`, which went away with the Wails shell. Studio commits its generated files under `internal/ext/extension/protocol/`. - `REASONIX.md`: the frontends behind `control.Controller` are the chat TUI, HTTP/SSE serve and the Electron desktop. - `issue-auto-label`: the classifier prompt no longer tells the model the desktop app is Wails. |
||
|
|
7e1e5a9d07 |
fix(update): self-heal stuck pending updates and add discard action
Problem In-app updates could permanently fail after a probationary transaction never received startup health confirmation. Version strings with and without a leading "v" skipped health capture, so AwaitingHealth blocked every later update while the product was already usable. Root cause Health identity capture and MarkUpdateHealthy compared versions with exact string equality. Missed post-DOM health commits left durable pending-update.json markers with no automatic retirement path and no user-facing abandon action. Fix - Normalize version comparison for pending-update health paths. - Auto-commit stale probationary updates after 24h when install evidence still holds. - Re-attempt health commit before install; expose AbandonPendingUpdate with banner/settings "Discard previous update". - Document in-app update recovery steps in RECOVERY docs. Verification - go test ./internal/repair/ - go test . -run TestCapturePendingUpdateHealth (desktop) - tsx desktop/frontend/src/__tests__/updater-shared-state.test.tsx |
||
|
|
f3e38181c5 |
fix(desktop): recover interrupted update transactions
Problem: - macOS updates could launch the replacement bundle without ever committing startup health, permanently blocking later updates. - Legacy WebKit could reject the Markdown chunk, and native installers hid layout activation failures. Root cause: - The visible-window lifecycle no longer called the exact update health commit, legacy app-bundle debris had no transaction-bound retirement path, local-path regexes used lookbehind, and installer/helper handshakes exposed only generic failures. Fix: - Commit only the startup-captured update identity and safely archive unrecoverable legacy app-bundle transactions. - Remove RegExp lookbehind, return structured macOS handoff errors, surface Windows activator output, and mark the localized NSIS script as UTF-8. - Document the signed overwrite-install recovery path in English and Chinese. Verification: - go test ./... - cd desktop && go test ./... - cd desktop/frontend && pnpm test:all && pnpm build - go test -race ./internal/repair -run TestArchiveSupersededPending - Native macOS arm64 Wails build and Parallels Windows 11 arm64 NSIS install/activation tests |
||
|
|
79449ef801 |
feat(desktop): versioned helper activation, drop Guard, NSIS dual layout
Problem:
The Windows update helper still published a flat six-member release unit with
Guard health recovery. The Guard recovery product remained as a first-class
binary and packaging still installed Guard as the permanent entry point.
Root cause:
Post-stage publish was hard-wired to flat InstallRoot members and pending
receipt recording. Packaging and docs still treated reasonix-guard as the
launcher/recovery surface.
Fix:
- Prefer versioned-v1 activation from staged NSIS payloads: write
versions/<ver>/{desktop,cli,helper}, swap current.json, place thin launcher
and portable alias at InstallRoot, remove flat desktop/guard leftovers.
- On versioned success, clear the pending transaction without health probation
and relaunch via reasonix-launcher.
- Resolve InstallRoot and update-helper source for versioned trees; claim
pending targets from the prepared transaction rather than hard-coded flat
paths.
- NSIS dual mode: /REASONIXSTAGE=1 still extracts the six-member flat payload
for 1.18-1.19.1 helpers; normal install writes versioned layout and does not
persist Guard.
- Delete cmd/reasonix-guard. Compatibility payloads still build
reasonix-guard from reasonix-legacy-migrator only. Point recovery docs at
reasonix doctor.
- Linux .desktop Exec uses reasonix-launcher.
Verification:
- go test ./internal/installlayout ./cmd/reasonix-launcher
./cmd/reasonix-legacy-migrator ./internal/repair
- cd desktop && go test ./cmd/update-helper/
- focused desktop packaging/window/updater tests
- GOOS=windows go test -c ./cmd/update-helper and desktop package
|
||
|
|
b8c82972f2 |
Harden Guard repair preview confirmation / 加固 Guard 修复预览确认绑定 (#6973)
* fix(guard): bind repair apply to confirmed preview * Harden Guard preview confirmation binding Problem: non-interactive apply-plan could accept a bare --yes, while preview IDs omitted derived-state contents and full pending-update identity. Root cause: confirmation hashes covered only display previews and were checked once before the plan loop, so state-dependent actions could drift after confirmation. Fix: require a prior preview ID for non-interactive apply-plan, bind opaque file and transaction state, re-check each action immediately before execution, and preserve unrelated multi-action behavior. Update English and Chinese recovery docs. Verification: go test ./internal/repair ./cmd/reasonix-guard; go test -race ./internal/repair; go vet ./...; go test ./...; git diff --check. Co-authored-by: SivanCola <[email protected]> * Serialize confirmed Guard repair mutations Problem: preview IDs were rechecked before mutation, but another process could still replace a target during the final rename window or race on last-repair.json, losing or mixing undo records. Root cause: repair actions lacked a shared transaction lock and per-target cross-process locks, while confirmed snapshot/config bytes were read again after approval and replacement writes could overwrite a concurrent recreation. Fix: serialize repair bookkeeping before canonical target locks, revalidate confirmed state inside the lock and around renames, publish restored content with create-only atomic writes, bind complete pending-update identity, preserve concurrent writers, and keep undo under the same lock order. Add focused coverage for wait/recheck, rename windows, snapshot bytes, unreadable LKG nodes, transaction serialization, and rollback identity. Verification: go test ./internal/fileutil ./internal/config ./internal/repair ./cmd/reasonix-guard; go test -race ./internal/fileutil ./internal/repair; go vet ./...; env -u DEEPSEEK_API_KEY go test ./...; Windows test-binary cross-compilation for internal/repair and cmd/reasonix-guard; git diff --check. Co-authored-by: SivanCola <[email protected]> * Normalize Windows repair lock test paths Problem: the Windows CI test waited for a raw backslash path while the lock hook receives the canonical lower-case slash form, so the test timed out before exercising the recheck. Root cause: the regression test compared platform-specific input text instead of the production lock key representation. Fix: normalize test hook paths with the same Windows case and separator rules used by repair mutation locks. Verification: focused repair lock tests pass on macOS; Windows amd64 test-binary compilation passes. Co-authored-by: SivanCola <[email protected]> * test(jobs): remove StartForSession race Keep the worker blocked while assertions inspect its state and protect job fields with the existing mutex. This prevents the race job from observing concurrent completion writes when validating accepted input. Co-authored-by: PaulDing98 <[email protected]> * fix(repair): bind target identity into Guard preview confirmation Problem: - previewId hashed only exported preview fields and content-based state IDs, so identical reasonix.toml content in two project roots produced the same confirmation and apply-plan --yes could mutate the unconfirmed project. - Mutation locks used Abs/Clean only, so symlink path aliases (and macOS case variants) took different locks for the same real node. - rollback_update bound only the pending transaction JSON and skipped target locks, so a stable pending update could still roll back an unconfirmed live release unit. - When a target was recreated after quarantine rename, the move was not recorded in last-repair, so UndoLastRepair could restore an unrelated prior repair. Root cause: - Confirmation identity omitted canonical target identity; lock keys and rollback binding did not converge on real paths or live release-unit state; post-rename failure paths returned before persisting the already-moved node. Fix: - Embed an irreversible canonical target identity in per-file state IDs used by previewId, while verifying quarantined nodes against the original path identity. - Resolve existing symlink parents and case-fold on Windows/macOS when building mutation-lock keys and target identities. - Bind current release-unit file states into rollback preview state, take shared target locks during prepare/rollback, and re-check under those locks. - Persist the quarantine/move transaction when a concurrent recreate is detected so undo restores the confirmed node and retains the rewrite as redo. Verification: - go test ./internal/repair/ -count=1 - go test -race ./internal/repair/ ./internal/fileutil/ -count=1 - go test ./cmd/reasonix-guard/ -count=1 - go vet ./internal/repair/ * fix(repair): close symlink, app-bundle, and macOS handoff confirmation gaps Problem: - canonicalRepairPath EvalSymlinks'd the full path, so two leaf symlinks sharing a referent produced the same previewId, and renaming a confirmed symlink leaf changed its identity and made apply fail. - App-bundle rollback bound only directory kind/mode for the live .app and omitted the backup tree, so interior executable drift still accepted an old previewId and rolled back. - macOS self-update held mutation locks only while writing the pending transaction; the actual mv/ditto ran in a shell helper that ignored the shared flock, racing Guard rollback into mixed bundles. Root cause: - Leaf nodes are what Lstat/Rename mutate, but identity resolved through them; directory release units need tree digests; handoff and repair used different processes without a shared lock holder over the swap window. Fix: - Resolve only parent-directory symlinks and reattach the original leaf name for mutation locks and preview target identity. - Bind full tree digests for directory release-unit nodes and include backup paths in pending-update preview state. - Replace the macOS shell handoff with a detached self-subprocess that waits for the old PID, then holds LockRepairMutations around the directory swap. - Export LockRepairMutations/Timeout for desktop handoff and add regressions. Verification: - go test ./internal/repair/ -count=1 - go test -race ./internal/repair/ -count=1 - go test ./cmd/reasonix-guard/ -count=1 - cd desktop && go test -count=1 -run TestMacUpdate . - go vet ./internal/repair/ and desktop * fix(repair): secure updater claims and path case locks Problem: The detached macOS updater trusted filesystem paths from command-line arguments, and repair identities folded path case by operating system rather than by the target filesystem. Root cause: The handoff only checked that a pending-update file existed before swapping bundles. Path canonicalization assumed every macOS and Windows filesystem was case-insensitive. Fix: Persist optional handoff paths and owner identity in the pending transaction, claim them under strict pending and target locks, revalidate the staged bundle before swapping, and remove filesystem paths from child arguments. Detect case sensitivity from the actual macOS directory or Windows per-directory flag before folding lock and preview identities. Verification: - go test ./internal/repair/ -count=1 - go test -race ./internal/repair/ ./internal/fileutil/ -count=1 - go test ./cmd/reasonix-guard/ -count=1 - cd desktop && go test -count=1 -run TestMacUpdate . - cd desktop && go test -race -count=1 -run TestMacUpdate . - go vet ./internal/repair/ - cd desktop && go vet . - GOOS=windows GOARCH=amd64 go test -c ./internal/repair * fix(repair): scope case probe helper by platform Problem: The Linux golangci-lint job reported existingRepairPathParent as unused. Root cause: The helper lived in a common file while its only callers were excluded from Linux builds by Darwin and Windows build tags. Fix: Move the helper into a Darwin-or-Windows platform file so it is compiled exactly where the filesystem case probes use it. Verification: - golangci-lint run --timeout=5m - go test ./internal/repair/ -count=1 - cd desktop && go test -count=1 -run TestMacUpdate . - GOOS=windows GOARCH=amd64 go test -c ./internal/repair * fix(repair): preserve verified rollback recovery Problem: - File rollback could install backup bytes that changed after preflight validation. - A failed macOS backup restore still cleared pending recovery state and cleanup material. - NFC and NFD aliases on APFS produced different repair lock and preview identities. Root cause: The staged-copy hash was ignored, macOS rollback cleanup was unconditional, and canonical repair paths handled case aliases without filesystem-aware Unicode normalization. Fix: Verify the staged rollback bytes against the transaction hash before mutating live targets. Make macOS rollback compensating and retain pending, backup, and staging state when restoration fails. Normalize repair identities to NFD only on APFS and HFS while preserving distinct names on other filesystems. Verification: - go test ./internal/repair/ -count=1 - go test -race ./internal/repair/ ./internal/fileutil/ -count=1 - go test ./cmd/reasonix-guard/ -count=1 - cd desktop && go test ./... -count=1 - cd desktop && go test -race -count=1 -run TestMacUpdate . - go vet ./internal/repair/ - cd desktop && go vet . - golangci-lint run --timeout=5m - GOOS=windows GOARCH=amd64 go test -c ./internal/repair * Harden transactional updater handoffs Problem: Repair and self-update paths could continue without a pending-state lock, apply a prepared update after its transaction or release unit changed, or restore an unverified macOS bundle tree. Linux also persisted a CLI sibling that transaction validation rejected. Root cause: Pending transitions used a best-effort unbounded lock, file updaters locked paths without claiming the exact prepared transaction, and app-bundle handoff/rollback validation did not bind both the staged tree and original backup tree across the rename window. Fix: Use bounded fail-closed pending locks and a consistent pending-to-target lock order. Claim Linux and Windows replacements by version, creation identity, platform, and canonical release-unit paths. Bind macOS staging, original, installed, and backup trees; recover rejected handoffs only when the original bundle is still verified; protect backup paths and reject symlink escapes. Add focused concurrency, drift, rollback, compatibility, and cross-platform tests. Verification: - go test ./internal/repair/ ./internal/fileutil/ ./cmd/reasonix-guard/ -count=1 - go test -race ./internal/repair/ ./internal/fileutil/ ./cmd/reasonix-guard/ -count=1 - cd desktop && go test ./... -count=1 - cd desktop && go test -race ./... -count=1 - go vet ./... and cd desktop && go vet ./... - golangci-lint run --timeout=5m ./... - Windows amd64/arm64 test-binary compilation for repair, desktop, and update-helper Co-authored-by: SivanCola <[email protected]> * Complete fail-closed repair and updater transactions Problem: Repair, undo, and self-update entry points could act on state that changed while waiting for locks. File-update completion also needed a crash-safe installed-unit binding, and platform handoffs could execute mutable or incompletely claimed payloads. Root cause: Invocation identity was sampled too late or incompletely, mutable pending state doubled as installed state, cleanup paths did not consistently compare ownership, and Windows/macOS handoffs did not bind every source, backup, staging, and release-unit transition. Fix: Bind every mutating invocation before lock waits and recheck it under a pending-to-target lock order. Persist create-only installed-state sidecars, preserve recovery material on ambiguity, use atomic no-replace publication, validate complete app and file trees, isolate and hold the verified Windows installer through execution, and make rollback/undo crash-retryable. Verification: go test ./internal/repair ./internal/fileutil ./cmd/reasonix-guard -count=1 cd desktop && go test ./... -count=1 Windows amd64 and arm64 update-helper test-binary compilation gofmt -l internal/repair desktop git diff --check Co-authored-by: SivanCola <[email protected]> * Document fail-closed legacy update recovery Problem: Recovery documentation described additive update state as generally backward compatible and a Linux comment still described the obsolete mutable-pending design. Root cause: The text was not updated when installed release-unit state moved to a transaction-unique sidecar and legacy destructive actions began requiring explicit ownership proof. Fix: Document immutable pending state, crash-safe sidecar recovery, and the distinction between readable legacy transactions and authorization for handoff, healthy commit, or app-bundle rollback. Verification: git diff --cached --check Focused repair and updater tests, full race suites, vet, lint, and cross-platform compilation passed against the merged main-v2 baseline. Co-authored-by: SivanCola <[email protected]> * Close updater execution and compensation races Problem: - Generic failure-marker writes could let a stale invocation overwrite a newer transaction marker. - Legacy app rollback could move a symlink backup before rejecting it, and file publish could leave a tampered staged node live. - Windows self-update could execute a helper that changed after transaction prepare, overwrite a concurrently allocated cache path, or add a portable alias that was absent before. - macOS updater commands were resolved through PATH. Root cause: Mutation ownership was not rebound under the pending lock at every public entry point. Helper validation proved only PE architecture, staged-file verification followed symlinks, and helper cache publication used replace semantics. Fix: Rebind generic failure markers after lock acquisition, reject non-directory app backups before mutation, require regular-file staged payloads, compensate failed publication by retaining the rejected node and restoring the verified prior file, and preserve pending recovery state. Bind the Windows helper to the exact prepared release-unit SHA-256, create a unique cache node without replacement, freeze it through process creation, preserve the original portable-alias shape, and use absolute macOS system command paths. Verification: - go test ./... -count=1 - go test -race ./internal/repair ./internal/fileutil ./cmd/reasonix-guard -count=1 - cd desktop && go test ./... -count=1 - cd desktop && go test -race ./... -count=1 - go vet ./... and cd desktop && go vet ./... - golangci-lint 2.12.2 for root and desktop - cache guard: 8/8 pass - Windows amd64/arm64 repair, desktop, and update-helper test-binary compilation - Linux amd64 repair test-binary compilation Co-authored-by: SivanCola <[email protected]> * Tidy desktop updater dependencies Problem: The desktop CI go-mod-tidy gate failed because the updater no longer imports github.com/minio/selfupdate, but the module files still retained that dependency and its stale transitive checksums. Root cause: The transactional updater implementation replaced the selfupdate package without running the desktop module tidy gate afterward. Fix: Remove the unused selfupdate requirement and the transitive checksum entries that are no longer reachable from the desktop module graph. Verification: - cd desktop && go mod tidy (idempotent) - cd desktop && go vet ./... - focused workspace-rebuild timing tests: 10/10 pass - git diff --check Co-authored-by: SivanCola <[email protected]> * Harden prepared repair journals and Windows release-unit signing Problem: - Repair mutations could leave ambiguous undo state after a crash between rename and last-repair.json publication. - Concurrent writers could replace a pending journal or cleanup node after ownership checks, turning cleanup into deletion of unowned material. - Windows portable/installer updates did not bind signed payload identity through packaging, and Linux release-unit publication did not return exact installed-state receipts. Root cause: Undo bookkeeping treated last-repair.json as the only durable intent, cleanup used path-based remove after verification, and Windows packaging trusted unsigned payload layout without a create-only signed manifest contract. Fix: - Introduce create-only pending-repair.json write-ahead journals, promote or discard them under the repair lock, and fail closed on ambiguous recovery. - Displace cleanup targets to unique siblings, re-verify identity, and never unlink a pending journal that changed before cleanup. - Bind Windows signed payload manifests through packaging/signing and require exact installed-state receipts for Linux release-unit publication. Verification: - go test ./internal/repair -count=1 (pass) - focused security coverage for prepared intent, pending cleanup ownership, legacy healthy/rollback fail-closed, and macOS staging cleanup Co-authored-by: SivanCola <[email protected]> * fix(ci): use resolved version for payload manifest Problem: The Windows payload manifest step referenced a nonexistent ver step output, so actionlint rejected the release workflow. Root cause: The build job receives the release version from needs.resolve.outputs.version, but the step used steps.ver.outputs.version. Fix: Bind the signed payload manifest to the resolved release version output. Verification: actionlint v1.7.7 and scripts/release-workflows.test.sh pass. * fix(repair): bind prepared create ownership to published Windows modes Problem: - Windows CI rejected undo after a crash following snapshot create: the restored config file remained because CreatedStateID ownership failed. - Desktop packaging contract tests still expected steps.ver.outputs.version after the release workflow switched to needs.resolve.outputs.version. Root cause: - Prepared create intents predicted FileMode 0o600, but Windows Lstat reports regular files as 0444/0666. Undo then treated the published file as an unowned concurrent write and left it in place. - The packaging test was not updated with the resolved-version workflow fix. Fix: - Predict create-state IDs with platform-published file modes and rebind the pending journal to the exact on-disk node after AtomicCreateFile. - Align the Windows signing packaging contract test with the resolve job version output. Verification: - go test ./internal/repair -count=1 - go test ./internal/repair -run TestPreparedCreateStateIDMatchesAtomicCreate,TestApplyRepairPlanPersistsMissingSnapshotTargetBeforeCreate - cd desktop && go test -run TestWindowsReleaseSignsPayloadBeforeRepackaging . Co-authored-by: SivanCola <[email protected]> * fix(repair): reject prepared create ownership drift Problem: A file replaced between AtomicCreateFile and ownership rebinding could be claimed by the repair transaction and removed by undo. Root cause: The pending journal was rewritten to bind whatever state happened to be present after publication instead of proving it matched the precomputed owned state. Fix: Keep the write-ahead ownership binding immutable and fail closed when the published path differs; add a regression test that preserves a concurrent replacement through undo. Verification: focused crash/create tests, go test ./internal/repair, repair/fileutil race tests, Guard tests, go vet, and Windows repair test cross-compile pass. --------- Co-authored-by: SivanCola <[email protected]> Co-authored-by: PaulDing98 <[email protected]> |
||
|
|
035f92897f |
fix(desktop): support authorized Debian package updates / 支持 Debian 安装包应用内授权更新 (#6866)
* fix(desktop): support authorized Debian package updates Problem: Ubuntu users who installed the desktop .deb could not update in app because the updater could not replace root-owned system files. Root cause: Linux installs were treated uniformly as writable portable layouts, and the release manifest exposed only the tarball updater artifact. Fix: Detect dpkg-owned installs, publish signed native .deb metadata, and install upgrades through a packaged Polkit helper that re-verifies ownership, signatures, package identity, architecture, and version before delegating to apt. Preserve the portable tarball path and add user-facing progress, metrics, tests, and recovery documentation. Verification: - cd desktop && go test ./... - cd desktop && go vet ./... - pnpm --dir desktop/frontend test:typecheck - pnpm --dir desktop/frontend test:updater - pnpm --dir workers/crash-report typecheck - pnpm --dir workers/crash-report test - Linux amd64 helper test binary cross-compilation - git diff --check * fix(desktop): recover from updater mode changes Problem: The desktop CI failed on two unused updater helpers, and the UI could remain stuck in downloading or authorizing when install mode or manifest availability changed between updater steps. Root cause: The backend opened the manual download page and returned nil after reclassification, while the frontend treated nil as an in-flight operation with no terminal state. Two obsolete helper functions also remained after the refactor. Fix: Return and emit a typed manual-update error before opening the download page, preserve the manual fallback action in the shared updater state, add authorization/install/cancellation/reclassification coverage, and remove the unused functions. Verification: - cd desktop && go test ./... - cd desktop && go vet ./... - pnpm --dir desktop/frontend test:typecheck - pnpm --dir desktop/frontend test:updater - pnpm --dir desktop/frontend build - pnpm --dir workers/crash-report typecheck - pnpm --dir workers/crash-report test - Linux amd64 update-helper test binary and production build - git diff --check * Fix Linux package smoke checks under pipefail Problem: Linux .deb contract smoke checks could fail on valid packages when the producer emitted more data after grep found its match. Root cause: The build script combined set -o pipefail with grep -q. Early grep exit could close the pipe and make dpkg-deb terminate with SIGPIPE, turning a successful contract match into a failed pipeline. Fix: Consume the complete dpkg-deb output with non-quiet grep redirected to /dev/null, and add a packaging guard that rejects the unsafe early-exit patterns. Verification: - cd desktop && go test ./... - cd desktop && go test -run TestDesktopPackagesPreserveNativePlatformLaunchers -count=1 . - pnpm --dir desktop/frontend test:updater - bash -n scripts/desktop-build.sh - git diff --check |
||
|
|
93c82a948a |
Remote Workbench with Local Provider Broker / 使用本机模型的远程工作台 (#6728)
* feat(remote): add rpcwire, RuntimeAPI registry, and protocol codegen Problem: Remote Workbench needs a bidirectional JSON-RPC transport and a single Go registry that generates schema, Schema Hash, and TypeScript DTOs so Desktop and Host negotiate strictly by schema, not by full Build ID hard-fail. Root cause: main-v2 lacked rpcwire and a generative Remote protocol surface. Fix: - Port transport-neutral NDJSON JSON-RPC (rpcwire) with strict frames, concurrent requests, cancel, and size limits (adapted from #6725). - Port RuntimeAPI protocol registry + schema generator; regenerate committed artifacts for main-v2 eventwire. - Mark eventwire large fields externalizable for content-ref offload without changing provider-visible semantics. - Extend directions for Provider Broker (host_to_client_request / client_to_host_notification) and register broker methods in the frozen surface. Verification: - go test ./internal/rpcwire ./internal/remote/protocol ./internal/remote/protocolgen ./internal/eventwire - go run ./cmd/remote-protocol-gen -check -root . Co-authored-by: SivanCola <[email protected]> Co-authored-by: taibai233 <[email protected]> * feat(remote): add Desktop Provider Broker and TargetManager Problem: Workbench Hosts must consume models without holding API keys, and the main window needs Local + one Remote adapters with a single active projection. Root cause: No in-process Broker over rpcwire and no target fencing manager on main-v2. Fix: - Desktop Broker endpoint: catalog, stream open/cancel, chunk/end notifications, concurrency limits, DeepSeek ToolCallReasoning catalog flags, connection-wide stream cancel on close (direction from #6722; fencing ideas from #6725). - TargetManager: permanent Local, optional Remote, last-click-wins fencing, busy remote host-swap rejection, restart reconnect hint only (no auto SSH). Verification: - go test ./internal/remote/broker ./internal/remote/workbench/target Co-authored-by: SivanCola <[email protected]> Co-authored-by: taibai233 <[email protected]> * feat(remote): workbench SSH, attach-workspace, adapters, mirror, trust Problem: Remote Workbench needed end-to-end transport, lifecycle, main-window adapters, workspace-safe files, mirrors, and Provider trust — not Serve HTML or HTTP Gateway tunnels. Root cause: Prior foundation only had protocol/Broker/TargetManager; no SSH stdio path, attach proxy, runtime grace, or UI wiring. Fix: - Windows: system OpenSSH + AskPass + Job Object (adapted from #6725); remote command is `reasonix remote attach-workspace --stdio`. - macOS/Linux: Go SSH session stdio to the same attach entry. - attach-workspace + per-workspace runtime on Unix socket; 5-minute grace after detach; Schema Hash gate on initialize. - Desktop Workbench adapters (connect/disconnect/switch Local, remote RPC, Provider trust prompt); OpenRemoteWorkspace uses workbench path. - File containment (relative refs, no symlink leaves, atomic writes). - Local mirror store with digest validation; restore requires session.jsonl. - Durable Provider trust store (host+fingerprint → allowed refs only). - Frontend workbenchTarget helpers + tests. Verification: - go test ./internal/remote/workbench/... ./internal/remote/broker ./internal/rpcwire ./internal/remote/protocol ./internal/cli - cd desktop && go test -run 'TestRemote|TestWorkbench|TestAskPass|TestOpenRemote' - pnpm exec tsx --test desktop/frontend/src/__tests__/workbench-target.test.ts Co-authored-by: SivanCola <[email protected]> Co-authored-by: taibai233 <[email protected]> * docs(remote): record source PR authors as repository co-contributors Problem: Repository co-contribution attribution requires explicit documentation and commit-level Co-authored-by trailers for the source PR authors (#6722, #6725). Root cause: PR body credits alone do not enter the GitHub contribution graph. Fix: Document both source PR authors, what was adopted, and that GitHub co-author attribution uses Co-authored-by trailers with public noreply emails in REMOTE_WORKBENCH docs (EN + zh-CN). Verification: - docs/REMOTE_WORKBENCH.md contains Repository co-contributors table - every commit on this branch includes both Co-authored-by trailers Co-authored-by: SivanCola <[email protected]> Co-authored-by: taibai233 <[email protected]> * fix(remote): close the workbench broker runtime loop Problem: Remote Workbench still mixed Remote state with the Local controller, left parts of the runtime API empty, and could lose reconnect, operation, history, Git, and provider semantics in real main-window use. Root cause: The first integration established the transport and broker direction but did not fully fence target projections, rebuild controller profiles, persist remote execution state, or cover strict protocol and process lifecycle parity. Fix: - route the existing main window through the Host-owned controller, files, Git, history, catalogs, operations, goals, checkpoints, and slash completion - keep provider credentials on Desktop while forwarding strict provider requests, effort, DeepSeek tool-call reasoning, and reconnect-safe stream generations - harden Build ID/schema negotiation, SSH/AskPass process cleanup, runtime socket ownership, workspace containment, mirror pulls, disconnect fencing, and background target isolation - add generated protocol contracts and regression coverage for no-Host-key broker use, paging, reconnect, overflow, lifecycle, and projection behavior Verification: - env -u DEEPSEEK_API_KEY REASONIX_RELEASE_CACHE_GUARD=1 go test -race ./... - cd desktop && go test ./... && go vet ./... && go build ./... - pnpm --dir desktop/frontend test:all && pnpm --dir desktop/frontend build - go run ./cmd/remote-protocol-gen -check -root . - Windows amd64 cross-compilation for root Remote packages and desktop module - scripts/check-cache-impact.sh Co-authored-by: SivanCola <[email protected]> Co-authored-by: taibai233 <[email protected]> * fix(remote): bind attach to its workspace target Problem:\nCI lint found an overwritten normalized workspace, and initialize could replace the SSH attach target before runtime startup.\n\nRoot cause:\nThe attach bootstrap normalized Options.Workspace but then assigned the client-provided initialize workspace to the same variable without comparing the two.\n\nFix:\nKeep the normalized attach target, normalize the requested workspace separately, and reject mismatches before schema negotiation or runtime startup.\n\nVerification:\n- go test ./internal/remote/workbench/attach ./internal/remote/workbench/runtime\n- go vet ./internal/remote/workbench/attach\n- golangci-lint v2.12.2: 0 issues * fix(desktop): remove the legacy remote child window Problem:\nThe same-window Remote Workbench still carried an unreachable child-window launcher and special shell lifecycle, causing Desktop CI unused-code failures and contradicting the selected product model.\n\nRoot cause:\nThe App bindings were migrated to TargetManager, but the old ticket-based Serve HTML launch path and its window-specific startup branches were left behind.\n\nFix:\nRemove remote-window tickets, spawning, middleware, lifecycle branches, and obsolete helpers so every SSH workbench runs in the existing main window.\n\nVerification:\n- cd desktop && go test ./...\n- desktop and root golangci-lint v2.12.2: 0 issues\n- Windows amd64 Desktop cross-compilation\n- wails generate module * fix(remote): preserve workspace diff parity Problem: After rebasing onto #6733, WorkspaceChangeDetail still executed against the Desktop filesystem while a Remote target was active. Root cause: The frozen RuntimeAPI had no method for the newly added per-file workspace diff query. Fix: Add a strict workspace/changeDetail contract, route Desktop through the Host runtime, and generate bounded Git/checkpoint patches inside the selected remote workspace. Verification: go test ./...; go test -race ./...; cd desktop && go test ./...; pnpm test:all; protocol codegen check; vet/build/lint; Windows cross-compile. Co-authored-by: SivanCola <[email protected]> * Harden Remote provider broker lifecycle Problem: the local Provider Broker became active before the live SSH peer was rebound to its trusted fingerprint, and slow provider consumers could block detach while the Host mutex was held. Root cause: peer validation happened after client.Connect returned, while Host stream delivery performed blocking channel sends inside the global lock. Fix: gate Broker activation on the authenticated live peer identity and move ordered Host delivery into bounded per-stream queues with a sole output pump. Verification: go test -race ./internal/remote/broker; go test ./internal/remote/workbench/client; cd desktop && go test -race . -run 'Test(AuthorizeWorkbenchPeerFailsClosed|Workbench|Remote)' -count=1. * Restore Remote sessions across runtime restarts Problem: Remote sessions existed only in the runtime process map, so a normal detach followed by runtime exit made persisted transcripts invisible on reconnect. Root cause: the Host had no durable mapping between protocol session identities, controller profiles, topics, and transcript paths. Fix: add a per-workspace atomic session registry, lazily rebuild controllers after Broker activation, retain temporarily unavailable records, and persist lifecycle/profile changes without holding the runtime mutex across file I/O. Verification: go test -race ./internal/remote/workbench/runtime -count=1; go test -race ./internal/remote/workbench/runtime -run 'TestRuntime(RestoresSessionRegistryAfterProcessRestart|EarlyShutdownDoesNotOverwriteUnreadRegistry)' -count=20. * Keep Remote projections and provider state current Problem: Remote callbacks stayed bound to a stale local tab, provider metadata and authorization were captured at connect time, and the bounded-handler regression test released its blockers before overload dispatch was observable. Root cause: Local navigation was not serialized with Remote activation, Broker descriptors omitted compaction/pricing fields, provider closures captured immutable config, and the rpcwire test synchronized only handler startup. Fix: Fence visible local navigation and rebind callbacks on Remote activation, propagate complete non-secret provider metadata, refresh config and trust-scoped access for live Broker connections, fail closed on empty authorization, and wait for all overload responses before releasing handlers. Verification: go test -race ./internal/boot ./internal/remote/protocol ./internal/remote/broker ./internal/remote/workbench/client ./internal/remote/workbench/runtime ./internal/rpcwire (cd desktop && go test -race ./...) go test -race ./internal/rpcwire -run TestInboundHandlerConcurrencyIsBoundedWithoutBlockingResponses -count=100 go run ./cmd/remote-protocol-gen -check -root . ./scripts/cache-guard.sh * Constrain restored Remote transcript paths Problem: An edited session registry could name an opaque topic that the wire contract permits but restoration rejected, while a nested transcript path could traverse a directory symlink outside SessionDir. Root cause: Registry validation derived a topic_ prefix from an opaque protocol ID and only performed lexical containment plus a final-component symlink check. Fix: Accept any non-empty opaque topic ID, require runtime transcripts to be direct children of SessionDir, close partially built controllers on restore errors, and isolate fallback socket paths per test run. Verification: go test -race ./internal/remote/workbench/runtime -count=3 * Fence late Remote projection callbacks Problem: A callback or snapshot refresh captured for one local tab could complete after Remote was rebound to another tab and still emit into the stale surface. Root cause: Reactivation marked Remote visible before rebinding callbacks, and callback/refresh completion trusted its captured tab ID instead of the current projection binding. Fix: Bind callbacks before activation, route late events through the current Remote tab under the transition fence, redirect snapshot completion to the live binding, and drop completion while Local is active. Verification: cd desktop && go test -race -run 'TestWorkbenchLateCallbackUsesCurrentProjectionTab|TestSetActiveTabSwitchesRemoteProjectionOnlyForDifferentTab|TestConcurrentActivateTopicSerializesSingleSurfacePruning' -count=20 * Synchronize Remote host-key prompt regression Problem: The full desktop race suite detected an unsynchronized map write in the host-key prompt serialization test. Root cause: The test started the first prompt goroutine before registering the second managed host, allowing the goroutine to read the manager map while the test wrote it. Fix: Register every host before launching concurrent prompts and wait for both prompt goroutines during test cleanup. Verification: cd desktop && go test -race -run '^TestHostKeyPromptsAreSerializedForGlobalDialog$' -count=100 .; cd desktop && go test -race ./... * Wait for queued background task teardown Problem: Windows CI could finish TestBackgroundTaskReturnsBeforeSlotFrees while its background job was still persisting transcript artifacts, causing TempDir cleanup to fail with a non-empty directory. Root cause: The test waited only for provider startup and then slept for 50 milliseconds instead of synchronizing with the job's terminal lifecycle. Fix: Scope the job to the test session, capture its returned job ID, wait for jobs.Done, and close the manager on every exit path before temporary-directory cleanup. Verification: go test -race ./internal/agent -run '^TestBackgroundTaskReturnsBeforeSlotFrees$' -count=100; REASONIX_RELEASE_CACHE_GUARD=1 go test -race ./internal/agent; REASONIX_RELEASE_CACHE_GUARD=1 go test ./...; GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go test -c ./internal/agent; go vet ./internal/agent; golangci-lint run ./internal/agent/... * fix(remote): fall back to server root workspace * fix(remote): close review blockers for workbench v1 Problem: Remote Workbench could silently expose the Host root, strand a session after registry persistence failure, leave local provider streams running after cancellation, and fail the Ubuntu/Windows attach tests. Root cause: One-click workspace resolution used an implicit root fallback; profile changes closed or mutated live controllers before durable state succeeded; Broker delivery lacked an abort path and open cancellation did not reach Desktop; attach readiness and tests depended on connection and timing assumptions that were not portable. Fix: Require explicit workspace selection, roll profile changes back while preserving the old controller, propagate best-effort Broker cancellation with abortable delivery, remove the readiness probe generation race, and use deterministic platform-aware attach tests. Verification: Remote, Broker, attach, runtime, rpcwire, race, Desktop, frontend Remote, TypeScript, production build, protocol generation, cache guard, go vet, and repeated cancellation/attach regressions passed. * fix(remote): make attach startup portable Problem: The Windows CI attach integration test could not observe the in-process AF_UNIX listener and reported that the runtime never became ready. Root cause: Startup readiness was inferred with os.Stat on the socket path, but Windows AF_UNIX does not expose a portable socket file. A separate readiness connection is also unsafe because runtime connections own generations. Fix: Let the real attach connection retry bounded socket dials until the runtime listener accepts it, and return immediately after starting the in-process test runtime. Verification: - attach integration test repeated 50 times - attach race test repeated 30 times - Windows amd64 test binary cross-compiled - go test ./internal/remote/... - remote broker, attach, and runtime race tests * fix(remote): keep runtime sockets portable Problem: Windows CI still could not connect to the in-process workbench runtime even with bounded dial retries. Root cause: The generated AF_UNIX address exceeded the platform path limit when the remote home itself was long, as on Windows hosted runners. Fix: Compact the runtime socket hierarchy while keeping it scoped under the Reasonix home, and add a regression test against the portable AF_UNIX length bound. Verification: - attach integration test repeated 50 times - runtime socket path tests repeated 20 times - attach and runtime race tests - Windows amd64 runtime test binary cross-compiled - go test ./internal/remote/... - protocol generation check and cache guard * fix(desktop): preserve native macOS app ownership Problem: Packaged macOS builds used reasonix-guard as CFBundleExecutable, so the Dock and LaunchServices owned a non-UI parent while the Wails child owned the window. The app could stay running without reopening its window from the Dock. Root cause: The packaging step replaced Wails' native bundle entry point to route startup through Guard. macOS application identity cannot be transferred reliably across that parent-child process boundary. Fix: Keep reasonix-desktop as the macOS bundle executable, retain Guard and the CLI as recovery sidecars, and run the equivalent failed-install, crash-loop rollback, repair, and Safe Mode preflight in Desktop before Wails creates WebView. Update packaging contracts and recovery documentation for the platform-specific launch model. Verification: - env -u DEEPSEEK_API_KEY go test ./... - go test ./... (desktop module) - go test -race -run 'TestDesktopStartupRecovery|TestDesktopPackagesPreserveNativePlatformLaunchers' -count=1 . (desktop module) - go vet ./... (desktop module) - DESKTOP_BUILD_SKIP_DMG=1 scripts/desktop-build.sh darwin/arm64 v0.0.0 - Signed packaged App launched with reasonix-desktop as PID 1 child, one Desktop process, no Guard process, and an onscreen CoreGraphics window * fix(desktop): satisfy startup recovery lint Problem: The Desktop CI job rejected the macOS startup recovery helper because continueLaunch was initialized before every return path overwrote it. Root cause: The named return value carried an unnecessary default assignment that go vet did not flag but golangci-lint's ineffassign check did. Fix: Initialize only the Safe Mode result and let each branch set the continue decision explicitly. Verification: - go test -run 'TestDesktopStartupRecovery|TestDesktopPackagesPreserveNativePlatformLaunchers' -count=1 . - go vet ./... * fix(remote): close workbench runtime safety gaps Problem: Remote Workbench could reject typed client requests before session hydration, execute duplicate mutations more than once, lose the committed target during a failed replacement, race controller lifecycle changes, and expose Local saved-session bindings while Remote was active. Root cause: Client authority hydration preserved serialized zero values, the advertised requestId contract had no runtime ledger or request sequencer, TargetManager stored candidates as committed state, and unsupported Remote history actions silently fell through to Local bindings. Fix: Authoritatively hydrate client-owned fields while preserving retry IDs, serialize runtime requests with a bounded 24-hour mutation replay ledger, fence controller profile transitions, promote replacement targets only after successful connection, and fail closed for unsupported Remote saved-session operations. Verification: - env -u DEEPSEEK_API_KEY go test ./... - env -u DEEPSEEK_API_KEY REASONIX_RELEASE_CACHE_GUARD=1 go test -race ./... - cd desktop && go test ./... && go vet ./... && go build ./... - pnpm --dir desktop/frontend test:remote - go run ./cmd/remote-protocol-gen -check -root . - scripts/check-cache-impact.sh with the live PR body Co-authored-by: taibai233 <[email protected]> * fix(remote): keep session rotations authoritative Problem: Completed turns could retain stale approval or ask prompts, while committed new/clear session rotations could return an error after a registry write failure and leave clients on the old runtime epoch. Root cause: Turn completion only cleared replay events when no prompt remained, session rotation treated the fallible registry write as part of the already-committed controller mutation, and the client did not apply new/clear result epochs. Fix: Clear terminal prompt state, return and adopt the committed rotation epoch while logging registry degradation, reset stale runtime state, and invalidate the previous snapshot. Verification: go test ./...; go test -race ./internal/remote/workbench/runtime ./internal/remote/workbench/client; cd desktop && go test ./...; go vet ./...; go run ./cmd/remote-protocol-gen -check -root . * fix(remote): fence snapshot refreshes and fork cleanup Problem: Remote rewind could report failure after destructive state changes committed, late subscribe responses could restore stale runtime authority, and failed forks left transcript artifacts on disk. Root cause: Post-commit registry errors were treated as rollbackable, subscribe responses had no request-authority fence, and fork rollback removed only the in-memory child session. Fix: Keep committed rewind results authoritative, serialize and revision-fence subscription refreshes with automatic stale retry, validate projection freshness, and remove all artifacts for uncommitted forks. Verification: - go test ./... - go test -race ./internal/remote/workbench/client ./internal/remote/workbench/runtime ./internal/control - go vet ./... - cd desktop && go test ./... - go run ./cmd/remote-protocol-gen -check * fix(remote): serialize projections and capability boundaries Problem: Remote subscribe snapshots could overwrite newer events, unsupported Remote Memory surfaces could reach Local state, and the broker test assumed concurrent notification arrival order. Root cause: Snapshot publication, event callbacks, and authority-changing results had no shared projection boundary; Desktop bindings did not fail closed for frozen capabilities; the test ignored stream sequence numbers. Fix: Linearize subscribe commits with session delivery and mutation results, install the initial Remote projection within that boundary, reject unsupported Remote Memory and Auto Research access, and assert broker chunks by sequence. Verification: go test ./...; go test -race ./internal/remote/...; desktop go test ./...; desktop go vet ./...; broker round-trip with coverage at count 500. * fix(remote): preserve active workbench transport Problem: Uninitialized socket probes could evict the live Desktop connection, target transition events exposed candidates as active, and Remote notification overload silently dropped ordered events. Root cause: Connection ownership was transferred before initialize response commit, candidate identity and active identity shared one event shape, and rpcwire used best-effort concurrent notification dispatch. Fix: Add provisional connection gates with post-write activation and exact daemon build checks; keep transition events on the committed target and fence submits; add ordered bounded notification queues with explicit overflow failure and generation-aware Broker delivery. Verification: go test ./... go test -race ./internal/rpcwire ./internal/remote/broker ./internal/remote/protocol ./internal/remote/workbench/... (cd desktop && go test ./...) (cd desktop/frontend && pnpm test:all) * fix(remote): serialize connection teardown Problem: A client closing immediately after initialize could race the response-commit callback, leaving a rejected gate paired with newly activated connection ownership. Root cause: Provisional connection teardown and post-write activation checked and mutated the wire registry under separate critical sections. Fix: Serialize teardown with connection activation, keep the production notification queue memory bound at 256 entries, and lock the initialize post-write contract with a router regression test. Verification: go test ./internal/remote/protocol ./internal/remote/workbench/runtime go test -race ./internal/remote/workbench/runtime ./internal/remote/protocol ./internal/remote/broker ./internal/rpcwire * test(remote): cover broker-backed tool loop Problem: The no-Host-key integration test only proved a single text response. It did not exercise the critical model-to-Host-tool-to-model loop or DeepSeek reasoning replay across the Desktop Broker. Root cause: The stub Provider always returned final text on its first request, so Host tool execution and the second Broker request were outside the end-to-end coverage. Fix: Make the stub request read_file first, assert the Host result and reasoning/tool-call replay in the second request, then complete the turn and verify projected tool events. Verification: - go test ./internal/remote/workbench/runtime -run '^TestRuntimeControllerUsesDesktopBrokerWithoutHostKey$' -count=1 -v - go test -race ./internal/remote/workbench/runtime -run '^TestRuntimeControllerUsesDesktopBrokerWithoutHostKey$' -count=20 - go test ./internal/remote/workbench/... ./internal/remote/broker ./internal/rpcwire - env -u DEEPSEEK_API_KEY go test ./... * test(remote): add physical Windows Linux acceptance Context: The Remote Workbench release gate needs reproducible evidence from a real Windows OpenSSH client to a Linux Host, including Broker-backed tool execution and reconnect cleanup. Change: Add an opt-in Windows ARM64-compatible acceptance test that exercises the production SSH transport, Linux workspace queries, Desktop Broker tool replay, session authority after reconnect, and OpenSSH process reaping. The fixture is environment-gated and keeps Provider execution on the Desktop side. Verification: - GOOS=windows GOARCH=arm64 CGO_ENABLED=0 go test -c -tags reasonix_remote_integration ./desktop - go test ./... - go test -race ./internal/remote/... * fix(remote): align Desktop and Host build identity Context: The Desktop is built from a nested Go module, so Go does not embed vcs.revision there while the bundled Host CLI built from the root module does. Strict Remote Workbench negotiation consequently rejects matching release artifacts as different builds. Fix: Allow release builds to link a validated shared source revision into the protocol package. Capture the clean repository revision before packaging mutations and inject it into both the Wails Desktop and bundled CLI sidecar, preserving the dirty suffix for local builds. Verification: - go test ./... - go test ./... (desktop module) - go test -race ./internal/remote/... - Windows ARM64 acceptance cross-compile with linked source revision - bash -n scripts/desktop-build.sh * fix(remote): preserve direct SSH credentials Context: The Windows Workbench direct-host branch reduced a saved Host to username, address, and port before starting OpenSSH. Explicit identity_file and proxy_jump settings were silently dropped, so valid direct connections could fail authentication or bypass the required jump path. Fix: Add an injection-safe direct configured transport that preserves identity and ProxyJump as distinct argv values. Route the Windows Workbench direct branch through it while retaining normalized IPv4 and IPv6 target parsing. Verification: - go test ./... (desktop module) - go test -race focused Windows Workbench transport tests - Windows ARM64 acceptance cross-compile * fix(remote): share runtime build identity Context: The detached workspace runtime duplicated Build ID discovery instead of using the shared protocol implementation. Linked source revisions used by nested Desktop release builds were therefore ignored, causing one installed CLI to reject its own runtime as a different build. Fix: Use protocol.CurrentBuildID for production runtime identity while retaining the explicit SourceRevision test seam. This keeps Desktop, attach, and detached runtime negotiation on one validated source of truth. Verification: - go test ./internal/remote/workbench/runtime - go test -race ./internal/remote/workbench/runtime - linked-revision focused regression test * fix(remote): allow initial history page Context: The Desktop history client intentionally requests the latest page without a cursor, and the Host runtime supports that state. The wire DTO nevertheless marked cursor as required, so strict validation rejected every initial session/history request after a successful Remote turn. Fix: Make the history cursor optional, regenerate the frozen protocol artifacts, and cover omission plus strict decoding. Strengthen the physical acceptance fixture to verify both product version and exact source revision before connecting. Verification: - go test ./... - go test ./... (desktop module) - go run ./cmd/remote-protocol-gen -check -root . - Windows ARM64 acceptance cross-compile * fix(remote): validate session mirror snapshots Context: After a completed turn the reconnect snapshot includes the persisted session mirror. That complete object incorrectly populated originalBytes while marked non-truncated, violating the frozen externalized-field contract and turning session/subscribe into an internal error. Fix: Emit complete session mirrors without truncation-only metadata and cover the artifact contract directly. Verification: - go test ./... - go test -race ./internal/remote/workbench/runtime - focused session mirror and runtime integration tests * fix(remote): model session mirror payload Context: Remote reconnect snapshots advertised /mirror/session.jsonl as an externalized content pointer, but SessionSnapshot had no schema field at that path. Strict response validation therefore rejected every post-turn reconnect snapshot before Desktop could fetch the mirror. Fix: Add the mirror placeholder to the frozen snapshot DTO, replace its concrete body with null during marshaling, and keep the body behind the existing bounded contentRef transfer. Regenerate Go/TypeScript protocol artifacts and prove that no session body is inlined on the wire. Verification: - go test ./... - go test ./... (desktop module) - go run ./cmd/remote-protocol-gen -check -root . - Windows ARM64 acceptance cross-compile * test(remote): add live Desktop Broker acceptance * test(remote): require live Broker tool loop --------- Co-authored-by: taibai233 <[email protected]> |
||
|
|
5b0dfb0621 | fix(guard): harden diagnostic privacy and repair commits | ||
|
|
2cfaef26d6 |
fix(recovery): close rollback and undo crash windows from second review
- Keep every undo backup on disk until the per-change progress record is persisted (restore by copy, then mark, then remove), so a crash between the restore and the progress write can no longer strand an unresumable transaction; completed-but-uncleaned steps are swept on retry - Record a Windows installer failure from the update helper (which runs outside the validated install directory and must not restore binaries itself) and let Guard roll back the release unit on its next launch instead of leaving a mixed install behind a clean-exit state - Make redo names unique per change (index + nanosecond stamp) so one undo touching the same target twice keeps both redo copies - Serialize startup-state read-modify-write cycles with a cross-process file lock and refuse transitions against a live foreign owner, closing the concurrent cold-start race - Reject file update transactions with missing backup hashes and require the release unit to list the primary executable; rollback errors on any unhashed entry instead of skipping verification |
||
|
|
2845bbcc30 |
fix(recovery): harden rollback, startup counting, plan undo, and read-only paths
- Back up and restore the complete Windows/Linux release unit (desktop executable plus Guard/launcher siblings), verify every backup hash before restoring, and roll back instead of deleting the rollback metadata when the Linux apply fails after the Guard binary was already replaced - Stop counting duplicate launches as crashes: StartupTracker.Begin no longer overwrites state while the recorded owner PID is alive, since Wails second instances exit through os.Exit without OnShutdown - Record multi-action AI repair plans as one plan-level transaction so undo reverts the whole plan (or the applied prefix on mid-plan failure), and persist per-change undo progress so an interrupted undo can resume - Skip legacy memory/session migration and cleanup-pending deletion in Safe Mode to preserve the recovery isolation boundary - Load config read-only in guard diagnose/assist so documented read-only paths never rewrite legacy MCP tier lines on disk |
||
|
|
3baf0b3c46 | feat(recovery): add offline Guard and safe mode |