Skip to content

feat(tasks): track handoffs and requester acceptance (#54) - #110

Closed
hsliuustc0106 wants to merge 3 commits into
mainfrom
fix-54-task-lifecycle
Closed

hsliuustc0106 wants to merge 3 commits into
mainfrom
fix-54-task-lifecycle

Conversation

@hsliuustc0106

Copy link
Copy Markdown
Collaborator

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 to main after 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-derived requesterId decides (bot/forbidden otherwise) — the #52 rule.

What

  • core/src/host/tasks.js (new host module, installed after reach): owns state.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/failed terminal; accepted reachable only from result-ready. Every transition appends a per-status actor entry; ids are task-<hex>.
  • Block/resume wiring (three guarded hooks in src/host/hooks.js): a held send from the responsible Bot blocks the working task with the approval id; the owner's flybot/decide resumes (approve) or cancels (reject) it; deleting the responsible Bot fails its open tasks.
  • Endpoints (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.
  • Store: tasks: {} literal + JSDoc + adopt clause (src/host/store.js).
  • Deferred honestly: chat task cards / activity view are [Team] Add a human-readable authorization and task audit trail #57's scope; auto-detection of result-ready from round replies and exchange threads lands with [Team] Recover task handoffs without duplicate work #55's recovery work (the state machine already has the result-ready gate; task-return carries the summary today). Team mode stays disabled.

Fixes #54

Verification

Tip SHA: a76230c67ea7f72cb880526663926bd450b7394a (base d464235).

  • Fail-without-change: core/test/tasks.test.js written first — 7/7 fail at base d464235 (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, corrupt state.tasks resets.
  • 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).
  • Smoke (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

  • New patches format: new files are stored whole in patches/ds-bot/files/ (files/src/host/tasks.js, files/test/tasks.test.js) — no topics.json entry.
  • The rewritten generate crashes if an untracked directory sits under core/ (it copies the tree into files/) — keep the harness symlink out of the tree while running it. check is tracked-files-only and tolerates it.
  • Red-at-base re-check: worktree at d464235, copy only core/test/tasks.test.js in, run — expect 0 pass / 7 fail on Unknown endpoint task-create.

hsliu_ustc added 2 commits October 16, 2026 00:22
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
@hsliuustc0106

Copy link
Copy Markdown
Collaborator Author

Review round 1 (independent Verifier) — verdict PASS on a76230c; all gates re-run by the Verifier (verify exit 0, 704/704, red-at-base reproduced 0/7), item-by-item acceptance table in the report. Follow-ups addressed before the push:

Delta re-review requested at the new tip (delta: one new test + one strengthened assertion + the CHANGELOG entry).

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
@hsliuustc0106

Copy link
Copy Markdown
Collaborator Author

Correction: the follow-up commit initially landed as 31fcabc/3a9a27f with two packaging mistakes (patches stale after the test edit; the harness symlink swept back into the commit). Final tip: 588fa9d — patches check ok, arch-docs OK, npm run verify exit 0, no symlink in the tree. Delta vs the PASSed a76230c: one new test (reject → cancelled, terminal), a strengthened restart assertion, and the CHANGELOG entry. Re-review of that delta requested at 588fa9d.

@hsliuustc0106

Copy link
Copy Markdown
Collaborator Author

Delta re-review — verdict PASS on 588fa9d (supersedes the round-1 PASS at a76230c).

  • Delta verified as claimed: 3 files (reject test, restart assertion, CHANGELOG); src/ byte-identical; npm run verify exit 0 (705/705 core incl. the new test); patches ok; no harness leak in the tree.
  • The reject test exercises taskDecided's cancel branch through the real channel (decide reject → cancelled → further moves bot/stale).
  • Reviewer's corrections accepted: the new test is carried whole in patches/ds-bot/files/test/tasks.test.js (new format), and a test-only delta carries no new fail-without-change obligation (the original feature red run at d464235 stands).
  • Carry-overs remain ledgered in Task lifecycle: stamp meta.taskId on held sends; clarification state + workBotId (remainder of #111, needs #55) #111 (per-Bot hold linkage, prune window, authz prefix set, clarification + workBotId).

Implementer agrees on 588fa9d. Ready for maintainer review; no merge action from my side.

@hsliuustc0106
hsliuustc0106 force-pushed the fix-53-context-sharing branch 2 times, most recently from 2657bf8 to f1b034c Compare October 15, 2026 17:38
Base automatically changed from fix-53-context-sharing to main October 15, 2026 17:42
@Birfy

Birfy commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Rebased onto current main with grant-model review fixes as #121 (Birfy:cursor/rebase-110-task-lifecycle-dae8). Please prefer that PR; this one can be closed once #121 is the path forward. Credit remains yours for the original work. Deferred from review: grant-tied briefAllowed (noted in team.md); in-chat task cards stay #57 / #111.

@Birfy Birfy closed this in #121 Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Team] Persist a minimal collaboration task lifecycle

2 participants