ac-teams 0.0.7 → 0.0.9

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.
@@ -0,0 +1,34 @@
1
+ id: main-session
2
+ name: Main session
3
+ summary: >-
4
+ A Pi session the user started, joined to a team, or promoted. Every main
5
+ session controls every member and other main sessions, shares the team's
6
+ tasks and messages, and belongs to one team at a time.
7
+ kind: component
8
+ channels: [cli]
9
+ relationships:
10
+ - id: user-drives-main
11
+ from: user
12
+ to: main-session
13
+ direction: one-way
14
+ label: Promotes, joins, and leaves through /teams in
15
+ - id: main-uses-coordinator
16
+ from: main-session
17
+ to: coordinator
18
+ direction: one-way
19
+ label: Hosts as owner, or connects to as a client
20
+ - id: main-writes-transcript
21
+ from: main-session
22
+ to: transcripts
23
+ direction: one-way
24
+ label: Writes its conversation and team entry to
25
+ - id: guard-reads-main
26
+ from: read-guard
27
+ to: main-session
28
+ direction: one-way
29
+ label: Finds no member role in
30
+ - id: coordinator-launches-main
31
+ from: coordinator
32
+ to: main-session
33
+ direction: one-way
34
+ label: Relaunches promoted members as
@@ -0,0 +1,28 @@
1
+ id: member
2
+ name: Member
3
+ summary: >-
4
+ An agent-launched Pi process with ACSTACK_AGENT_ROLE=member and AC_TEAMS_*
5
+ variables. It controls only its descendants, and its transcript stays under
6
+ ac-teams/<team>/<member>/ until promotion.
7
+ kind: component
8
+ relationships:
9
+ - id: coordinator-runs-member
10
+ from: coordinator
11
+ to: member
12
+ direction: one-way
13
+ label: Launches, stops, and resumes
14
+ - id: member-uses-coordinator
15
+ from: member
16
+ to: coordinator
17
+ direction: one-way
18
+ label: Calls team tools through
19
+ - id: member-writes-transcript
20
+ from: member
21
+ to: transcripts
22
+ direction: one-way
23
+ label: Writes its conversation to
24
+ - id: guard-reads-member
25
+ from: read-guard
26
+ to: member
27
+ direction: one-way
28
+ label: Reads ACSTACK_AGENT_ROLE=member in
@@ -0,0 +1,17 @@
1
+ id: read-guard
2
+ name: ACStack read guard
3
+ summary: >-
4
+ ACStack's large-read hook. It blocks a large untargeted read once in main
5
+ agents only, and reads ACSTACK_AGENT_ROLE on every call to decide.
6
+ kind: external-system
7
+ relationships:
8
+ - id: guard-reads-member
9
+ from: read-guard
10
+ to: member
11
+ direction: one-way
12
+ label: Reads ACSTACK_AGENT_ROLE=member in
13
+ - id: guard-reads-main
14
+ from: read-guard
15
+ to: main-session
16
+ direction: one-way
17
+ label: Finds no member role in
@@ -0,0 +1,13 @@
1
+ id: team-store
2
+ name: Team store
3
+ summary: >-
4
+ Private team state under ~/.pi/ac-teams/teams/<team>/: members with their
5
+ role, tasks, messages, owner.lock, and each main session's connection
6
+ token. Sandboxed members cannot read it.
7
+ kind: store
8
+ relationships:
9
+ - id: coordinator-writes-store
10
+ from: coordinator
11
+ to: team-store
12
+ direction: one-way
13
+ label: Holds owner.lock and records roles in
@@ -0,0 +1,23 @@
1
+ id: transcripts
2
+ name: Pi transcripts
3
+ summary: >-
4
+ Standard Pi session files. Main sessions sit at the top level of the
5
+ project's session folder, where /resume finds them. Members sit under
6
+ ac-teams/<team>/<member>/, where only /teams finds them.
7
+ kind: store
8
+ relationships:
9
+ - id: main-writes-transcript
10
+ from: main-session
11
+ to: transcripts
12
+ direction: one-way
13
+ label: Writes its conversation and team entry to
14
+ - id: member-writes-transcript
15
+ from: member
16
+ to: transcripts
17
+ direction: one-way
18
+ label: Writes its conversation to
19
+ - id: coordinator-moves-transcript
20
+ from: coordinator
21
+ to: transcripts
22
+ direction: one-way
23
+ label: Moves promoted transcripts within
@@ -0,0 +1,17 @@
1
+ id: user
2
+ name: User
3
+ summary: >-
4
+ Starts main sessions and is the only party who can promote a member, join a
5
+ session to a team, or approve a sandboxed member's full access.
6
+ kind: actor
7
+ relationships:
8
+ - id: user-drives-main
9
+ from: user
10
+ to: main-session
11
+ direction: one-way
12
+ label: Promotes, joins, and leaves through /teams in
13
+ - id: user-uses-herdr
14
+ from: user
15
+ to: herdr
16
+ direction: one-way
17
+ label: Switches between main sessions in
@@ -51,6 +51,8 @@ This is snapshot-based cleanup, not OS containment. Detached or uncaptured desce
51
51
 
52
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
53
 
54
+ Stopping a main session ends its Pi process; an exiting coordinator hands over first. Resuming another main session relaunches it in its own terminal.
55
+
54
56
  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
57
 
56
58
  ### Exit confirmation needs a Pi hook
@@ -59,6 +61,12 @@ Exit confirmation requires Pi's `session_before_exit` hook. The prerequisite is
59
61
 
60
62
  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
63
 
64
+ ### Coordinator handover
65
+
66
+ The main session holding `owner.lock` runs the coordinator. Before it exits it records whether each member was busy, idle, or waiting for input, then stops the members. Another connected main session takes the lock within seconds and runs the resume pass: busy members resume and are told their process restarted during a handover, idle members resume idle, and members waiting for input resume and ask again. The same pass runs when a main session opens a team with no coordinator running.
67
+
68
+ A main session that crashes is marked interrupted; any main session can resume it. Raising the member limit above 10 requires the coordinator's own session, because the confirmation prompt runs there.
69
+
62
70
  ### Crash recovery is best effort
63
71
 
64
72
  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.
@@ -79,7 +87,8 @@ Each root session uses `~/.pi/ac-teams/teams/<session-id>/`:
79
87
 
80
88
  - `state.json` contains membership, policy, tasks, messages, claims, and notification cursors
81
89
  - Member transcripts live under Main's session directory in `ac-teams/<team>/<member>/`, normally `~/.pi/agent/sessions/<project>/ac-teams/...`; Pi's `/resume` lists only top-level sessions, so use `/teams` to find them
82
- - `owner.lock` and `coordinator.sock` coordinate the running root
90
+ - `owner.lock` and `coordinator.sock` coordinate the main session running the coordinator; other main sessions authenticate with tokens stored in `state.json`
91
+ - Promoted members' transcripts move to `<session folder>/` beside other top-level sessions, and their `~/.pi/ac-teams/agents/<id>` folder is removed
83
92
  - Interactive teams also own `t.sock`, the private tmux socket, and per-member terminal environment files; shutdown removes those files
84
93
 
85
94
  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.
@@ -88,7 +97,9 @@ State schema 3 adds stable task numbers and short labels. Opening a schema 1 or
88
97
 
89
98
  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
99
 
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.
100
+ State schema 4 adds a role to each record: `main` or `member`. Opening a schema 3 team makes the root record a main session and every other record a member. A record without a role has left the team. A promotion records each step, so a failure rolls the member back to a stopped member with its original transcript path.
101
+
102
+ Only the coordinator 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
103
 
93
104
  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
105
 
package/docs/usage.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Use ac-teams
2
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.
3
+ ac-teams provides three tools with lightweight guidance for tracking delegated work. Your Pi session is a main session; the agents it launches are members. The first main session opens coordination state on the first team request. See [main sessions](#main-sessions-share-one-team) for adding more.
4
4
 
5
5
  | Tool | Actions | Main rule |
6
6
  | --- | --- | --- |
@@ -8,7 +8,7 @@ ac-teams provides three tools without prescribing a workflow. Your Pi session is
8
8
  | `team_task` | `create`, `list`, `read`, `edit`, `claim`, `start`, `release`, `complete`, `reopen` | Claim reserves work; dependencies gate starting, not ownership |
9
9
  | `team_message` | `send`, `history`, `search` | Recipients select who receives notification, not who can read |
10
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.
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 member; main sessions keep running. `/teams join` and `/teams leave` change which team this session belongs to. See [operations](operations.md) for limits, recovery, and worktree cleanup.
12
12
 
13
13
  ## Navigate without stopping members
14
14
 
@@ -38,6 +38,17 @@ The `+N lines` hint shows the hidden detail count. Ctrl+O expands the full reque
38
38
 
39
39
  Team notification messages remain compact; Ctrl+O expands their labeled fields. UI state colors do not replace the underlying progress, ownership, or dependency fields.
40
40
 
41
+ ## Main sessions share one team
42
+
43
+ A team can have several main sessions, each a top-level Pi session a person drives. Members are the agents they launch. Every main session controls every member and can stop or resume other main sessions; a member controls only its own descendants and never a main session.
44
+
45
+ - **Promote:** On the panel's Teammates tab, `P` stops a member and relaunches it as a main session. It keeps its session ID and history, its transcript moves to the normal Pi session folder so `/resume` lists it, and it stays in the team. Under Herdr it opens in a new tab of the workspace for its worktree; otherwise it runs in its own tmux server and ac-teams prints the attach command. A member with enforced access asks first, because the promoted session runs without the container.
46
+ - **Join:** `/teams join` lists the teams in this project and adds this session to the chosen one as a main session, then posts a summary of open tasks, owners, and recent messages. It refuses a session already in that team, or one already in a team with other members.
47
+ - **Leave:** `/teams leave` returns this session's in-progress tasks to `todo`, clears their ownership, and drops its main-session role; its record keeps its history. The last main session cannot leave while members are live.
48
+ - **Resume:** A session remembers its team in its transcript. Resuming it reconnects to the team; if no coordinator is running, ac-teams offers to run it here. Declining turns the team tools off for this session.
49
+
50
+ One main session runs the coordinator; the others connect to it. When that session exits, another main session takes over automatically and resumes the members that were working. See [operations](operations.md#coordinator-handover).
51
+
41
52
  ## Show tasks and configure the displays
42
53
 
43
54
  The task summary sits above the input editor; the agent selector sits below the editor. The task summary shows completed/total counts and up to five numbered task labels, ordered by:
@@ -57,12 +68,27 @@ Hiding a display does not stop agents, change tasks, or disable `/teams`. With t
57
68
 
58
69
  ## Give members bounded assignments
59
70
 
60
- Example `team_agent` arguments:
71
+ Before delegating a deliverable, create or reuse a shared task and include its ID in the member's brief. Track independently owned outcomes, not every agent, tool call, or procedural step. For example:
72
+
73
+ - A fix and an independently owned test assignment need separate tasks.
74
+ - A diagnosis others need for follow-up needs a task, even if the investigation is read-only.
75
+ - A quick lookup, clarification, or brief second opinion can skip a task unless its result needs coordination or follow-up.
76
+ - Running tests as part of a fix usually belongs to the fix's existing task.
77
+
78
+ Review the current task list and relevant details first. Reuse an existing task when it covers the assignment. If none does, create one with acceptance criteria. Example `team_task` arguments:
79
+
80
+ ```json
81
+ {"action":"create","label":"Parser review","title":"Review parser errors and malformed input","description":"Read-only review of src/parser.ts. Acceptance: report concrete malformed-input failures with reproduction steps, or report that none were found."}
82
+ ```
83
+
84
+ Put the returned task UUID in the brief in place of `<task-id>`. Example `team_agent` arguments:
61
85
 
62
86
  ```json
63
- {"action":"launch","name":"parser-review","brief":"Review src/parser.ts. Read only; do not delegate or edit. Send findings to root through team_message."}
87
+ {"action":"launch","name":"parser-review","brief":"Task <task-id>: claim and start it, then review src/parser.ts. Read only; do not delegate or edit. Send findings to root through team_message. Complete the task after checking its acceptance criteria, or report blockers."}
64
88
  ```
65
89
 
90
+ These are prompt guidelines, not launch requirements. ac-teams neither creates tasks automatically nor blocks launches without tasks.
91
+
66
92
  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.
67
93
 
68
94
  `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.
@@ -75,11 +101,7 @@ Children can delegate through the same coordinator, subject to depth and capacit
75
101
 
76
102
  ## Track progress separately from ownership
77
103
 
78
- Example `team_task` arguments:
79
-
80
- ```json
81
- {"action":"create","label":"Parser review","title":"Review parser errors and malformed input","description":"Check malformed input and report concrete failures; no edits."}
82
- ```
104
+ Task owners claim and start their work, then complete it after checking acceptance criteria or report blockers. Claiming reserves a task; starting also requires its dependencies to be done.
83
105
 
84
106
  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.
85
107
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ac-teams",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "Small, persistent teams for Pi",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/commands.ts CHANGED
@@ -3,7 +3,7 @@ import { memberName, type Member } from "./types.ts";
3
3
  import { cleanText } from "./render.ts";
4
4
 
5
5
  type NamedMember = Pick<Member, "id" | "name" | "status">;
6
- const actions = ["panel", "teammate", "config", "back", "stop", "status"];
6
+ const actions = ["panel", "teammate", "config", "back", "stop", "status", "join", "leave"];
7
7
 
8
8
  export function resolveTeammate(members: NamedMember[], value: string): string | undefined {
9
9
  const key = value === "main" ? "root" : value;