feat: share the proposal board across chats
The unfinished-proposal board is now visible to every conversation, with entries marked scope=own/scope=other (chat type only, no IDs), so anyone can see what the single worker is busy with. All actions remain owner-only, and pending reminders still target only the owner.
This commit is contained in:
@@ -397,18 +397,28 @@ test("proposals are owned per chat+user: a second user in the same chat cannot c
|
||||
assert.equal(harness.proposals.get(proposal.id)!.status, "proposed");
|
||||
assert.equal(await harness.manager.finish("webhook", "chat-1", "user-b"), false);
|
||||
assert.equal(await harness.manager.stop("webhook", "chat-1", "user-b"), false);
|
||||
assert.equal(harness.manager.listProposals("webhook", "chat-1", "user-b").length, 0);
|
||||
|
||||
// The board is globally visible: both users see the same proposal, tagged by scope.
|
||||
assert.equal(harness.manager.listProposals("webhook", "chat-1", "user-b").length, 1);
|
||||
assert.equal(harness.manager.listProposals("webhook", "chat-1", "user-a").length, 1);
|
||||
|
||||
assert.equal(await harness.manager.confirm("webhook", "chat-1", "user-a"), true);
|
||||
assert.equal(harness.proposals.get(proposal.id)!.status, "working");
|
||||
|
||||
await harness.manager.prompt(request("hello owner", "user-a"));
|
||||
const aPrompt = readLog(harness.logFile).find((entry) => entry.method === "session/prompt" && entry.text?.startsWith("[User message]\nhello owner"));
|
||||
assert.ok(aPrompt?.text);
|
||||
assert.match(aPrompt.text!, /scope=own/);
|
||||
|
||||
await harness.manager.prompt(request("hello again", "user-b"));
|
||||
const bPrompt = readLog(harness.logFile).find((entry) => entry.method === "session/prompt" && entry.text?.startsWith("[User message]\nhello again"));
|
||||
assert.ok(bPrompt?.text);
|
||||
// Debugging phase: non-owners also see the live card, marked as another user's proposal.
|
||||
assert.match(bPrompt.text!, /Test proposal/);
|
||||
assert.match(bPrompt.text!, /another user's proposal/);
|
||||
// The shared board tags the entry scope=other with a chat-type label; no raw user ID leaks.
|
||||
assert.match(bPrompt.text!, /scope=other chat=direct/);
|
||||
assert.doesNotMatch(bPrompt.text!, /user-a/);
|
||||
|
||||
assert.equal(await harness.manager.stop("webhook", "chat-1", "user-b"), false);
|
||||
assert.equal(harness.proposals.get(proposal.id)!.status, "working");
|
||||
|
||||
+20
-4
@@ -658,11 +658,27 @@ test("the list panel orders pending first, then working, queued, proposed, and r
|
||||
.map((section) => reply.indexOf(section));
|
||||
assert.ok(order.every((index) => index >= 0), reply);
|
||||
assert.deepEqual([...order].sort((a, b) => a - b), order);
|
||||
assert.match(reply, /p-pending「待确认任务」:做了一半(问你:继续吗?)/);
|
||||
assert.match(reply, /p-pending「待确认任务」(你的):做了一半(问你:继续吗?)/);
|
||||
assert.match(reply, /\/finish 结束/);
|
||||
assert.match(reply, /p-working「干活中」正在执行/);
|
||||
assert.match(reply, /p-cancelled「取消任务」已取消/);
|
||||
assert.match(reply, /p-finished「旧任务」已完成/);
|
||||
assert.match(reply, /p-working「干活中」(你的)正在执行/);
|
||||
assert.match(reply, /p-cancelled「取消任务」(你的)已取消/);
|
||||
assert.match(reply, /p-finished「旧任务」(你的)已完成/);
|
||||
});
|
||||
|
||||
test("the list panel shows other members' proposals without exposing their identity", async () => {
|
||||
const { runtime, gateway } = createGateway();
|
||||
const adapter = recordingAdapter();
|
||||
runtime.proposals = [
|
||||
fakeProposal({ id: "p-mine", title: "我的任务", status: "working" }),
|
||||
fakeProposal({ id: "p-other", title: "别人的任务", status: "pending", ownerChatKey: "qq:group:g-secret-9", requesterUserId: "someone-else", pending: { summary: "做到一半", receivedAt: 5 } })
|
||||
];
|
||||
|
||||
const list = await gateway.receive(message("/list"), adapter, { synchronous: true });
|
||||
const reply = list.reply || "";
|
||||
assert.match(reply, /p-other「别人的任务」(其他成员):做到一半/);
|
||||
assert.match(reply, /p-mine「我的任务」(你的)正在执行/);
|
||||
assert.doesNotMatch(reply, /someone-else/);
|
||||
assert.doesNotMatch(reply, /g-secret-9/);
|
||||
});
|
||||
|
||||
test("synchronous work sends no delivery messages", async () => {
|
||||
|
||||
Reference in New Issue
Block a user