Repository navigation
S16: persistent Bots from exact proposals and bounded Bot-to-Bot delegation - #447
Conversation
…t delegation BOT16-01 and DELEG16-01 behind explicit bots: true (set by the generated installer): - protected Bot directory (bots.sqlite): profiles, exact proposals bound to the policy revision and team resources, immutable conversation-to-Bot bindings - one-press acceptance installs a standing-policy revision that adds the Bot to every team rule naming the main Bot; POLICY keeps running work across a revision that only changes other Bots' membership - one Bot per conversation with its route, responsibility and excluded resources - archive fences the Bot's catalog identity, stops its unfinished work, pauses its routines and refuses new messages; restore reactivates the same identity - credential-free duplicate, export and import, each as a new proposal - delegate tool: peer and temporary assignments inside the parent's frozen scope, slices charged to the parent, own drain pool, TEAM handoff and DATA15 ancestry checked before every child send; stop cascades from parent to children - main Bot's propose_bot tool drafts an inert proposal card in the chat - s16-client-bots/v1 owner API and React Bots pages, roster, Talk to choice, proposal and child cards in English and Thai Closes #412 Closes #413
Adds ADR 0088, the s16-bots/v1 contract summary, CONTEXT terms for persistent Bots, proposals and temporary workers, and marks BOT16-01/DELEG16-01 as implemented-deterministic in the S16 roadmap and coverage index.
[High impact] The fixes appear safe to merge; the remaining main Bot conversation-list issue is non-blocking. Findings
Fix with agent prompt### Issue 1
src/s16/bots/service.ts:undefined-140
The main Bot's detail page never lists its ordinary conversations. `detail` reads only explicit bindings, while main-Bot conversations intentionally stay unbound-even `conversation.bind` returns without inserting one for the main Bot. Include unbound conversations when building the main Bot's recent list.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.SummaryThe fixes in
|
| detail(owner: Owner, botId: string): BotDetail { | ||
| this.#owner(owner); const record = this.profile(botId); | ||
| if (!record || !this.#bots(owner).some(r => r.id === botId)) throw new AppError("not_found", 404); | ||
| return { contract: "s16-client-bot/v1", bot: this.#view(record, this.options.selections(owner)), conversations: this.options.conversations.recent(owner, this.boundConversations(botId)).slice(0, 32), impact: this.impact(owner, botId) }; |
There was a problem hiding this comment.
Main Bot conversations are missing
The main Bot's detail page never lists its ordinary conversations. detail reads only explicit bindings, while main-Bot conversations intentionally stay unbound—even conversation.bind returns without inserting one for the main Bot. Include unbound conversations when building the main Bot's recent list.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/s16/bots/service.ts
Line: 140
Comment:
**Main Bot conversations are missing**
The main Bot's detail page never lists its ordinary conversations. `detail` reads only explicit bindings, while main-Bot conversations intentionally stay unbound—even `conversation.bind` returns without inserting one for the main Bot. Include unbound conversations when building the main Bot's recent list.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
Fixed in c6b00bb: the main Bot's detail lists recent top-level conversations whose Bot resolves to it. Test added.
- POLICY: a work stays current only when every revision since its own is a membership-only change; an intervening reinstall keeps it stale - Bot commands commit their change and receipt together; an interrupted archive keeps its request ID until stops and routine pauses finish, and its retry or a restore finishes them over all of the Bot's conversations - interpretation uses the conversation Bot's route; a temporary worker keeps its parent work's route in the pin - children run only in computer sessions no ordinary request may hold; a new assignment refuses capacity_busy when none is free - pending proposals are filtered before the page bound; the main Bot page lists its unbound conversations and its export carries a usable name - the client holds one send lock through the Bot binding and binds the chosen Bot before opening a routine
|
@greptileai review the fixes in c6b00bb |
Closes #412
Closes #413
Refs #392
What
Behind explicit
bots: true(set by the generated installer), following the owner's 2026-11-07 decisions:bots.sqlite) holds profiles, exact proposals and immutable conversation-to-Bot bindings. A Bot is created only by one-press acceptance of an exact proposal (proposalHashbinds the draft, the policy revision and the listed team resources) from the New Bot form or from the chat card the main Bot drafts withpropose_bot. Acceptance installs one standing-policy revision that adds the Bot to every team rule naming the main Bot (team defaults); exclusions are refused by the catalogallows.stale_authority.bot_archived). Restore reactivates the same identity, so history and sourced memory return; nothing revoked resumes. The main Bot cannot be archived.delegatehands up to 3 assignments to active peers that accept assignments or to a temporary worker (the assigning Bot, not kept). Children run inside the parent's frozen purpose/resources/access with a slice charged to the parent (never refunded; 6 per request, 3 unfinished), without interpretation, memory or further delegation, in their own drain pool sized to the computer's free sessions. Bot-private context refuses a peer (private_context); before every child model send the TEAM handoff from the still-current parent and DATA15 ancestry are checked. Stopping a parent stops its children; stopping one child keeps siblings.s16-client-bots/v1API, Bots pages, rail roster, "Talk to" for a new chat, proposal card, child cards and assignment banner, in English and Thai.Decision record: ADR 0088; contract: s16-bots/v1.
Evidence (tested head
db904898b41fe199de444321bec16a546ba2c73b)bun run typecheck,git diff --check: pass.bun test tests/s16-bots.test.ts: 10 pass — exact proposal/stale acceptance, team defaults and unchanged other fields, running work kept across the install, per-conversation Bot/route/persona, excluded resource refused, archive during work stops it and fences sends, restore + restart keeps history, duplicate/export/import, peer + temporary results with budget exhaustion, independent child stop with no double attach/charge after restart, private ancestry refused for a peer, withdrawn task source refuses the child's next send, default-policy renewal keeps Bots, POLICY narrowing still stale, interrupted acceptance retry.JIT_S16_BROWSER_TESTS=1real-bundle suites (9 files, 28 tests) incl. newtests/s16-bots.browser.test.tsat 1440 (English) and 390 (Thai): all pass;s16-memory.browserfailed once under parallel load and passed twice alone.Pending / limits
delegateyet. Mid-work route switching and real usage reporting stay with [Frontier] [MODEL16-01] Switch approved routes with actual usage and continuity #421.