Q153: the approval button that reviews a request is called Review, and leads to where the request can change

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-09 01:32:09 -04:00
1 parent e8634afb82
commit af831abd53
3 files changed
+32 -5

No files matched your search

+3
View File
@@ -40,6 +40,9 @@ export const zh: Record<string, string> = {
"Reopen": "重新打开",
"Back to backlog": "退回待办",
"Delete this task?": "删除这个任务?",
"Review": "审阅",
"Edit the task": "编辑任务",
"Changing the task replaces this request with a fresh one.": "修改任务会用新的申请替换这一项。",
"Delete task": "删除任务",
"Nothing else is affected.": "不影响其他内容。",
"{n} sessions and their action records are deleted.": "{n} 次会话及其操作记录将被删除。",
+11 -5
View File
@@ -116,7 +116,7 @@ export function ApprovalsPage({ snapshot, actions, navigate, focus }: PageProps)
isBot={approval.requestedByType === "agent"}
onApprove={() => decide(approval, "approved")}
onDecline={() => decide(approval, "declined")}
onEdit={() => setEditingId(approval.id)}
onReview={() => setEditingId(approval.id)}
/>
))}
@@ -191,7 +191,12 @@ function ApprovalDetailDialog({
<>
<span style={{ color: "var(--text-3)" }}>{t("Source")}</span>
{approval.sourceEntityType === "task" && approval.sourceEntityId
? <button type="button" className="link-button" onClick={() => onOpenTask(approval.sourceEntityId!)}>{t("Open task")}</button>
? (
<span>
<button type="button" className="link-button" onClick={() => onOpenTask(approval.sourceEntityId!)}>{t("Edit the task")}</button>
<span style={{ color: "var(--text-3)" }}> · {t("Changing the task replaces this request with a fresh one.")}</span>
</span>
)
: <span>{humanizeKind(approval.sourceEntityType)}</span>}
</>
)}
@@ -254,14 +259,15 @@ function ApprovalRow({
isBot,
onApprove,
onDecline,
onEdit,
onReview,
}: {
approval: ApprovalRecord;
requester: string;
isBot: boolean;
onApprove: () => void;
onDecline: () => void;
onEdit: () => void;
/** Opens the request to read it in full and decide with notes; what is requested is changed at its source. */
onReview: () => void;
}) {
const tone = RISK_TONES[approval.risk];
if (!tone) throw new Error("Approval risk tone is missing.");
@@ -297,7 +303,7 @@ function ApprovalRow({
</div>
<div style={{ display: "flex", flexDirection: "column", gap: 6, alignItems: "flex-end" }}>
<Button tone="primary" onClick={onApprove}>{t("Approve")}</Button>
<Button onClick={onEdit}>{t("Edit")}</Button>
<Button onClick={onReview}>{t("Review")}</Button>
<Button tone="ghost" onClick={onDecline}>{t("Decline")}</Button>
</div>
</div>
+18
View File
@@ -97,6 +97,24 @@ test("the pinned CEO conversation is the Messages front door", async () => {
return [task.writingMode, task.requiresFilesystem];
});
expect(edited).toEqual(["technical", true]);
// A pending request opens for review: read it in full and decide with notes; nothing there pretends to edit it.
await taskDialog.getByRole("button", { name: "Close" }).click();
await page.evaluate(async () => {
const api = (window as unknown as { agentCompany: {
loadSnapshot: () => Promise<{ ok: true; data: { activeOrgId: string } }>;
createApproval: (input: unknown) => Promise<{ ok: boolean }>;
} }).agentCompany;
const orgId = (await api.loadSnapshot()).data.activeOrgId;
await api.createApproval({ orgId, kind: "budget_increase", title: "Raise the ads budget", details: "From $200 to $500.", risk: "medium", requestedByType: "system", requestedById: null });
});
await page.getByRole("button", { name: "Approvals" }).click();
await expect(page.getByRole("button", { name: "Edit", exact: true })).toHaveCount(0);
await page.getByRole("button", { name: "Review" }).first().click();
const review = page.getByRole("dialog", { name: "Raise the ads budget" });
await expect(review.getByRole("textbox", { name: "Decision notes" })).toBeVisible();
await review.getByRole("button", { name: "Close" }).click();
await page.getByRole("button", { name: "Work" }).click();
await page.getByRole("button", { name: /Operationalize goal: Ship the FlowPilot MVP\./ }).first().click();
// Blocking says why on the task and stops it; work can also move backwards.
await taskDialog.getByRole("button", { name: "Block", exact: true }).click();
await taskDialog.getByRole("textbox", { name: "Why is it blocked?" }).fill("Waiting for the legal review.");