Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Grok Bot is the single entry point for humans; it schedules OpenCode (implements
4. **PR** to `main`. Imperative English title, `Fixes #N` in the body, and what you ran and did **not** run at the tip SHA. A user-visible change adds one fragment `changelog.d/<issue-or-slug>.<kind>.md` ([changelog.d/README.md](changelog.d/README.md)); never edit `CHANGELOG.md` in a feature PR. Squash is the only merge method; the PR title and body become the commit message, so keep the body short.
5. **CI.** The required check is `tests-ok`. It is green only when `test`, `plugins (tree)`, `plugins (social)` and `package` all pass. Never merge around a red check.
6. **Review and merge.** Review the **tip SHA** with [`review-pr`](.claude/skills/review-pr/SKILL.md) (PASS / FAIL / INC); a tip move voids the PASS. Once the tip has its PASS and the maintainer has delegated the merge, enable auto-merge with `gh pr merge --auto --squash --match-head-commit <sha>`. Without that delegation, the maintainer merges. [`fix-issue`](.claude/skills/fix-issue/SKILL.md) walks all of this, with the environment gotchas.
7. **Stop** and hand over to the maintainer on a security-sensitive change, an open decision such as #16, or when you cannot get a green tip.
7. **Stop** and hand over to the maintainer on a security-sensitive change, an unresolved maintainer decision, or when you cannot get a green tip.

When a class of bug repeats, date a lesson in LESSONS.md (`Seen N×`); after **≥3 days** promote the durable rule into `docs/code-standards.md` / CONTRIBUTING.

Expand Down Expand Up @@ -55,8 +55,9 @@ The Bot team:

- Every Bot is a DSH Session and runs through the normal DSH agent loop, tools and model routes.
- The team works together: Bots message each other, share group chats and can see what the other Bots are doing. Each Bot still runs on its own and does not disturb the others.
- Bots have clear, different roles. A Main Bot has the highest rights: it creates, changes and removes other Bots. Other Bots do not get these rights. There can be more than one Main Bot.
- The multi-human authority contract (human owner ↔ designated Chief ↔ specialists) is documented in [docs/subsystems/team.md](docs/subsystems/team.md) as **planned, not shipped**: team mode stays disabled until its authorization gates pass, and the `create_child_bot` decision (#16) is still open—do not assume either option in code, schema or tests.
- Bots have clear, different roles. A Main Bot has the highest rights: it changes and removes other Bots, and can create them. Other Bots do not get those management rights. There can be more than one Main Bot.
- **Tree child creation (#16, Option B).** A tree Bot (not only the Main/root) may call `create_child_bot` to create a child directly under itself. The tool takes no parent argument; `maxChildren` and depth limits stay in force. The new child is usable only by its creator's owner; sharing it with another person still requires an independent per-Bot grant (default deny). There is no publish mechanism. See [docs/subsystems/tree.md](docs/subsystems/tree.md).
- The multi-human authority contract (human owner ↔ designated Chief ↔ specialists) is documented in [docs/subsystems/team.md](docs/subsystems/team.md) as **planned, not shipped**: team mode stays disabled until its authorization gates pass. Issue #16 is resolved (Option B); do not re-open Main-only child creation.
- Users customize each Bot (name, role label, instructions, model, character).
- Behavior must be reliable: a Bot acts on evidence, stays inside its goal, and its results can be checked.

Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ Turns your Bots into one recursive tree that splits a request into parts, sends
![Tree plugin: Chief splits a Hangzhou trip across Travel, Food, and Budget](docs/images/demo-tree.gif)

- **One root.** The tree's root is the Main Bot (Chief); no new bot is created for it. A separate `Root` bot is created only if the team has Bots but no Main Bot. Existing local Bots join under the root as its children, up to `maxChildren`.
- **Children on demand.** A tree Bot calls `create_child_bot(name, role_description)` to make a child directly under *itself*; the tool takes no parent argument. Calls are handled one at a time per parent, so parallel calls never go over the limits or create two siblings with the same name. The rules:
- **Children on demand.** Any tree Bot (not only the Main/root) calls `create_child_bot(name, role_description)` to make a child directly under *itself*; the tool takes no parent argument. Calls are handled one at a time per parent, so parallel calls never go over the limits or create two siblings with the same name. The rules:
- names are 1–40 characters, and duplicate sibling names are rejected (case and spaces ignored);
- depth is at most 5 (the root counts as 1), with at most 8 children per Bot (set in `limits.json` or the plugin config).
- depth is at most 5 (the root counts as 1), with at most 8 children per Bot (set in `limits.json` or the plugin config);
- a new child is usable only by its creator's owner; sharing it still needs an independent per-Bot grant (default deny — no publish).
- **Level-by-level delegation.** Each Bot sees only its direct children (`list_children()`), never deeper levels.
- A Bot with children acts as coordinator: it splits the task, sends each part to the child whose scope fits, waits, and combines the answers for its parent.
- A Bot with no children does the work itself.
Expand Down
5 changes: 3 additions & 2 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ FlyBot 是在固定版本的 [DS Bot](https://github.com/Fei2411/DeepSeek-Bot)
![树插件:Chief 把杭州行程拆给 Travel、Food、Budget](docs/images/demo-tree.gif)

- **一个根。** 树的根是主 Bot(Chief),不会再新建一个根。只有团队里有 Bot、却没有主 Bot 时,才会单独建一个 `Root`。已有的本地 Bot 会挂到根下面作子节点,数量不超过 `maxChildren`。
- **按需生子。** 树中的 Bot 调用 `create_child_bot(name, role_description)`,在**自己**下面直接建子 Bot;工具没有 parent 参数。同一父节点的调用串行处理,避免超限或重名。规则:
- **按需生子。** 树中的任意 Bot(不只是主 Bot / 根)调用 `create_child_bot(name, role_description)`,在**自己**下面直接建子 Bot;工具没有 parent 参数。同一父节点的调用串行处理,避免超限或重名。规则:
- 名称 1–40 个字符;同级重名会被拒绝(忽略大小写和空格);
- 深度最多 5(根算第 1 层),每个 Bot 最多 8 个子节点(见 `limits.json` 或插件配置)。
- 深度最多 5(根算第 1 层),每个 Bot 最多 8 个子节点(见 `limits.json` 或插件配置);
- 新建的子 Bot 默认只给创建者的主人用;分享给别人仍需对该 Bot 单独授权(默认拒绝,没有发布机制)。
- **按层委托。** 每个 Bot 只能看到直接子节点(`list_children()`),看不到更深。
- 有子节点的 Bot 当协调者:拆任务,把每块发给职责匹配的子节点,等待,再汇总给父节点。
- 没有子节点的 Bot 自己干活。
Expand Down
1 change: 1 addition & 0 deletions changelog.d/16-tree-create-child-bots.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**Tree Bots may create children under themselves.** Issue [#16](https://github.com/ThinkFlowLab/FlyBot/issues/16) is Option B: any tree Bot (not only Main/root) can call `create_child_bot` for a child directly under it. `maxChildren` and depth limits stay. A new child is usable only by its creator's owner; sharing it with another person still needs an independent per-Bot grant (default deny). There is no publish path.
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Each subsystem has a detail page under [docs/subsystems/](subsystems/README.md)

## Team authority (planned, not shipped)

Multi-human ownership is **planned, not shipped**. The proposed contract — human owner ↔ designated Chief ↔ specialists, owner-scoped management, Chief-only cross-owner traffic, approval authority and the routing matrix — lives in [docs/subsystems/team.md](subsystems/team.md). Schema (#47), member sign-in (#48), owner-scoped access (#49) and typed room membership (#50) are foundations on that page; **team mode stays disabled** until that page's authorization gates pass, and the child-creation decision (#16) remains an open maintainer decision recorded there.
Multi-human ownership is **planned, not shipped**. The proposed contract — human owner ↔ designated Chief ↔ specialists, owner-scoped management, Chief-only cross-owner traffic, approval authority and the routing matrix — lives in [docs/subsystems/team.md](subsystems/team.md). Schema (#47), member sign-in (#48), owner-scoped access (#49) and typed room membership (#50) are foundations on that page; **team mode stays disabled** until that page's authorization gates pass. Issue #16 is resolved: tree Bots may create children under themselves (Option B; see [tree](subsystems/tree.md)).

## Integrating

Expand Down
3 changes: 1 addition & 2 deletions docs/code-standards.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ When you report status on a change:
## Team authority contract (planned)

- The human ↔ Chief ↔ specialist ownership contract lives in [docs/subsystems/team.md](subsystems/team.md). It is a **planned** contract: multi-human is not shipped, and **team mode stays disabled** until that page's authorization gates pass.
- Issue #16 (who may call `create_child_bot`) is **open**; both options are documented there. Do not implement, review or merge work that assumes either answer, and do not encode one in a test.
- Main/Chief creation rights stay exactly as [AGENTS.md](../AGENTS.md) states them until #16 is decided.
- Issue #16 is **resolved (Option B)**: a tree Bot (not only Main/root) may call `create_child_bot` under itself, within `maxChildren` and depth limits. A newly created child is not auto-granted; sharing still needs an independent per-Bot grant. See [AGENTS.md](../AGENTS.md) and [docs/subsystems/tree.md](subsystems/tree.md). Do not re-open Main-only child creation.

## Tiny loops

Expand Down
29 changes: 12 additions & 17 deletions docs/subsystems/team.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ Shipped behavior stays what [core/README.md](../../core/README.md) (roles: You /

## Does not own

- Tree shape, root adoption, `maxChildren`/depth limits → [tree](tree.md).
- Tree shape, root adoption, `maxChildren`/depth limits, and shipped `create_child_bot` (#16 Option B) → [tree](tree.md).
- Core runtime, shipped single-human roles and tools → [ds-bot-core](ds-bot-core.md) (`core/README.md`).
- Plugin runtime surface → [plugin-runtime](plugin-runtime.md).
- The open `create_child_bot` decision itself → issue #16 (this page only records it as open).
- Per-Bot grants / default deny (#90) → core reach + [tree](tree.md); this page does not invent a publish path.

## Key concepts

Expand All @@ -44,7 +44,7 @@ Shipped by the core store (`core/src/host/store.js`, owned by [ds-bot-core](ds-b
- The saved team (`state.json`) is **version 2**. `members` holds records with an immutable `id`, `createdAt`, and `designatedChiefId`; every Bot carries an `ownerId` binding.
- Loading a legacy **version-1** team runs one migration: it creates the single initial owner (`owner-1`), binds every existing Bot to it, sets the designated Chief from the **first Main Bot** (the shipped Main role — no name matching, no new Main rules), and writes version 2. Bot ids, Session parts and private histories are preserved. The pre-migration file is backed up once as `state.json.v1` before the first version-2 write; if a backup already exists it counts only when it is a readable file holding a parseable version-1 state — a directory, an empty or truncated file, or anything else there fails the load closed instead of migrating.
- Malformed ownership **fails closed**: a Bot owner that names no member, duplicate or mismatched member ids, or a designated Chief that is not a Bot of its member makes the file read-only — it is never repaired by guessing. An older binary already refuses a newer version read-only, so it cannot overwrite the schema.
- This is **not team mode**: the gates below are unchanged and unsatisfied. The schema resolves nothing about `create_child_bot` (#16 stays open) and defines no flag/config/env for team mode. The #48 member-auth foundation (invitations, sessions, whoami) is a sign-in surface only — it does not enable team mode or cross-owner routing.
- This is **not team mode**: the gates below are unchanged and unsatisfied except #16 (resolved Option B on the tree plugin). The schema does not encode child-creation policy and defines no flag/config/env for team mode. The #48 member-auth foundation (invitations, sessions, whoami) is a sign-in surface only — it does not enable team mode or cross-owner routing.

## Member auth foundation (landed, #48)

Expand All @@ -63,8 +63,8 @@ Central authorization in `core/src/host/authz.js`, installed after member-auth:
- When enforced, every Bot / room / session an endpoint touches must belong to the signed-in actor (`bot/forbidden` otherwise). `body.actorId` still grants nothing. Session targets resolve through the store's owner maps (`botOf` for a Bot id; `selfOf` / `groupOwners` / `pastOwners` for a current chat, group Session or earlier part); unresolvable ids deny. `approval-answer` is judged by the approval's own Bot or room, resolved by approval id — caller-supplied session fields grant nothing.
- Shared resources that cannot yet be isolated per owner (secrets, connectors, folder picks, browser bridge, update-install, diagnostics, set-prefs, capability library writes, `add-agent` — the DSH Agent is one per deployment with no owner) are **explicitly blocked** with `bot/blocked-shared` while more than one member exists — not hidden only in the UI. `flybot/*` plugin endpoints follow the same split: plugin reads reach any signed-in actor, plugin writes are shared-blocked.
- `create-bot` stamps `ownerId` from the actor; `view()` and `live()` narrow to the actor — per-session entries (`questions`, `exchangeTurns`) keep the actor's own, deployment-wide surfaces (agents, secrets, connectors, memory reviews) stay visible while a single member exists and hide with more than one, the same rule as the shared writes. `create-room` refuses a request with neither a member Bot nor any participant (a room with nothing in it would belong to nobody); view() also keeps the shared rooms the actor belongs to and the Bots in them (#50).
- Watch item: `set-main` lets an owner promote their own Bot to a Main Bot. Main rights inside the Bot team are a shipped product concept, but how they compose with multi-human authority is exactly what #16 owns — revisit there before team mode turns on.
- **Not done here:** cross-owner task execution and filesystem sandbox redesign (reach is #51, below). Team mode stays disabled; #16 stays open.
- Watch item: `set-main` lets an owner promote their own Bot to a Main Bot. Main rights inside the Bot team are a shipped product concept; how they compose with multi-human authority is still a team-mode question (not #16 — that issue decided tree child creation). Revisit before team mode turns on.
- **Not done here:** cross-owner task execution and filesystem sandbox redesign (reach is #51, below). Team mode stays disabled.

## Room membership foundation (landed, #50)

Expand Down Expand Up @@ -136,7 +136,7 @@ Shipped room privacy (a group never reads a Bot's private chat) is unchanged; th
5. **No forwarding to owner approval.** No route may turn another human's request into owner approval by forwarding it. An approval is created only by the owner whose authority is spent, for the exact action; receipt, relay, or a Chief's word never becomes approval.
6. **Approval authority stays with the human.** A Chief may ask its own owner, present options, and act on an approval it actually received from that owner. It cannot mint an approval, replay another owner's approval, or treat silence as consent.
7. **Team mode is disabled** until every gate below passes.
8. **#16 is open.** Neither option may be assumed by schema or implementation work (see [Open decisions](#open-decisions-16-unresolved)).
8. **#16 is resolved (Option B).** Tree Bots may create children under themselves within `maxChildren` and depth limits. A new child is usable only by its creator's owner; sharing still needs an independent per-Bot grant (default deny). The shipped rule lives in [tree](tree.md), not here.
9. **Contract honesty.** Nothing on this page describes shipped behavior; shipped behavior is [core/README.md](../../core/README.md) and [plugins/tree/README.md](../../plugins/tree/README.md).

## Routing matrix
Expand Down Expand Up @@ -173,18 +173,13 @@ Planned rules for team mode. Default is **deny**: a route is allowed only if a r
| Action touching a second owner's scope | Each affected owner, for their own scope only | Chief → Chief may negotiate; neither Chief can approve for the other's owner. |
| Anything forwarded from another human | Nobody, by forwarding alone | Reject the forwarded "approval"; it is a request, not consent. |

## Open decisions (#16, unresolved)
## Resolved decision (#16, Option B)

Issue **#16** (who may call `create_child_bot`) is an **OPEN maintainer decision** since the PR #2 review. Both options, recorded without preference:
Issue **#16** (who may call `create_child_bot`) is **resolved**. The owner chose **Option B**:

| Option | Statement |
| --- | --- |
| **A** | Restrict `create_child_bot` to the root/Main/Chief Bots (or require owner approval for each creation). |
| **B** | Amend AGENTS.md so specialists / tree Bots may create children under themselves within owner limits (`maxChildren`, depth limits). |
Tree Bots (not only Main/root/Chief) may call `create_child_bot` to create a child directly under themselves. `maxChildren` and depth limits stay. A newly created child is usable only by its creator's owner; sharing with another person still requires an independent per-Bot grant (default deny). There is no publish mechanism.

- Status: **open** — this contract picks neither side.
- Schema and team-mode work (#47+) **must not assume either answer**, and no test may encode one.
- The gate below requires #16 to be *resolved* before team mode can be enabled; resolving it is a maintainer act outside this page.
Shipped enforcement and tests live in [tree](tree.md) (`plugins/tree/`). This contract does not re-open Main-only creation. Remaining team-mode gates below are unchanged.

## Team mode gate

Expand All @@ -193,7 +188,7 @@ Issue **#16** (who may call `create_child_bot`) is an **OPEN maintainer decision
1. **Owner identity enforced server-side** on every management call (create/update/delete Bot, group administration, memory writes) — not prompt-level, not client-side only.
2. **Room/Bot scoping enforced server-side**: a request from outside an owner's scope fails closed, for reads and writes alike.
3. **Approval binding**: an approval names the owner whose authority is spent and the exact action; forwarded or replayed approvals never satisfy it (invariant 5).
4. **#16 resolved** by a maintainer, with a test asserting who may create Bots.
4. **#16 resolved** (Option B): tree Bots may create children under themselves; `plugins/tree/test` asserts who may create, that limits still bind, and that a new child is not auto-granted. This item is satisfied; the others are not.
5. **Chief lifecycle fails closed**: a disabled, missing or replaced Chief leaves no path for specialists to reach cross-owner traffic or approvals (next section).

Until every gate passes, team mode is off and the shipped single-human model is the only supported one.
Expand All @@ -214,7 +209,7 @@ Planned rules (fail closed by default):
- Treating team administration (shared groups, team memory) as private owner authority, or vice versa.
- Letting a specialist "just relay" across owners — relaying is routing, and it is forbidden.
- Treating a forwarded request or forwarded "approval" as owner approval.
- Assuming #16 Option A or Option B has been decided, in schema drafts, code or tests.
- Treating #16 as still open, or restricting `create_child_bot` to Main/root after Option B.
- Adding a team-mode flag, config key or env var before the gates pass.
- Rewriting tree ownership here instead of in [tree](tree.md).

Expand Down
Loading
Loading