ac-teams 0.0.0-stage → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +52 -2
- package/docs/development.md +89 -0
- package/docs/implementation-plan.md +197 -0
- package/docs/operations.md +101 -0
- package/docs/usage.md +128 -0
- package/package.json +27 -4
- package/src/commands.ts +21 -0
- package/src/config.ts +49 -0
- package/src/connection.ts +85 -0
- package/src/coordinator.ts +408 -0
- package/src/graph.ts +79 -0
- package/src/index.ts +273 -0
- package/src/panel.ts +309 -0
- package/src/render.ts +71 -0
- package/src/rpc-agent.ts +155 -0
- package/src/schemas.ts +58 -0
- package/src/store.ts +349 -0
- package/src/task-summary.ts +34 -0
- package/src/telemetry.ts +19 -0
- package/src/terminal-agent.ts +110 -0
- package/src/terminal-ui.ts +162 -0
- package/src/types.ts +135 -0
- package/src/ui-types.ts +19 -0
- package/src/worktrees.ts +87 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alex Coote
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,53 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ac-teams
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Persistent agent teams for [Pi](https://github.com/earendil-works/pi): shared tasks, searchable messages, and optional Git worktrees. Members stay alive between assignments and can resume their native Pi sessions after stopping. No workflow engine or background service.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
Requires Linux, Node 22.19 or newer, and an authenticated `pi` executable on `PATH`. Interactive teams also require `tmux` on `PATH`. Tested with Pi 1.4.0.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pi install npm:ac-teams@0.0.2
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Restart Pi after installation. Use Pi's `/trust` command to save approval for each project directory before launching members there; headless children cannot answer the initial trust prompt.
|
|
14
|
+
|
|
15
|
+
## Use it
|
|
16
|
+
|
|
17
|
+
Your Pi session is the root; its child agents are members. Ask Pi to delegate a bounded assignment, for example:
|
|
18
|
+
|
|
19
|
+
> Launch a member to review src/parser.ts without editing, and have it send findings back to me.
|
|
20
|
+
|
|
21
|
+
| Tool | Purpose |
|
|
22
|
+
| --- | --- |
|
|
23
|
+
| `team_agent` | Launch, inspect, stop, and resume members; manage limits and worktrees |
|
|
24
|
+
| `team_task` | Track shared work, ownership, and dependencies |
|
|
25
|
+
| `team_message` | Send notifications and read or search team history |
|
|
26
|
+
|
|
27
|
+
`/teams` or `/teams panel` opens Tasks, Teammates, and Activity. `/teams teammate <name-or-id>` opens a teammate directly; subcommands and teammate names autocomplete. Use the task graph or list, send feedback, and open a member's full live Pi session.
|
|
28
|
+
|
|
29
|
+
The task summary sits above the input. The agent selector below status shows descriptive names, models, and context usage. `/teams config` toggles these displays independently.
|
|
30
|
+
|
|
31
|
+
From an empty editor, press Down to select the team footer, then Enter to open a member. Ctrl+Shift+Left returns to Main without stopping the member. `/teams stop` stops every descendant.
|
|
32
|
+
|
|
33
|
+
Defaults allow up to **10 live members** and **two levels of delegation**. Use the fewest useful agents.
|
|
34
|
+
|
|
35
|
+
## Know the boundaries
|
|
36
|
+
|
|
37
|
+
- Members share your filesystem access. All members can read all team messages, including direct messages.
|
|
38
|
+
- Limits cover only `team_agent`, not other delegation tools. Use separate worktrees for concurrent writers.
|
|
39
|
+
- Stop retains tasks, sessions, and worktrees. Worktree deletion is explicit and requires clean, integrated work.
|
|
40
|
+
- Exit confirmation needs Pi's `session_before_exit` hook, which installed Pi 1.4.0 lacks. Without it, shutdown cleans up but cannot ask first. Signals always bypass confirmation.
|
|
41
|
+
|
|
42
|
+
See the [operations guide](docs/operations.md) for recovery guarantees, storage, and the Pi dependency security advisory.
|
|
43
|
+
|
|
44
|
+
## Guides
|
|
45
|
+
|
|
46
|
+
- [Usage](docs/usage.md): tool actions, task rules, messages, and companion tools
|
|
47
|
+
- [Operations](docs/operations.md): limits, stop/resume, worktrees, and security
|
|
48
|
+
- [Development](docs/development.md): source setup, verification, and publishing
|
|
49
|
+
- [Implementation history](docs/implementation-plan.md): design decisions and prior art
|
|
50
|
+
|
|
51
|
+
## License
|
|
52
|
+
|
|
53
|
+
[MIT](LICENSE).
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Develop and publish ac-teams
|
|
2
|
+
|
|
3
|
+
Source setup is for contributors. For normal use, [install the npm package through Pi](../README.md#install).
|
|
4
|
+
|
|
5
|
+
## Run from source
|
|
6
|
+
|
|
7
|
+
Requirements: Linux, Node 22.19 or newer, and an authenticated `pi` executable on `PATH`. Interactive teams also need `tmux`. From a clone of this repository:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm ci
|
|
11
|
+
pi -e "$PWD/src/index.ts"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
To work in another project, launch Pi there with the absolute path to `ac-teams/src/index.ts`. Load the extension once, either explicitly or through Pi package settings, not both. Save native Pi trust for each member's cwd as described in [operations](operations.md#save-project-trust-before-launching).
|
|
15
|
+
|
|
16
|
+
## Run local checks
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
npm run check
|
|
20
|
+
npm test
|
|
21
|
+
npm pack --dry-run
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The deterministic suite makes no model calls. It covers:
|
|
25
|
+
|
|
26
|
+
- Task reservations, progress, dependencies, release/reopen rules, and durable migration
|
|
27
|
+
- Subprocesses, sockets, notification batching, shutdown escalation, worktree safety, and lifecycle races
|
|
28
|
+
- Graph navigation, task numbers and labels, UUID references, task summaries, display toggles, state colors, and narrow layouts
|
|
29
|
+
- Draft retention, quiet resume, shutdown-time feedback, and maximum-length messages
|
|
30
|
+
- Name validation and recovery, autocomplete, name/ID resolution, and model/context reports
|
|
31
|
+
|
|
32
|
+
### Recorded native Pi verification
|
|
33
|
+
|
|
34
|
+
Additional local checks on 2026-10-24, using Pi 1.4.0 unless noted:
|
|
35
|
+
|
|
36
|
+
- Native Pi busy follow-up, idle wake with the same PID, and resume with the same session ID/path and a new PID
|
|
37
|
+
- Normal project-extension loading and a 10-call model smoke using the existing default model; Pi reported an estimated $0.0861
|
|
38
|
+
- Actual ac-teams exit confirmation, cancel/retry, and child cleanup in a real terminal using patched Pi and a model-free RPC child fixture
|
|
39
|
+
- Native child/grandchild cleanup after coordinator SIGTERM and SIGKILL, without model calls
|
|
40
|
+
- Independent review and executable checks of stop/start, cleanup/resume, and shutdown/socket races
|
|
41
|
+
|
|
42
|
+
Terminal UI checks used real native Pi processes in an isolated full-size Herdr tab with a local deterministic model endpoint, not a paid provider:
|
|
43
|
+
|
|
44
|
+
- Private tmux transport, native child/grandchild delegation, member-to-descendant switching, and single-key return to Main
|
|
45
|
+
- Same PID across switching, unsent member draft retention, and a new PID with the same session ID/path after quiet resume
|
|
46
|
+
- Real UUID task graphs, green/cyan/red state borders, and creator-directed feedback without direct task mutation
|
|
47
|
+
- Root exit stopping native descendants and retaining task, message, and session records
|
|
48
|
+
- Task summary above the input, agent selector below status, native subcommand/name autocomplete, and same-PID/session opening by name or ID
|
|
49
|
+
- Pi-reported model display names and changing context estimates in the live selector
|
|
50
|
+
|
|
51
|
+
Not verified on macOS, Windows, or network filesystems. The package is Linux-only because safe process identity uses `/proc`. No web dashboard, workflow DSL, daemon, or automatic merging is included.
|
|
52
|
+
|
|
53
|
+
## Stage releases for npm approval
|
|
54
|
+
|
|
55
|
+
[The GitHub workflow](https://github.com/ac8318740/ac-teams/actions/workflows/publish-npm.yml) automatically stages a release when `package.json` reaches `main`. Changes to the workflow itself also trigger staging, so installing this automation stages the current version. It runs typecheck, tests, and package checks first.
|
|
56
|
+
|
|
57
|
+
This follows ACStack's automatic staged-release approach. Final publication still requires approval on npm with 2FA; merging alone does not make the version public.
|
|
58
|
+
|
|
59
|
+
Only `main` can stage releases. The workflow rejects other branches and tags before checkout. The GitHub environment `npm` also restricts deployments to the branch `main`, with no allowed tags.
|
|
60
|
+
|
|
61
|
+
Store `NPM_TOKEN` only in that environment, not as a repository secret. This keeps older workflows on other branches from accessing it. Set it using an interactive prompt, not a token pasted into a command or chat:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
gh secret set NPM_TOKEN --repo ac8318740/ac-teams --env npm
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Reuse acstack's token only if its permissions allow creating and staging `ac-teams`. GitHub cannot reveal the existing secret value. Otherwise, create a granular npm token with stage-publish access. npm requires 2FA on the publishing account.
|
|
68
|
+
|
|
69
|
+
For a retry without another commit, run the workflow manually from `main` in GitHub Actions or dispatch it:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
gh workflow run publish-npm.yml --repo ac8318740/ac-teams --ref main
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Pushes to other branches, tags, and pull requests do not trigger staging. An already published version is a no-op. Like ACStack, the workflow treats npm's `Version uniqueness check failed unexpectedly` response as an apparent existing staged submission and directs you to approve it. Other staging errors fail the run.
|
|
76
|
+
|
|
77
|
+
Review and approve the staged version in npm's **Staged Packages** tab using 2FA. The first staging of a new name creates a public `0.0.0-stage` placeholder. The requested version and its contents become public only after approval. See [npm's staged publishing documentation](https://docs.npmjs.com/staged-publishing/).
|
|
78
|
+
|
|
79
|
+
After approval, install through Pi, replacing the version below for later releases:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
pi install npm:ac-teams@0.0.2
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## License and prior art
|
|
86
|
+
|
|
87
|
+
[MIT](../LICENSE). No third-party extension implementation was copied. Pi and TypeBox remain peer dependencies; `grok-mermaid` is a runtime dependency for terminal diagrams. The [implementation history](implementation-plan.md) records design decisions, exit-guard prior art, and license findings.
|
|
88
|
+
|
|
89
|
+
[Back to README](../README.md)
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# ac-teams implementation history
|
|
2
|
+
|
|
3
|
+
**Status:** v0.0.1 is built and verified on Linux as of 2026-10-24. The [README](../README.md) introduces the package and links to its current guides. This file records implementation decisions and the original proposal.
|
|
4
|
+
|
|
5
|
+
The user approved implementation with these refinements:
|
|
6
|
+
|
|
7
|
+
- Warn about competing delegation tools instead of refusing coexistence. Keep normal child resources. Limits cover only ac-teams launches, not other launchers or same-user shell access.
|
|
8
|
+
- Require explicit root opt-in before reading project policy. Configuration alone cannot authorize a limit above 10.
|
|
9
|
+
- Stop, rather than detach, live members when exit is confirmed. Confirmation uses the separately implemented native Pi hook, not input interception.
|
|
10
|
+
- Separate task progress (`todo`, `in_progress`, `done`), ownership, and dependency readiness. Checkout reserves even blocked work; `start` requires completed dependencies. Release clears ownership without reopening done work; reopening is explicit and protects active/done dependents. This supersedes the initial claim-as-progress design. Schema 1 snapshots migrate atomically to schema 2, preserving IDs, owners, dependencies, and revisions.
|
|
11
|
+
|
|
12
|
+
The smallest complete implementation uses one atomically replaced `state.json` for messages and tasks, rather than a separate message journal. Mutations are not request-deduplicated; ambiguous retries require inspection. Notification acknowledgement records queuing, not reading, and does not guarantee at-least-once model execution across crashes. Worktree cleanup is explicit, never automatic.
|
|
13
|
+
|
|
14
|
+
Deterministic subprocess/socket/storage/Git tests, native Pi busy/idle/resume checks, an actual terminal confirmation test, model-free native SIGTERM/SIGKILL probes, package checks, and independent review passed. The paid smoke used 10 calls and Pi reported an estimated $0.0861. The [operations guide](operations.md#pi-dependency-advisory) records the host dependency advisory.
|
|
15
|
+
|
|
16
|
+
## Original proposal
|
|
17
|
+
|
|
18
|
+
The sections below preserve the design investigation and its proposed acceptance checks. Where they differ from the implementation, the [usage guide](usage.md), [operations guide](operations.md), and the refinements above take precedence. Their original future-tense recommendations are not additional pending work.
|
|
19
|
+
|
|
20
|
+
## Architecture: the root owns transport, not everyone's work
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
root Pi extension
|
|
24
|
+
|
|
|
25
|
+
+-- coordinator: durable state, local socket, event delivery
|
|
26
|
+
| |
|
|
27
|
+
| +-- owns RPC pipes --> child Pi session
|
|
28
|
+
| +-- owns RPC pipes --> grandchild Pi session
|
|
29
|
+
|
|
|
30
|
+
+-- native root Pi session/transcript
|
|
31
|
+
|
|
32
|
+
child extension -- authenticated local socket --> coordinator
|
|
33
|
+
requests launch, tasks, messages, or stop
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
A child can delegate, but the coordinator launches every process. The recorded parent tree controls depth and stop permissions. Owning all RPC pipes at the root avoids a persistent service and makes root process death close every child's input pipe. Finishing an assignment changes an agent to idle; it does not close that pipe or exit the session.
|
|
37
|
+
|
|
38
|
+
Use Node platform APIs, Pi's peer APIs, and its schema dependency. No database, process supervisor service, or orchestration dependency is needed for this size. Use a small JSONL RPC transport rather than Pi's exported `RpcClient`: v1 needs explicit pipe ownership, EOF shutdown, process identity, and bounded shutdown escalation. The installed client's `stop()` sends SIGTERM and then SIGKILL after one second; its public interface does not provide the required graceful EOF control.
|
|
39
|
+
|
|
40
|
+
### Proposed source boundaries
|
|
41
|
+
|
|
42
|
+
| File | Responsibility |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `src/index.ts` | Register tools, guidance, flags, and Pi lifecycle handlers |
|
|
45
|
+
| `src/coordinator.ts` | Team membership, authorization, single-writer mutations, socket requests, notifications |
|
|
46
|
+
| `src/rpc-agent.ts` | Spawn Pi, correlate RPC responses, track settlement, stop processes |
|
|
47
|
+
| `src/store.ts` | Private local storage, durable writes, message search and cursors |
|
|
48
|
+
| `src/worktrees.ts` | Create optional worktrees and verify safe removal |
|
|
49
|
+
|
|
50
|
+
Keep task rules in the coordinator initially; do not create a generic scheduler. Add the Pi package manifest, TypeScript configuration, and tests only after approval.
|
|
51
|
+
|
|
52
|
+
## The three tools compose without prescribing a workflow
|
|
53
|
+
|
|
54
|
+
Proposed names and actions:
|
|
55
|
+
|
|
56
|
+
| Tool | Actions | Rules |
|
|
57
|
+
| --- | --- | --- |
|
|
58
|
+
| `team_agent` | Launch, list/status, stop, explicit resume, root limit update | Brief, cwd, optional worktree, model, and thinking level; return member and native session identifiers |
|
|
59
|
+
| `team_message` | Send, history, search | Notify all teammates or a nonempty explicit recipient set; all members can read all messages |
|
|
60
|
+
| `team_task` | Create, list/read, edit to-do work, claim, start, release, complete, reopen | Separate progress, ownership, and dependencies; blocked checkout is allowed, starting is gated |
|
|
61
|
+
|
|
62
|
+
Children receive their launch brief and normal project instructions, not the parent's conversation. Startup guidance explains how to pull shared messages and tasks. It asks agents to use the fewest useful teammates, consider thinking level, state edit ownership, and notify their parent before an in-scope split. Scope expansion or changed shared commitments requires approval. There are no fixed manager roles or file locks.
|
|
63
|
+
|
|
64
|
+
Stop authorization follows ancestry: a parent can stop its descendants, not a peer or ancestor. The user can override. Task ownership is separate: agents complete or release their own claims; a parent or the user can explicitly release an interrupted descendant's claim. Stop never silently releases or reruns work.
|
|
65
|
+
|
|
66
|
+
### Launch controls and precedence
|
|
67
|
+
|
|
68
|
+
- Defaults: depth 2, at most 10 live descendants including idle members. Root is depth 0 and does not consume a descendant slot.
|
|
69
|
+
- Root settings resolve in order: built-in defaults, user ac-teams configuration, project ac-teams configuration, explicit root launch flags. Descendants receive the resolved team policy from the coordinator, not authority to rewrite it.
|
|
70
|
+
- A ceiling above 10 requires explicit user authorization: a root startup flag, or a root tool request confirmed through the host UI. Configuration alone cannot silently raise it. In noninteractive mode, require the explicit startup override. Descendants cannot raise either ceiling.
|
|
71
|
+
- Lowering a live ceiling does not stop existing agents. Reject new launches until the proposed membership fits. Lowering depth prevents further over-depth launches; it does not kill existing members.
|
|
72
|
+
- Reserve a slot atomically before spawn; count starting and stopping processes until confirmed exited. Roll back failed startup reservations. Validate the requesting member and ancestry server-side, not from a caller-supplied depth.
|
|
73
|
+
- Read the spawning member's current model and thinking level for each launch. Pass provider/model and thinking explicitly to Pi; an explicit launch override wins. Validate support and fail clearly rather than silently routing to another model.
|
|
74
|
+
|
|
75
|
+
Configuration is convenience, not a security boundary. Members share OS-user access; shell access can bypass coordination policies.
|
|
76
|
+
|
|
77
|
+
### Normal Pi resources, with explicit readiness checks
|
|
78
|
+
|
|
79
|
+
Launch `pi --mode rpc` in the requested cwd, using the installed executable, a dedicated native session directory, and an explicit absolute `-e` path to ac-teams. Preserve normal package, extension, skill, model, authentication, and project-instruction loading. Do not use `--no-extensions` as the production shortcut.
|
|
80
|
+
|
|
81
|
+
Before sending an assignment, require a child readiness handshake proving that ac-teams registered, joined the expected Team, and sees the coordinator's policy. The handshake also reports competing delegation tools/resources. Reject startup on conflicts, missing resources, trust restrictions, or timeout; never continue with an ungoverned child. Normalize package paths to avoid loading ac-teams twice.
|
|
82
|
+
|
|
83
|
+
Known conflicts must be checked before spawning where discoverable from settings/resources, and again at child readiness before model work. A post-load readiness check cannot undo another extension's startup side effects. Supporting arbitrary unknown launchers or claiming full coexistence is outside v1; do not modify existing installations during this project.
|
|
84
|
+
|
|
85
|
+
## Durable state and atomic ownership
|
|
86
|
+
|
|
87
|
+
Store coordination data at `~/.acstack/ac-teams/teams/<team-id>/` regardless of cwd. Use private directories (0700) and private files/socket (0600). The product uses this directory name without depending on ACStack. Never send tasks or messages to GitHub, ACStack maps, or another tracker.
|
|
88
|
+
|
|
89
|
+
- `state.json`: member identities and ancestry, policy, task state, claims, session paths, and notification progress.
|
|
90
|
+
- `messages.jsonl`: append-only shared message history with monotonic sequence numbers and stable message IDs.
|
|
91
|
+
- `sessions/`: native Pi-managed session files; store references instead of copying transcripts.
|
|
92
|
+
- Coordinator socket and exclusive owner lock: runtime coordination only, with per-member credentials and validated request schemas.
|
|
93
|
+
|
|
94
|
+
Only the root coordinator writes. Serialize mutations in one request queue. Validate and commit each reservation in the same critical section: the task is to-do and unowned. Checkout does not start work and can reserve a blocked task. Starting requires ownership and completed dependencies. Atomic snapshot replacement uses a same-directory temporary file, flush, rename, and directory flush. Append and flush a message before notifying recipients. A successful mutation response follows durable persistence; use request IDs to make retries idempotent.
|
|
95
|
+
|
|
96
|
+
Validate dependency IDs and reject cycles. Freeze dependencies while a task is in progress or done; a reserved to-do task remains editable by its owner. Return unfinished prerequisites as derived `blockedBy`, not a stored progress value. Release clears ownership, returns in-progress work to to-do, and leaves done work done. Explicit reopening cannot invalidate in-progress or done dependents. A process crash marks the member interrupted but retains task progress and ownership visibly.
|
|
97
|
+
|
|
98
|
+
An exclusive team lock prevents simultaneous roots writing the same state. Check process identity, not PID alone, before deciding a lock is stale. If identity or liveness is uncertain, refuse takeover and report recovery steps rather than killing processes or breaking the lock automatically. Test these filesystem assumptions on supported local Linux filesystems; do not promise network-filesystem locking guarantees.
|
|
99
|
+
|
|
100
|
+
Retain all durable records until explicit user-authorized deletion. Refuse deletion while members are live. Do not log tokens or credentials. Document that coordination messages, launch briefs, and native transcripts can contain sensitive project data.
|
|
101
|
+
|
|
102
|
+
## Delivery wakes agents without model polling
|
|
103
|
+
|
|
104
|
+
Append each message once. Broadcast resolves to the other current members; an explicit recipient set selects notification targets, not access permissions. History/search remains team-wide, including messages between other members. Paginate by sequence/cursor and return bounded text matches without loading the entire history into the model.
|
|
105
|
+
|
|
106
|
+
The coordinator pushes sequence references to connected member extensions. Use Pi's custom message delivery to wake an idle agent and queue a follow-up while busy. Batch pending references per member to avoid a model turn for each message. Reuse the same notification ID after reconnect and keep recipient progress for deduplication. Treat delivery as at-least-once; do not promise exactly-once model execution across crashes.
|
|
107
|
+
|
|
108
|
+
An assignment is complete only after `agent_settled`, not the RPC prompt acknowledgement or an intermediate `agent_end`. Idle members remain available. Default notifications do not interrupt running tools; reserve steering for an explicit urgent instruction. Transport failure leaves pending notifications visible. No automatic model retry or task reassignment follows a crash.
|
|
109
|
+
|
|
110
|
+
## Stop, exit, and resume guarantees
|
|
111
|
+
|
|
112
|
+
| Situation | Proposed behavior | Guarantee boundary |
|
|
113
|
+
| --- | --- | --- |
|
|
114
|
+
| Parent requests stop | Stop descendants in that subtree, clear queued work, abort active work, close stdin, wait, then SIGTERM/SIGKILL on a timeout | Test graceful and forced paths; report forced exits |
|
|
115
|
+
| Assignment settles | Record idle; keep process and RPC connection open | Supported by Pi RPC lifecycle |
|
|
116
|
+
| Root native exit | Confirm while descendants are live, then stop them and retain records | Requires the local Pi pre-exit patch; installed Pi 1.4.0 supports cleanup only |
|
|
117
|
+
| Intermediate member exits unexpectedly | Coordinator observes exit and stops its descendants; preserve interrupted claims | Requires root still functioning |
|
|
118
|
+
| Root crashes or receives SIGKILL | Its owned pipes close; RPC children receive EOF and begin shutdown | Best effort; child/event-loop hangs or inherited pipe handles can defeat timely cleanup |
|
|
119
|
+
| Machine failure | Processes stop; reconcile records on next open | No cleanup hook or guaranteed final write |
|
|
120
|
+
| Native resume | Use `pi --session <path\|id>`; rejoin records after identity checks | Resume is a new process, not reconnection to old stdio |
|
|
121
|
+
|
|
122
|
+
Track only ac-teams-owned processes. Never enumerate and stop unrelated Pi sessions. Descendant process-group cleanup must be tested; arbitrary shell-spawned detached processes are not covered by a universal kill guarantee.
|
|
123
|
+
|
|
124
|
+
Expose session ID and path for every member. On explicit resume, verify that the old member is not still live, reserve capacity, and start the native session with the same membership binding. Keep its interrupted claims visible for explicit continuation or release. Never reconstruct a transcript or automatically replay its last assignment. A manually resumed member without its coordinator can inspect its transcript, but cannot launch team work until team recovery is explicit.
|
|
125
|
+
|
|
126
|
+
Because this coordinator lives in the root, automatic attachment to an orphan's existing RPC pipes is not supported. If post-crash processes remain live or uncertain, block replacement instead of running duplicate work. Switching/forking the interactive root session must not silently abandon the old Team: reject cancellable switches with live descendants unless they are explicitly stopped; a cloned/forked session must not inherit authority to the original Team.
|
|
127
|
+
|
|
128
|
+
## Exit confirmation: supported hook versus package interception
|
|
129
|
+
|
|
130
|
+
The earlier recommendation to omit confirmation in v1 was too restrictive. Confirmation can be built; the distinction is whether it uses a supported lifecycle hook or intercepts selected exit routes.
|
|
131
|
+
|
|
132
|
+
Verified installed behavior: `session_shutdown` has no cancellation result, and normal interactive shutdown stops the TUI before disposing extensions. `/quit` is handled directly by the interactive mode before extension command dispatch. `app.clear` and `app.exit` shortcuts are reserved, but `ctx.ui.onTerminalInput()` can consume raw input before built-in handling. Raw input interception is not a global shutdown gate: it must preserve editor, abort, paste, modal, and configured keybinding behavior, and cannot intercept another extension calling `ctx.shutdown()`.
|
|
133
|
+
|
|
134
|
+
The Pi prerequisite is implemented locally in `/home/acoote/projects/pi`, branch `feat/cancellable-exit-hook`. It is not committed, published, or installed. The implementation uses no private-method replacement or copied third-party code.
|
|
135
|
+
|
|
136
|
+
Verification passed: 73 focused tests, `npm run check`, and real-terminal checks for `/quit`, Ctrl+D, double Ctrl+C, extension-requested exit, cancellation/retry, and SIGTERM during confirmation. No model prompts were sent.
|
|
137
|
+
|
|
138
|
+
Hook behavior and the proposed ac-teams integration contract:
|
|
139
|
+
|
|
140
|
+
- Pi emits `session_before_exit` before interactive terminal teardown. Returning `{ cancel: true }` keeps Pi open; a handler error also cancels exit and is reported.
|
|
141
|
+
- `/quit`, exit keybindings, and extension-requested graceful exit use the hook. Concurrent exit requests share one pending check; cancellation leaves Pi usable. Reload and session replacement do not emit it.
|
|
142
|
+
- In ac-teams, prompt only for a root with live descendants, including idle members: cancel exit, or stop descendants and exit while retaining records. Any detach/keep-running choice needs a separate lifecycle decision; it is not implied by confirmation.
|
|
143
|
+
- Do not prompt on SIGTERM, SIGHUP, terminal loss, noninteractive exit, or crashes. Preserve best-effort cleanup; SIGKILL and machine failure cannot run a hook.
|
|
144
|
+
- Test exit routes, cancellation, repeated requests, busy agents, no-live-member exits, cleanup, and unavailable UI. Until Pi supports the hook, a package-only exit command or input guard must explicitly document its bypasses.
|
|
145
|
+
|
|
146
|
+
Prior art checked on 2026-10-24:
|
|
147
|
+
|
|
148
|
+
| Project | Actual mechanism | Reuse assessment |
|
|
149
|
+
| --- | --- | --- |
|
|
150
|
+
| [sidstack/pi-codex-agents](https://github.com/sidstack/pi-codex-agents/blob/ae789448a8b1724075343d3341e99d04c628a1a6/src/core/host.ts#L145-L198) | Exit menu for its managed sessions; replaces the owned interactive mode's private `shutdown` and signal methods | Closest working design reference, but not a drop-in supported hook. Do not import its daemon/UI architecture or private-method patch for this tools-only package. MIT |
|
|
151
|
+
| [atayarani/pi-close-guard](https://github.com/atayarani/pi-close-guard/blob/54f9be0872b9881e57b0d1ddd34ba7608769f6c8/extensions/close-guard.ts) | Uses cancellable `session_before_switch` for `/new` and optionally `/resume`; explicitly excludes `/quit` | Useful confirm/cancel pattern, not an exit solution. MIT |
|
|
152
|
+
| [j1nn0/pi-extensions, pi-exit](https://github.com/j1nn0/pi-extensions/tree/78b556daf6dcd02757aec77077f278c39944c71d/packages/pi-exit) | Dedicated exit command/tool and keyboard shortcut | Example of requesting exit, not vetoing built-in shutdown. MIT |
|
|
153
|
+
| [getsimpledirect/vinci-code-cli](https://github.com/getsimpledirect/vinci-code-cli/blob/33b4ae7b6788c07a9c7e5109b083ae1e313aff4e/packages/coding-agent/src/core/extensions/runner.ts) | Defines `session_before_exit` in a fork for one-shot modes, without cancellation | A matching name does not supply the interactive cancellable behavior. MIT |
|
|
154
|
+
|
|
155
|
+
No third-party implementation was copied or installed. If code is adapted, retain the relevant copyright and MIT permission notice and identify the project, source commit, and adapted files in third-party notices. Acknowledgment alone does not replace the license notice. Upstream API evidence was checked at [earendil-works/pi commit d0aa218](https://github.com/earendil-works/pi/blob/d0aa218cb16c333c008f6aa3dcd670ac8b68383c/packages/coding-agent/src/core/extensions/types.ts). These are static source findings, not runtime verification of third-party exit behavior.
|
|
156
|
+
|
|
157
|
+
## Worktrees preserve work by default
|
|
158
|
+
|
|
159
|
+
A launch can use its supplied cwd or request a worktree. For a worktree, resolve the repository and base commit before spawning. Default to that repository's current HEAD; accept an explicit base ref. Do not fetch, checkout, reset, merge, or stash another working tree. Use an ac-teams-specific branch name containing team/member identifiers and pass Git arguments without shell interpolation.
|
|
160
|
+
|
|
161
|
+
Creation records repository, resolved base, branch, path, and an optional user-authorized integration target. Branch selection must reject collisions and invalid refs.
|
|
162
|
+
|
|
163
|
+
Automatic worktree removal is allowed only after the member has stopped, the tree is clean including untracked files, and its HEAD is an ancestor of the recorded integration target's current commit. Recheck immediately before removal. Missing target, uncertain status, or squash/rebase integration without ancestry proof means retain the tree and explain why. Never use force removal. V1 does not delete branches automatically and never treats stopping an agent as permission to merge.
|
|
164
|
+
|
|
165
|
+
## Implementation order and acceptance checks
|
|
166
|
+
|
|
167
|
+
Each step adds focused tests before it is considered complete. Before writing tests, follow the test-conventions skill and choose ordinary unit/integration tests for this standalone package, not ACStack application conventions.
|
|
168
|
+
|
|
169
|
+
1. **Package and child lifecycle.** Register the extension, root coordinator, readiness protocol, and RPC transport. Check normal cwd resources, explicit package loading, no parent-conversation inheritance, model/thinking inheritance and overrides, idle reuse across two assignments, and native session IDs/paths. Fail closed on both installed competing launchers. Bound output buffers and shutdown waits; always drain stderr.
|
|
170
|
+
2. **Durable tasks and limits.** Race simultaneous claims and launches; exactly one claimant wins, dependencies and cycles are checked, team/depth caps include idle agents, and startup failures release only their reservations. Test owner permissions, lower-limit behavior, request retries, disk failure, truncated message-tail recovery, duplicate roots, and crash-preserved claims.
|
|
171
|
+
3. **Messages and notifications.** Test broadcast and explicit multiple recipients, team-wide search, pagination, idle wake-up, busy follow-up, settlement, notification batching/deduplication, disconnection, and no periodic model polling. Define behavior for invalid/departed recipients explicitly and reject invalid recipient sets before append.
|
|
172
|
+
4. **Failure and resume.** Exercise orderly stop, queued-work cancellation, intermediate failure, root SIGTERM/SIGKILL, EOF, a child ignoring termination, and explicit native resume. Check no unrelated process is touched, no duplicate member starts, and no interrupted claim silently changes owner. Document observed best-effort limits.
|
|
173
|
+
5. **Worktrees and usage guidance.** Test clean and dirty repositories, branch collisions, integrated/unmerged heads, untracked files, absent targets, and safe cleanup. Add concise examples of child delegation and parent notification. An optional short Herdr skill may reference `herdr --skill`; it must not become a runtime dependency or a second messaging implementation.
|
|
174
|
+
|
|
175
|
+
Use fake RPC peers for deterministic protocol tests and real Pi processes for lifecycle/resource checks. A small paid-model smoke test is needed for two real assignments, busy/idle messaging, and tool-guidance behavior; do not confuse the no-model probe below with that verification. No frontend or dashboard verification is required for this tools-only scope.
|
|
176
|
+
|
|
177
|
+
## API evidence and investigation limits
|
|
178
|
+
|
|
179
|
+
The evidence below describes the installed package; the separate local Pi patch is documented above. Package root: `/home/acoote/.npm-global/lib/node_modules/@earendil-works/pi-coding-agent/`.
|
|
180
|
+
|
|
181
|
+
| Evidence | Supports |
|
|
182
|
+
| --- | --- |
|
|
183
|
+
| `docs/extensions.md`, `dist/core/extensions/types.d.ts:1229-1300` | Tool registration, extension flags, custom/user messages, model/thinking access |
|
|
184
|
+
| `docs/sdk.md`, `dist/core/resource-loader.d.ts:70-124` | SDK session/resource APIs; normal cwd loading and explicit additional resources |
|
|
185
|
+
| `dist/core/resource-loader.js:409-422` | Resource merging and extension loading; an after-load override is not proof of safe conflict prevention |
|
|
186
|
+
| `docs/rpc.md`, `docs/rpc-commands.md` | Persistent JSONL RPC; prompt/steer/follow-up, clear queue, abort, state, and settlement |
|
|
187
|
+
| `docs/rpc-extension-ui.md` | RPC UI requests require host responses; headless approval needs explicit policy |
|
|
188
|
+
| `dist/modes/rpc/rpc-mode.js:579-650` | Shutdown on stdin EOF and native runtime disposal |
|
|
189
|
+
| `dist/modes/rpc/rpc-client.js:89` | Exported client's limited stop sequence |
|
|
190
|
+
| `dist/modes/interactive/interactive-mode.js:3444-3488`, `dist/core/extensions/types.d.ts:637` | Shutdown ordering, non-cancellable shutdown event, emergency-exit limits |
|
|
191
|
+
| `docs/cli.md`, installed `pi --help`, `docs/sessions.md` | Native `--session <path\|id>` resume and session persistence |
|
|
192
|
+
| `docs/packages.md`, `docs/configuration.md`, `docs/settings.md`, `docs/security.md` | Package resources, settings/trust, and extension security limits |
|
|
193
|
+
| Installed `@tintinweb/pi-subagents` 0.22.0 and `pi-subagents` 0.81.0 | Independent delegation and lifecycle behavior; both MIT, neither required or copied |
|
|
194
|
+
|
|
195
|
+
A temporary, isolated real-Pi probe disabled all optional extensions/skills/templates/themes and sent no model prompt. It verified successful `get_state`, `get_commands`, `clear_queue`, and `abort` responses; continued availability between commands; native session ID/path reporting; and exit code 0 after stdin EOF. The first probe timed out because its Python text-buffered selector reader missed buffered lines; switching the probe to byte reads resolved that harness error.
|
|
196
|
+
|
|
197
|
+
At the end of the initial investigation, extension coexistence/readiness, paid model turns, busy message delivery, concurrent claims, parent-death cleanup, native resume/rejoin, and worktree safety were still unverified. Those checks were subsequently exercised during implementation; see [recorded verification](development.md#recorded-native-pi-verification) and [operational limits](operations.md). Publishing, marketplace integration, and ACStack changes were outside the initial local delivery. Current [publishing instructions](development.md#stage-releases-for-npm-approval) are separate from that history.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Operate ac-teams
|
|
2
|
+
|
|
3
|
+
ac-teams runs on Linux with Node 22.19 or newer and an authenticated `pi` executable on `PATH`. Interactive roots also require `tmux`: each team owns a private server and native member terminals. Headless roots retain RPC members. Both share your OS user's access, not a sandbox.
|
|
4
|
+
|
|
5
|
+
## Save project trust before launching
|
|
6
|
+
|
|
7
|
+
Use Pi's `/trust` command to approve each member's cwd before launching there. Children cannot complete the coordinator readiness handshake while waiting for Pi's initial trust prompt. ac-teams rejects readiness if project resources were skipped; it never auto-approves a project.
|
|
8
|
+
|
|
9
|
+
A one-run approval in the root is not a saved approval for children or new worktrees. Worktree creation copies committed content, not uncommitted project configuration. Approve the new cwd through native Pi trust before retrying a launch that could not load its project resources. A failed launch retains its created worktree and member record.
|
|
10
|
+
|
|
11
|
+
## Limits are ceilings, not staffing targets
|
|
12
|
+
|
|
13
|
+
Default: at most **10 live descendants**, counting starting, busy, idle, and stopping members. Root does not consume a slot. Default depth is **2**: root, child, grandchild. Use the fewest useful agents.
|
|
14
|
+
|
|
15
|
+
Root policy precedence, from lowest to highest:
|
|
16
|
+
|
|
17
|
+
1. Built-in defaults
|
|
18
|
+
2. `~/.acstack/ac-teams/config.json`
|
|
19
|
+
3. `.pi/ac-teams.json`, only with `--teams-project-config`
|
|
20
|
+
4. Explicit `--teams-limit` and `--teams-depth` flags
|
|
21
|
+
|
|
22
|
+
Config files accept only `limit` and `depth`, for example `{"limit":4,"depth":2}`. Limits must be 1–100; depth must be 0–10.
|
|
23
|
+
|
|
24
|
+
A limit above 10 requires an explicit root startup flag or interactive confirmation of a root `limits` tool request. Configuration alone cannot raise it. Lowering limits does not kill existing members; it blocks further launches until capacity fits.
|
|
25
|
+
|
|
26
|
+
For an npm-installed extension, set startup limits with:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
pi --teams-limit 4 --teams-depth 1
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Other delegation tools remain outside these limits. See [companion tools](usage.md#companion-tools-add-guidance-or-terminal-management).
|
|
33
|
+
|
|
34
|
+
## Display preferences are global
|
|
35
|
+
|
|
36
|
+
`/teams config` saves task-summary and agent-selector visibility to `~/.acstack/ac-teams/display.json`:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{"tasks":true,"agents":true}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Only these two boolean keys are accepted; omitted keys default to `true`. Saves atomically replace a private 0600 file. A malformed or unreadable preferences file produces a warning and is not overwritten; correct or remove it before saving settings again. These preferences are separate from resource policy in `config.json` and have no project override.
|
|
43
|
+
|
|
44
|
+
## Stop and resume members
|
|
45
|
+
|
|
46
|
+
`stop` stops the member's descendants deepest-first, clears queued work, and aborts the turn. It closes the owned RPC pipe or terminates the owned native terminal. Hung processes escalate to SIGTERM and then SIGKILL, with a warning. Escalation requires a matching captured process-group identity; the coordinator refuses uncertain ownership.
|
|
47
|
+
|
|
48
|
+
This is snapshot-based cleanup, not OS containment. Detached or uncaptured descendants and identity-check races remain outside the guarantee.
|
|
49
|
+
|
|
50
|
+
`resume` needs a stopped descendant ID and a new brief. It keeps the member's descriptive name; renaming during resume is rejected. It starts a new process against the same native Pi session file. It does not reconstruct a transcript, reconnect to old stdio, or replay the previous assignment automatically. The coordinator refuses tool-driven resume if the old process is live or its identity is uncertain.
|
|
51
|
+
|
|
52
|
+
The interactive panel can instead quietly resume a saved member session without inventing a new brief. Feedback then arrives through the durable team mailbox.
|
|
53
|
+
|
|
54
|
+
Root session switching, forking, and tree traversal are blocked while members are live. A member cannot switch away from its team binding. Stop members explicitly before replacing the root session.
|
|
55
|
+
|
|
56
|
+
### Exit confirmation needs a Pi hook
|
|
57
|
+
|
|
58
|
+
Exit confirmation requires Pi's `session_before_exit` hook. The prerequisite is implemented in the separate local Pi checkout described in [the implementation history](implementation-plan.md#exit-confirmation-supported-hook-versus-package-interception), not in installed Pi 1.4.0.
|
|
59
|
+
|
|
60
|
+
With that hook, native exit asks before stopping live members; cancellation leaves them running. Without it, shutdown performs cleanup but cannot ask first. Signals bypass confirmation.
|
|
61
|
+
|
|
62
|
+
### Crash recovery is best effort
|
|
63
|
+
|
|
64
|
+
If the root crashes, closing its owned pipes and losing the coordinator connection makes ordinary RPC children shut down. Native members also monitor the authenticated coordinator connection and exit after it is lost. This passed SIGTERM and SIGKILL probes with native child and grandchild processes.
|
|
65
|
+
|
|
66
|
+
It is not a guarantee against a hung event loop, machine failure, or detached shell processes. Recovery refuses duplicate work when a previous member is still live or uncertain. Tasks keep their ownership and progress after stop or crash; there is no automatic reassignment.
|
|
67
|
+
|
|
68
|
+
## Worktree cleanup is explicit
|
|
69
|
+
|
|
70
|
+
Set `worktree: true` on launch. `base` defaults to the repository's HEAD; `target` records the branch/ref against which later cleanup must prove integration. Worktrees live under a sibling `.ac-teams-worktrees` directory. No fetch, merge, stash, or checkout of the original directory occurs.
|
|
71
|
+
|
|
72
|
+
Stopping never deletes a worktree. `cleanup` requires a stopped member, a clean tree including ignored/untracked files, and HEAD ancestry proven against the recorded target's current commit.
|
|
73
|
+
|
|
74
|
+
Missing targets, dirty work, and uncertain/squashed integration retain the tree. Cleanup never forces removal and retains the branch. Cleanups and resumes exclude each other.
|
|
75
|
+
|
|
76
|
+
## Local records contain sensitive project data
|
|
77
|
+
|
|
78
|
+
Each root session uses `~/.acstack/ac-teams/teams/<session-id>/`:
|
|
79
|
+
|
|
80
|
+
- `state.json` contains membership, policy, tasks, messages, claims, and notification cursors
|
|
81
|
+
- `sessions/` contains native Pi-managed member transcripts
|
|
82
|
+
- `owner.lock` and `coordinator.sock` coordinate the running root
|
|
83
|
+
- Interactive teams also own `t.sock`, the private tmux socket, and per-member terminal environment files; shutdown removes those files
|
|
84
|
+
|
|
85
|
+
New members also store their descriptive names and optional model/context reports. When an existing team opens, unnamed members receive stable, collision-free names such as `teammate-1`; their IDs and sessions do not change.
|
|
86
|
+
|
|
87
|
+
State schema 3 adds stable task numbers and short labels. Opening a schema 1 or 2 team assigns numbers in stored task order and initial labels from up to three title words. Full titles, descriptions, UUIDs, owners, creators, dependencies, and revisions remain unchanged.
|
|
88
|
+
|
|
89
|
+
Schema 1 also migrates progress: `pending` becomes `todo`, `claimed` becomes `in_progress`, and `completed` becomes `done`. Migration writes atomically and rejects invalid snapshots without replacement. Older ac-teams code cannot reopen schema 3; stop old sessions before updating.
|
|
90
|
+
|
|
91
|
+
Only the root writes state. Mutations validate a copy, flush a temporary snapshot, atomically rename it, and flush the directory before returning success. An exclusive process-identity lock prevents concurrent owners. Private team directories use 0700; state files and the authenticated Unix socket use 0600. Uncertain locks fail closed.
|
|
92
|
+
|
|
93
|
+
This is a small-team store: each mutation rewrites the snapshot, and search scans local history. There is no database, compaction, retention policy, automatic deletion, or deduplication of repeated mutation requests. Inspect state before retrying an ambiguous failed request.
|
|
94
|
+
|
|
95
|
+
Records and transcripts can contain sensitive project data. Permissions protect against other users, not agents running as the same OS user. All members can read all team messages, including direct messages.
|
|
96
|
+
|
|
97
|
+
### Pi dependency advisory
|
|
98
|
+
|
|
99
|
+
The local verification recorded on 2026-10-24 found that `npm audit` reports Pi 1.4.0's pinned `undici` dependency, including a high-severity advisory. ac-teams adds no HTTP client and cannot repair an existing host installation. The suggested npm fix downgrades Pi incompatibly; it has not been applied. Review the host dependency before deployment.
|
|
100
|
+
|
|
101
|
+
[Back to README](../README.md)
|
package/docs/usage.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Use ac-teams
|
|
2
|
+
|
|
3
|
+
ac-teams provides three tools without prescribing a workflow. Your Pi session is the root; its child agents are members. The root opens coordination state on the first team request.
|
|
4
|
+
|
|
5
|
+
| Tool | Actions | Main rule |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| `team_agent` | `launch`, `list`, `status`, `stop`, `resume`, `limits`, `cleanup` | A parent controls its descendants, not peers or ancestors |
|
|
8
|
+
| `team_task` | `create`, `list`, `read`, `edit`, `claim`, `start`, `release`, `complete`, `reopen` | Claim reserves work; dependencies gate starting, not ownership |
|
|
9
|
+
| `team_message` | `send`, `history`, `search` | Recipients select who receives notification, not who can read |
|
|
10
|
+
|
|
11
|
+
In interactive Pi, `/teams` or `/teams panel` opens the team panel. `/teams teammate <name-or-id>` opens a live teammate directly; autocomplete suggests subcommands and teammate names. You can also enter an exact teammate ID. The older `/teams open <id>` form remains supported. Headless roots retain the status listing. `/teams stop` stops every descendant. See [operations](operations.md) for limits, recovery, and worktree cleanup.
|
|
12
|
+
|
|
13
|
+
## Navigate without stopping members
|
|
14
|
+
|
|
15
|
+
The agent selector sits below Pi's status lines. It shows each member's name, state, model display name, and context usage. It keeps Main pinned and shows at most five rows, including an overflow indicator when needed. A finished assignment leaves its member idle and selectable.
|
|
16
|
+
|
|
17
|
+
Context shows Pi's reported token estimate, window size, and percentage, for example `Claude Opus 4.6 · 48k / 200k (24%)`. Reports refresh about once a second when they change. Unknown usage stays marked unknown, not zero. Stopped members retain their last report. These are context estimates, not billing totals.
|
|
18
|
+
|
|
19
|
+
- Press Down from an empty editor to focus Main in the footer. Up/Down select members; Enter opens the selected live session; Esc returns to editing.
|
|
20
|
+
- Ctrl+Shift+Left returns from a member to Main. Switching preserves the member's process, session, and draft. Returning does not stop it.
|
|
21
|
+
- `/teams` opens three tabs. Tab moves between Tasks, Teammates, and Activity; Esc closes the panel.
|
|
22
|
+
- **Tasks:** Arrow keys select nodes in the dependency graph. G toggles graph/list, and Enter shows full details. Green means Done, red Blocked, cyan Working, and neutral Ready; written labels remain visible. Large or unsupported graphs fall back to the list.
|
|
23
|
+
- **Teammates:** Enter opens a live member, or quietly resumes a stopped member's saved session before opening it. Root can open any member; member views can open their descendants.
|
|
24
|
+
- **Activity:** Shows the latest 100 persistent team messages rather than every tool update. Use `team_message history` to read older messages.
|
|
25
|
+
- N composes a task request for Main. C on a task sends feedback to its creator. Enter sends; Shift+Enter adds a newline; Esc cancels without losing the draft. These messages do not directly edit the task graph. Feedback resumes a stopped creator when possible; otherwise, the receipt explicitly reports delivery to Main instead.
|
|
26
|
+
|
|
27
|
+
A task request is a proposal, not an instruction to create a task. Main receives guidance to review the agreed scope and existing work first: reuse a task that already covers the request, extend one when coherent and permitted, or create distinct in-scope work. It should clarify unresolved scope conflicts and explain its decision with task references.
|
|
28
|
+
|
|
29
|
+
The send receipt confirms delivery, not acceptance or task creation. This is agent guidance, not an automatic semantic duplicate detector.
|
|
30
|
+
|
|
31
|
+
Team tool results and messages are compact by default. Ctrl+O expands them into labeled fields. UI state colors do not replace the underlying progress, ownership, or dependency fields.
|
|
32
|
+
|
|
33
|
+
## Show tasks and configure the displays
|
|
34
|
+
|
|
35
|
+
The task summary sits above the input editor; the agent selector stays below the status lines. It shows completed/total counts and up to five numbered task labels, ordered by:
|
|
36
|
+
|
|
37
|
+
1. In-progress work
|
|
38
|
+
2. Ready prerequisites blocking other tasks, with the most dependents first
|
|
39
|
+
3. Blocked work, marked `⊘` with prerequisite numbers such as `blocked by #3`
|
|
40
|
+
4. Recently completed work, newest first
|
|
41
|
+
|
|
42
|
+
Ordinary ready tasks remain in `/teams`; the summary is not the full task list. Completion time determines recent order for newly completed tasks. Older completed tasks without timestamps fall back to task-number order.
|
|
43
|
+
|
|
44
|
+
Use `/teams config` to toggle **Task summary** and **Agent selector** independently. Up/Down select a setting; Space or Enter toggles it; Esc closes. Changes save immediately for the current and future sessions. Other running sessions are not updated automatically. Both displays default to On.
|
|
45
|
+
|
|
46
|
+
Hiding a display does not stop agents, change tasks, or disable `/teams`. With the agent selector hidden, ordinary editor Down behavior returns. These global display preferences do not change the team's resource ceilings.
|
|
47
|
+
|
|
48
|
+
## Give members bounded assignments
|
|
49
|
+
|
|
50
|
+
Example `team_agent` arguments:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{"action":"launch","name":"parser-review","brief":"Review src/parser.ts. Read only; do not delegate or edit. Send findings to root through team_message."}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Every launch needs a unique descriptive `name`: one or two lowercase words, hyphenated if two, at most 40 characters. For example, `parser-review` or `research`. `main`, `root`, and names matching an existing member's ID are reserved. Names remain stable across stop/resume; IDs remain the API references.
|
|
57
|
+
|
|
58
|
+
`cwd` defaults to the requesting member's directory. `model` (`provider/model`) and `thinking` default to that member's current selection. An explicit override wins. Native Pi selects the model; provider/account rejections remain visible in member status and notify the parent. There is no automatic model retry.
|
|
59
|
+
|
|
60
|
+
Launch returns the name, a stable member ID, PID, cwd, and native session ID/path. Interactive roots launch native Pi terminals in a team-private tmux server; headless roots keep the RPC transport. Finishing a turn makes the member idle only after Pi reports `agent_settled`. It does not stop the process.
|
|
61
|
+
|
|
62
|
+
Children load ac-teams explicitly and otherwise keep normal Pi extensions, skills, authentication, and cwd instructions. They receive their brief, not the parent's conversation. Load ac-teams only once in the root, either through Pi package settings or an explicit extension path.
|
|
63
|
+
|
|
64
|
+
Children can delegate through the same coordinator, subject to depth and capacity. Delegation still needs user authorization. Keep briefs bounded, agree on file ownership, and use separate worktrees for concurrent writers.
|
|
65
|
+
|
|
66
|
+
## Track progress separately from ownership
|
|
67
|
+
|
|
68
|
+
Example `team_task` arguments:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{"action":"create","label":"Parser review","title":"Review parser errors and malformed input","description":"Check malformed input and report concrete failures; no edits."}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Each task has a stable team-local `number` and a 1–3-word `label` (at most 60 characters). The graph and list show `#3 Parser review`; details retain the full title, description, and UUID.
|
|
75
|
+
|
|
76
|
+
Numbers follow creation order. Editing, filtering, or reopening tasks never changes their numbers. A concise title can supply an omitted label; longer titles need an explicit label.
|
|
77
|
+
|
|
78
|
+
Interim and final goals are ordinary tasks. Use dependencies for real prerequisites, not to make the diagram connected. Independent tasks remain disconnected until they genuinely contribute to a dependent task.
|
|
79
|
+
|
|
80
|
+
Progress and ownership remain separate:
|
|
81
|
+
|
|
82
|
+
- **Progress:** `status` is `todo`, `in_progress`, or `done`
|
|
83
|
+
- **Ownership:** `owner` is one member ID, or absent
|
|
84
|
+
- **Dependencies:** `dependencies` lists prerequisite task IDs. Returned `blockedBy` lists those not yet done; the coordinator calculates it rather than storing it as a status.
|
|
85
|
+
|
|
86
|
+
Use the returned task ID with these actions:
|
|
87
|
+
|
|
88
|
+
| Action | Effect |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| `claim` | Reserve an unowned to-do task, even if blocked. Progress stays `todo`. |
|
|
91
|
+
| `start` | The owner moves `todo` to `in_progress`, only when every dependency is `done`. |
|
|
92
|
+
| `complete` | The owner moves `in_progress` to `done`, with `acceptance: true`. Ownership remains. |
|
|
93
|
+
| `release` | Clear ownership. In-progress work returns to `todo`; done work stays `done`. |
|
|
94
|
+
| `reopen` | Explicitly move `done` to `todo`, retaining any owner. Refuse if a dependent is in progress or done. |
|
|
95
|
+
|
|
96
|
+
Only the owner can start, complete, or release its work. An ancestor may explicitly release a stopped or interrupted descendant's ownership. The owner or root can reopen an owned task; any member can reopen an unowned one. Done tasks cannot be claimed until reopened.
|
|
97
|
+
|
|
98
|
+
Include `dependencies` on creation or `edit`. Any member can edit unowned to-do work; only the owner can edit reserved to-do work. In-progress and done tasks cannot be edited. The coordinator rejects unknown dependencies and cycles. An optional `revision` rejects stale mutations.
|
|
99
|
+
|
|
100
|
+
`acceptance: true` asserts that the agent checked the acceptance criteria; it is not an independent test runner. Stop/crash retains ownership and progress. There is no automatic reassignment.
|
|
101
|
+
|
|
102
|
+
## Send messages instead of polling
|
|
103
|
+
|
|
104
|
+
Example `team_message` arguments:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{"action":"send","recipients":["root"],"text":"Parser review complete. No edits; two malformed-input cases need tests."}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Omit `recipients` to notify all other live members. Explicit sets must contain unique live member IDs; an invalid set rejects the whole send. All team members can read the full history, including direct messages.
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{"action":"history","after":0,"limit":20}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Use the last returned `seq` as the next `after` cursor. `search` adds a case-sensitive literal `query`; results remain cursor-paged. Reads never consume messages. Task and message result pages are limited to 100 items.
|
|
117
|
+
|
|
118
|
+
New messages queue a compact Pi follow-up: an idle member wakes, while a busy member finishes its current work first. Notifications batch for 50 ms and reference history rather than copying every message into context. Notification acknowledgement means queued, not read or acted on.
|
|
119
|
+
|
|
120
|
+
Messages survive crashes; exactly-once delivery or model execution does not. Avoid acknowledgement-only replies.
|
|
121
|
+
|
|
122
|
+
## Companion tools add guidance or terminal management
|
|
123
|
+
|
|
124
|
+
ac-teams works alone. ACStack adds planning, review, and shipping skills; Herdr adds terminal tabs, panes, and visible root sessions. These are companion capabilities, not automatic integrations. ac-teams does not open a Herdr pane for each member. Interactive members use a team-private tmux server and open in the current terminal when selected; headless roots use RPC members.
|
|
125
|
+
|
|
126
|
+
Other delegation tools can coexist. ac-teams warns when `Agent`, `SubagentWorkflow`, or `subagent` is active, but does not disable them. Its limits cover only members launched through `team_agent`. Use Pi's resource settings to disable other launchers if you want one team authority. Shell access and same-user extensions are not sandboxed.
|
|
127
|
+
|
|
128
|
+
[Back to README](../README.md)
|