-
Notifications
You must be signed in to change notification settings - Fork 0
fix: converge Homebrew status and privacy feedback #209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
da3fbdd
c6a5ea1
6387aea
8cda3ad
d1ddd2d
8f88212
098d3da
0fc67a4
99cf946
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,7 +35,7 @@ | |
| path = selected; | ||
| resetDecision(); | ||
| } catch { | ||
| error = "iCloud 파일 선택을 완료하지 못했습니다. 다시 시도하십시오."; | ||
| error = "파일 선택 창을 열지 못했습니다."; | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -47,7 +47,7 @@ | |
| try { | ||
| plan = await api.planIcloudLocalCopyEviction(cloudRoot, selectedPath); | ||
| } catch { | ||
| error = "iCloud 로컬 사본 상태를 확인하지 못했습니다. 다시 시도하십시오."; | ||
| error = "iCloud 로컬 사본 상태를 확인하지 못했습니다."; | ||
| } finally { | ||
| planning = false; | ||
| } | ||
|
|
@@ -83,7 +83,7 @@ | |
| confirmation = ""; | ||
| rationale = ""; | ||
| } catch { | ||
| error = "iCloud 로컬 사본을 회수하지 못했습니다. 상태를 다시 확인하십시오."; | ||
| error = "iCloud 로컬 사본 축출을 실행하지 못했습니다."; | ||
| } finally { | ||
| executing = false; | ||
| } | ||
|
|
@@ -94,39 +94,6 @@ | |
| ? "macOS File Provider" | ||
| : "Foundation ubiquitous item"; | ||
| } | ||
|
|
||
| function uploadLabel(state: api.IcloudLocalState): string { | ||
| if (state.is_uploaded && !state.is_uploading) return "완료"; | ||
| if (state.is_uploading) return "업로드 중"; | ||
| return "미완료"; | ||
| } | ||
|
|
||
| function syncLabel(state: api.IcloudLocalState): string { | ||
| if (state.downloading_status_current && !state.is_uploaded && !state.is_uploading) { | ||
| return "로컬 최신본·업로드 미확인"; | ||
| } | ||
| if (state.is_uploaded && !state.is_uploading) return "공급자 동기화 완료"; | ||
| if (state.is_uploading) return "공급자 업로드 중"; | ||
| return "공급자 동기화 미완료"; | ||
| } | ||
|
|
||
| function blockerLabel(blocker: string): string { | ||
| const labels: Record<string, string> = { | ||
| "icloud-upload-not-confirmed": "로컬 최신본이지만 공급자 업로드가 아직 확인되지 않았습니다. 업로드 완료 후 다시 확인하십시오.", | ||
| "icloud-upload-still-running": "공급자 업로드가 진행 중입니다. 완료 후 다시 확인하십시오.", | ||
| "icloud-current-version-unconfirmed": "로컬 최신본 여부를 확인하지 못했습니다. File Provider 상태가 안정된 후 다시 확인하십시오.", | ||
| "icloud-file-provider-native-status-unavailable": "File Provider 상태 증거가 완전하지 않습니다. 잠시 후 다시 확인하십시오.", | ||
| "icloud-file-provider-sync-paused-or-unconfirmed": "File Provider 동기화가 일시중지됐거나 상태가 미확인입니다. 동기화를 재개한 후 다시 확인하십시오.", | ||
| "icloud-unresolved-conflict": "동기화 충돌이 해결되지 않았습니다. 충돌을 해결한 후 다시 확인하십시오.", | ||
| "active-file-use-detected": "현재 사용 중인 파일이라 회수할 수 없습니다. 파일을 닫은 후 다시 확인하십시오.", | ||
| "active-use-evidence-incomplete": "파일 사용 상태를 완전히 확인하지 못했습니다. 잠시 후 다시 확인하십시오.", | ||
| }; | ||
| return labels[blocker] ?? "필수 iCloud 상태 증거가 완전하지 않아 회수할 수 없습니다. 상태를 다시 확인하십시오."; | ||
| } | ||
|
|
||
| function blockerSummary(blockers: string[]): string { | ||
| return [...new Set(blockers.map(blockerLabel))].join(" "); | ||
| } | ||
| </script> | ||
|
|
||
| <div class="local-eviction-panel"> | ||
|
|
@@ -163,9 +130,8 @@ | |
| · {observationLabel(plan.icloud_state.observation_method)} | ||
| </div> | ||
| <div class="status-grid"> | ||
| <span>업로드 {uploadLabel(plan.icloud_state)}</span> | ||
| <span>공급자 상태 {syncLabel(plan.icloud_state)}</span> | ||
| <span>로컬 current {plan.icloud_state.downloading_status_current ? "예" : "아니오"}</span> | ||
| <span>업로드 {plan.icloud_state.is_uploaded && !plan.icloud_state.is_uploading ? "완료" : "미완료"}</span> | ||
| <span>최신 버전 {plan.icloud_state.downloading_status_current ? "확인" : "미확인"}</span> | ||
| <span>충돌 {plan.icloud_state.has_unresolved_conflicts ? "있음" : "없음"}</span> | ||
| <span>활성 사용 {plan.active_use.active ? "감지" : "없음"}</span> | ||
| <span>동기화 일시정지 {plan.icloud_state.is_sync_paused === false ? "아님" : "미확인/해당"}</span> | ||
|
|
@@ -228,7 +194,7 @@ | |
| </button> | ||
| </div> | ||
| {:else} | ||
| <p class="warning" role="status">현재 축출 불가: {blockerSummary(plan.blockers)}</p> | ||
| <p class="warning">현재 축출 불가: {plan.blockers.join(", ")}</p> | ||
|
Comment on lines
196
to
+197
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Changes break existing eviction UI contract test The rewritten status and error text drops Prompt for agentsWas this helpful? React with 👍 or 👎 to provide feedback. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 Info: Blocker codes now shown raw to users The deleted Was this helpful? React with 👍 or 👎 to provide feedback. |
||
| {/if} | ||
| </div> | ||
| {/if} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import { readFileSync } from "node:fs"; | ||
| import { dirname, resolve } from "node:path"; | ||
| import { fileURLToPath } from "node:url"; | ||
| import { describe, expect, it } from "vitest"; | ||
|
|
||
| const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../.."); | ||
|
|
||
| function readSource(path: string): string { | ||
| return readFileSync(resolve(repositoryRoot, path), "utf8"); | ||
| } | ||
|
|
||
| describe("BrewCleanup privacy-safe failure feedback", () => { | ||
| it("never renders arbitrary backend exception text", () => { | ||
| const source = readSource("src/lib/BrewCleanup.svelte"); | ||
| const evictionSource = readSource("src/lib/IcloudLocalEviction.svelte"); | ||
|
|
||
| expect(source).not.toContain("String(e)"); | ||
| expect(source).not.toContain("record_error"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 Info: Contract test asserts absence of substrings not just interpolations The new test at brewCleanupErrorPrivacyContract.test.ts asserts the BrewCleanup source Was this helpful? React with 👍 or 👎 to provide feedback. |
||
| expect(source).not.toContain("저장하지 못했습니다: {"); | ||
| expect(source).not.toMatch(/\{execution\.record_error\}/); | ||
| expect(evictionSource).not.toContain("String(e)"); | ||
| expect(evictionSource).not.toContain("result_record_error"); | ||
| expect(evictionSource).not.toMatch(/\{eviction\.result_record_error\}/); | ||
| expect(evictionSource).toContain("파일 선택 창을 열지 못했습니다."); | ||
| expect(evictionSource).toContain("iCloud 로컬 사본 상태를 확인하지 못했습니다."); | ||
| expect(evictionSource).toContain("iCloud 로컬 사본 축출을 실행하지 못했습니다."); | ||
| expect(source).toContain("Homebrew 정리 계획을 만들지 못했습니다."); | ||
| expect(source).toContain("Homebrew 정리를 실행하지 못했습니다."); | ||
| expect(source).toContain('role=\"alert\"'); | ||
| }); | ||
|
|
||
| it("preserves the existing judgment and execution authority calls", () => { | ||
| const source = readSource("src/lib/BrewCleanup.svelte"); | ||
|
|
||
| expect(source).toContain("api.judgeBrewCleanup()"); | ||
| expect(source).toContain("api.executeBrewCleanup("); | ||
| expect(source).toContain("submittedJudgment.plan_fingerprint"); | ||
| expect(source).toContain("submittedJudgment.judgment_id"); | ||
| }); | ||
| }); | ||
|
seonghobae marked this conversation as resolved.
seonghobae marked this conversation as resolved.
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 Info: Unused catch binding kept inconsistently in BrewCleanup
In BrewCleanup.svelte and
:75the catch clauses still bind the exception (catch (e)) even thougheis no longer referenced, whereas the equivalent edits insrc/lib/IcloudLocalEviction.svelte:37,49,85switched to the optional-catch-binding form (catch {). This is only a style inconsistency (and potentially a lint warning depending on the project's eslint config), not a runtime bug.Was this helpful? React with 👍 or 👎 to provide feedback.