Repository navigation
feat(tasks): track handoffs and requester acceptance (#54) - #110
hsliuustc0106 wants to merge 3 commits into
Conversation
A held send was decidable by anyone who could reach the decide endpoint: the record carried no owner, no request binding, and no origin, so 'my owner approved' in the message text was as good as an approval, and one member could decide another's queued send on a multi-member host. Holds now stamp server-derived provenance: the sender Bot's owner, a sha256 over the request content, and the origin (via/hop/audience). flybot/decide passes authz for any signed-in member, and hooks binds the decision to the sender Bot's owner's session (bot/forbidden otherwise, bot/unauthorized without a session; a body actorId grants nothing). Releasing revalidates: a changed request, a deleted sender or target Bot, a Bot that changed owners, or a demoted Chief marks the record stale instead of dispatching; deleteBot and setMain invalidate affected holds eagerly. Under enforcement the pending list shows a member only their own holds, and the approval card shows who sent the request and when it was relayed. Legacy records without the version stamp keep working and only miss the tamper check. Team mode stays disabled; this is the held-send half of approval binding (docs/subsystems/team.md gate 3). social/decide-approval stays a deployment-wide plugin write. Fixes #52
On a host with member sessions, a member Bot's group Session began with its owner's own-chat brief whoever else sat in the room, the memory review read every human as 'the user' and could publish team memory from another owner's room, list_bots disclosed other owners' folders and instructions, and a chat reference chip copied any Session's snapshot to every recipient. Now the own-chat brief rides into a room with more than one owner only when the Bot's owner shares it there (share-brief, a per-room briefShared flag on the participant that leaving drops); a review that reads a cross-owner room keeps entries in the Bot's own memory and reads only its own owner as the user; list_bots shows another owner's Bot by name, role and model only; and reference chips in send and room-post must resolve through sessionOwnedBy for the author. Previously received messages are not retroactively unseen; the secrets surface stays blocked-shared. Team mode stays disabled; this is the context half of the authority contract (docs/subsystems/team.md). Fixes #53
|
Review round 1 (independent Verifier) — verdict PASS on
Delta re-review requested at the new tip (delta: one new test + one strengthened assertion + the CHANGELOG entry). |
a76230c to
3a9a27f
Compare
A request was only chat text: nothing tracked whether work was claimed, running, blocked on an approval, finished, or accepted, and any member could not be refused from moving someone else's work along. state.tasks (additive, corrupt values reset) records each task with a stable id, the server-derived requester, the responsible Bot, per-status actor entries, and pointers to the originating conversation — a summary, never private transcripts. The state machine is open → claimed → working → blocked ⇄ working → result-ready → accepted, with cancelled and failed terminal and accepted reachable only from result-ready, so a failed or cancelled task can never display as accepted. A held send (#52 card) blocks the working task with the approval id; the owner's decision resumes or cancels it; deleting the responsible Bot fails its open tasks. Endpoints pass authz for any signed-in actor and are record-checked in tasks.js (requester-only moves). Task views in the chat are #57; team mode stays disabled. Fixes #54
3a9a27f to
588fa9d
Compare
|
Correction: the follow-up commit initially landed as |
|
Delta re-review — verdict PASS on
Implementer agrees on |
2657bf8 to
f1b034c
Compare
|
Rebased onto current |
Why
A request was only chat text: nothing recorded whether work was claimed, running, blocked on an approval, finished, or accepted, and nothing refused one member from moving another's work along. #54's acceptance — created, claimed, worked, blocked on approval, resumed, returned, accepted by the requester; wrong-owner moves refused; a failed/cancelled task can never display as accepted — is enforced here structurally.
Stacked on #101 (
fix-53-context-sharing, d464235 → PASS). Retarget tomainafter the stack merges. Team mode stays disabled: in the single-human product every transition is the requester's own; with member sessions the record's server-derivedrequesterIddecides (bot/forbiddenotherwise) — the #52 rule.What
core/src/host/tasks.js(new host module, installed afterreach): ownsstate.tasks(additive — corrupt values reset in the store's adopt clause; 200 terminal records kept, active never pruned). State machine:open → claimed → working → blocked ⇄ working → result-ready → accepted;cancelled/failedterminal; accepted reachable only from result-ready. Every transition appends a per-status actor entry; ids aretask-<hex>.src/host/hooks.js): a held send from the responsible Bot blocks the working task with the approval id; the owner'sflybot/decideresumes (approve) or cancels (reject) it; deleting the responsible Bot fails its open tasks.src/host/channel.js):tasks,task-create,task-accept,task-start,task-return,task-accept-result,task-cancel— authz passes any signed-in actor; the record's requester check lives in tasks.js. Records store pointers and a copied summary, never private transcripts.tasks: {}literal + JSDoc + adopt clause (src/host/store.js).result-readygate;task-returncarries the summary today). Team mode stays disabled.Fixes #54
Verification
Tip SHA:
a76230c67ea7f72cb880526663926bd450b7394a(based464235).core/test/tasks.test.jswritten first — 7/7 fail at based464235(mechanically re-verified: fresh worktree at the base, only the test copied in, 0 pass), all green at the tip. Matrix: happy path (open→claimed→working→result-ready→accepted, then stale), wrong-member accept/claim/cancel forbidden, accept-before-result + post-terminal moves stale, held-send block → owner approve resumes, responsible-Bot deletion fails the task, restart persistence, corruptstate.tasksresets.npm run verify— exit 0 (core 704/704, social, tree, client --check, patches check, arch-docs OK 40 files; core-host.md/core-client.md + team.md updated in-commit).index.js/src/host/changed): ports 3091/8791 — all 40 steps passed; bench stopped, data removed.Not run: DSH Desktop, real-model steward, Windows.
Reviewer notes
patches/ds-bot/files/(files/src/host/tasks.js,files/test/tasks.test.js) — no topics.json entry.generatecrashes if an untracked directory sits undercore/(it copies the tree intofiles/) — keep the harness symlink out of the tree while running it.checkis tracked-files-only and tolerates it.d464235, copy onlycore/test/tasks.test.jsin, run — expect 0 pass / 7 fail onUnknown endpoint task-create.