You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Make agent approval cards readable at a glance #173
Make every agent approval card readable by a non-technical user at a glance: who is asking, what kind of object (credential, value, group) changes, exactly what changes, and what happens on approval. Nothing on a card may be cut off silently.
Context
During the v0.3.0 device check (Build, notarize and publish v0.3.0 #169), the maintainer could not tell from a create card whether a credential or a group was being created, or what TOKEN · 28 B · RELEASE_CHECK_TOKEN meant.
An image-only usability review (Claude Opus 5.5, xhigh) of 15 cards in English and Simplified Chinese, rendered from 425e29e, found 6 issues that can cause a wrong approval, 7 that can cause a wrong denial or a misread outcome, and several jargon and consistency problems. The review and the images stay outside the repository; this issue carries everything needed.
Reads of this one credential, by any agent or command of this macOS user, for 30 minutes. Never writes.
When the countdown ends
The request expires. Nothing is delivered or written; the agent is told it expired.
Esc
Closes the card. The request stays in Pending requests until it expires.
Delete
Moves to the Recycle Bin for 30 days, restorable there, then removed permanently. Agents cannot use or see it meanwhile.
Replacing a value
The old value is overwritten. There is no history.
Group merge
Not undoable automatically.
Permission of an agent-created credential
Ask every time.
Re-authenticate after a cancelled Touch ID
Retries the decision the user originally chose (once or 30 minutes).
Temporary files
Removed after at most 5 minutes.
Executor: Claude · claude-opus-5-5 · xhigh. Display and copy only.
Decisions
Titles name the object (zh / en):
read: {请求方}想使用凭证「{名称}」 / {Requester} wants to use the credential “{Name}”
create: 想新建凭证「…」 / wants to create the credential “…”
value-only change: 想替换凭证「…」的值 / wants to replace the value of “…”
other changes: 想修改凭证「…」 / wants to change the credential “…”
delete: 想删除凭证「…」 / wants to delete the credential “…”
organize: 想调整分组(共 N 步) / wants to reorganize your groups (N steps)
Credential and group names use 「」 in Chinese and “ ” in English everywhere, and wrap as a whole.
Read cards:
The default view shows the full command under 要运行的命令 / Command to run, wrapping as needed. Commands longer than 4 lines go in a scroll area with a visible scroll indicator, and are never truncated in the middle.
Add 批准后这个命令会拿到 / If you allow, this command receives. Name each component and how it is delivered (rule 5).
The stated purpose follows the command as 对方说的用途(未核实) / Stated purpose (not verified).
Details keep only 运行目录 / Runs in and 请求方 / Requested by, written as "name provided by the requester; Ask Key can't verify it".
Under the 30-minute button, add one line stating its scope from the table above.
Write cards use fixed section headings, in this order: 对方说的用途(未核实); for modify, a summary line 会改动:… · 不变:… / Changes: … · Unchanged: …; 凭证内容(N 项) / Items (N); 给 Agent 的使用说明 / Instructions for agents; 分组 / Group; then 批准后 / After you approve for create and delete. Create states that the credential's permission will be Ask every time. Delete states Recycle Bin, 30 days and restore. Value replacement states that the old value is overwritten and the new value comes from the requester.
Modify: each component row and each section carries a status tag, as defined in rule 6. Sections that do not change collapse into the summary line instead of repeating their content. Instructions show the old and new text, labelled 原来 / 改为 (Before / After).
Component row: {name} · {N} 字节 · {delivery in plain words}, with English bytes and thousands separators. The delivery wording is:
使用时作为环境变量 X 交给程序 / given to programs as environment variable X
使用时作为临时文件交给程序(路径在 X) / given to programs as a temporary file (path in X)
只存在请旨里,不交给任何 Agent / kept in Ask Key only, never given to agents
A replaced value reads 旧值 40 字节 → 新值 52 字节(新值由 {请求方} 提供).
Status tags: small labels on neutral backgrounds; color carries risk, not novelty.
不变 / Unchanged: grey
已修改 / Changed: blue
新增 / New: green
新分组 / New group, followed by 批准后创建 / created when you approve: neutral (not red)
替换 / Replaced: orange
移除 / Removed: red
无变化 / No change: grey
合并 / Merge: orange
Value preview box:
Rename 待写入的冻结内容 to 要保存的值(由 {请求方} 提供) / Value to save (provided by {Requester}), or 新值 / New value.
Show it only when a value is created or replaced, with one row per new or replaced component.
Rename the button to 验证后查看 / Authenticate to View, and the note to 批准后保存的就是这个值。查看要再验证一次,查看不等于批准。
Organize:
Steps read as full sentences. Example: 4. 删除分组「Temp」, then on the next line 组里 1 个凭证不会被删除,会变成「未分组」.
Use 其中 N 个对 Agent 隐藏 / N hidden from agents, and omit the clause at zero. Counts reflect the state at that step.
An existing-group create starts with the 无变化 tag and states that nothing is created or changed.
A merge starts with the 合并 tag and states the result: the source disappears, the target has N credentials, and the merge cannot be undone.
Drop the redundant 新分组 · 批准后创建 subline under 新建分组 steps.
Never cut content silently: every capped region (command, instructions, group, organize steps) shows a persistent scroll indicator when it overflows, plus a line such as 还有 N 步,向下滚动查看 / N more steps — scroll to see them. Titles carry totals (N 项 / N 步). On long cards, shrink the top icon.
Buttons:
read: 允许本次 / 30 分钟内都允许 / 拒绝, in English Allow Once / Allow for 30 Minutes / Deny
create: 新建凭证 / Create Credential
modify: 保存修改 / Save Changes, or 替换值 / Replace Value for value-only changes
delete: 移到回收站 / Move to Trash, with destructive styling, not the default button
organize: 执行这 N 步 / Apply N Steps, with destructive styling when it deletes or merges groups
after a cancelled Touch ID: 重新验证,允许本次 or 重新验证,30 分钟内都允许, matching the original choice
English buttons use title case. The footer reads mm:ss 后自动失效 · Esc 先收起,稍后在「待处理请求」里决定 / Expires in mm:ss · Esc to decide later in Pending requests.
Pending requests list: use the same object-naming verbs as the titles.
Simplified Chinese copy keeps the App's terms 凭证 and Agent.
Data limits (decided 2026-10-09)
The write summary carries one digest over all components. A modified component whose size and delivery are unchanged, while another component did change, gets the tag 可能已替换 / May be replaced (orange) and the line 大小和交付方式没变,无法确认值是否被替换;可验证后查看 / Same size and delivery; Ask Key can't tell whether the value was replaced. Authenticate to view. It is also listed in the value box. Per-component digests are a separate follow-up after v0.3.0.
Read cards list one row per delivered variable, under the credential name: 「X」· 作为环境变量 V. A file row adds (路径在 V,最多 5 分钟后删除). When a multi-item credential has no mappings before approval, the card shows one row: 「X」里设为交给程序的所有项(具体名称批准后才能看到) / The items of “X” that are set to be given to programs (names are shown after you approve). A credential with no delivery shows 不交给这个命令任何值 / Nothing from this credential is given to the command.
AppDelegate+Approval.swift (the revealed-value text) stays unchanged. The value box's masked state, heading, button and note follow Decision 7.
Second review (2026-10-09)
The image-only re-review found the remaining issues listed in the PR #175 review comment. The PR also implements #174 (per-component value digests in the App-side write summary) so tags are exact; this extends Scope to Sources/AskKeyBroker/CredentialComponents.swift (summary struct only), the summary construction in Sources/AskKeyVault/Vault+AgentWriteFreeze.swift, and Vault tests. Approval digests and commit stay unchanged.
Scope
May change: the files listed in Context, new presentation helpers next to them, Localizable.xcstrings (English and Simplified Chinese), tests in Tests/AskKeyAppTests/, the approval screenshot scenarios in Tests/AskKeyE2ETests/ScreenshotE2ETests.swift and Tests/AskKeyTestSupport/E2EBrokerScenario.swift, and scripts/e2e-report.py (allowlist only).
Must not touch: the Broker, Vault, approval digests and summaries (BrokerCredentialWriteSummary, BrokerOrganizationSummary contents), decisions and authentication, timed-allowance behavior, product identifiers. Do not add data the card cannot already derive from the existing summary and request; if a decision needs new data, ask through Orca.
Acceptance
swift build
swift test --filter <changed suites>
python3 scripts/check_hygiene.py && python3 scripts/check_module_deps.py
Tests cover each card type in English and Simplified Chinese: read (default, details, file delivery, cancelled authentication, without the timed option), create (environment, file and App-only components), modify (metadata only, value only, component added), delete, and organize (regular, existing group and merge, 12 steps). They assert titles, section headings, tags, button titles, and the overflow hint, and that every card stays within 680 points with actions visible.
CI build-and-test and basic-ui-flows green; the approval screenshot tests themselves pass and the images are inspected.
The planner re-renders the same 15 cards and runs the same image-only review; no first- or second-level finding remains.
Goal
Make every agent approval card readable by a non-technical user at a glance: who is asking, what kind of object (credential, value, group) changes, exactly what changes, and what happens on approval. Nothing on a card may be cut off silently.
Context
TOKEN · 28 B · RELEASE_CHECK_TOKENmeant.425e29e, found 6 issues that can cause a wrong approval, 7 that can cause a wrong denial or a misread outcome, and several jargon and consistency problems. The review and the images stay outside the repository; this issue carries everything needed.Sources/AskKeyAppKit/App/FrozenAgentApprovalPrompt.swift,ApprovalPromptContent.swift,FrozenWriteApprovalContent.swift,FrozenWriteSummaryContent.swift,FrozenOrganizationApprovalContent.swift,FrozenApprovalActions.swift,Views/Credentials/PendingRequestPresentation.swift,Localizable.xcstrings.Facts verified in code (use these in the copy):
Executor: Claude ·
claude-opus-5-5· xhigh. Display and copy only.Decisions
Titles name the object (zh / en):
{请求方}想使用凭证「{名称}」/{Requester} wants to use the credential “{Name}”想新建凭证「…」/wants to create the credential “…”想替换凭证「…」的值/wants to replace the value of “…”想修改凭证「…」/wants to change the credential “…”想删除凭证「…」/wants to delete the credential “…”想调整分组(共 N 步)/wants to reorganize your groups (N steps)Credential and group names use 「」 in Chinese and “ ” in English everywhere, and wrap as a whole.
Read cards:
Write cards use fixed section headings, in this order: 对方说的用途(未核实); for modify, a summary line 会改动:… · 不变:… / Changes: … · Unchanged: …; 凭证内容(N 项) / Items (N); 给 Agent 的使用说明 / Instructions for agents; 分组 / Group; then 批准后 / After you approve for create and delete. Create states that the credential's permission will be Ask every time. Delete states Recycle Bin, 30 days and restore. Value replacement states that the old value is overwritten and the new value comes from the requester.
Modify: each component row and each section carries a status tag, as defined in rule 6. Sections that do not change collapse into the summary line instead of repeating their content. Instructions show the old and new text, labelled 原来 / 改为 (Before / After).
Component row:
{name} · {N} 字节 · {delivery in plain words}, with Englishbytesand thousands separators. The delivery wording is:X交给程序 / given to programs as environment variableXX) / given to programs as a temporary file (path inX)A replaced value reads 旧值 40 字节 → 新值 52 字节(新值由 {请求方} 提供).
Status tags: small labels on neutral backgrounds; color carries risk, not novelty.
Value preview box:
Organize:
Never cut content silently: every capped region (command, instructions, group, organize steps) shows a persistent scroll indicator when it overflows, plus a line such as 还有 N 步,向下滚动查看 / N more steps — scroll to see them. Titles carry totals (N 项 / N 步). On long cards, shrink the top icon.
Buttons:
English buttons use title case. The footer reads
mm:ss 后自动失效 · Esc 先收起,稍后在「待处理请求」里决定/Expires in mm:ss · Esc to decide later in Pending requests.Pending requests list: use the same object-naming verbs as the titles.
Simplified Chinese copy keeps the App's terms 凭证 and Agent.
Data limits (decided 2026-10-09)
V. A file row adds (路径在V,最多 5 分钟后删除). When a multi-item credential has no mappings before approval, the card shows one row: 「X」里设为交给程序的所有项(具体名称批准后才能看到) / The items of “X” that are set to be given to programs (names are shown after you approve). A credential with no delivery shows 不交给这个命令任何值 / Nothing from this credential is given to the command.AppDelegate+Approval.swift(the revealed-value text) stays unchanged. The value box's masked state, heading, button and note follow Decision 7.Second review (2026-10-09)
The image-only re-review found the remaining issues listed in the PR #175 review comment. The PR also implements #174 (per-component value digests in the App-side write summary) so tags are exact; this extends Scope to
Sources/AskKeyBroker/CredentialComponents.swift(summary struct only), the summary construction inSources/AskKeyVault/Vault+AgentWriteFreeze.swift, and Vault tests. Approval digests and commit stay unchanged.Scope
May change: the files listed in Context, new presentation helpers next to them,
Localizable.xcstrings(English and Simplified Chinese), tests inTests/AskKeyAppTests/, the approval screenshot scenarios inTests/AskKeyE2ETests/ScreenshotE2ETests.swiftandTests/AskKeyTestSupport/E2EBrokerScenario.swift, andscripts/e2e-report.py(allowlist only).Must not touch: the Broker, Vault, approval digests and summaries (
BrokerCredentialWriteSummary,BrokerOrganizationSummarycontents), decisions and authentication, timed-allowance behavior, product identifiers. Do not add data the card cannot already derive from the existing summary and request; if a decision needs new data, ask through Orca.Acceptance
build-and-testandbasic-ui-flowsgreen; the approval screenshot tests themselves pass and the images are inspected.Blocked by
None. Blocks #169.