indus-swarms 0.1.0

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.
Files changed (52) hide show
  1. package/AGENTS.md +14 -0
  2. package/LICENSE +21 -0
  3. package/README.md +119 -0
  4. package/docs/claude-parity.md +151 -0
  5. package/docs/field-notes-teams-setup.md +107 -0
  6. package/docs/smoke-test-plan.md +146 -0
  7. package/eslint.config.js +74 -0
  8. package/extensions/teams/README.md +23 -0
  9. package/extensions/teams/activity-tracker.ts +234 -0
  10. package/extensions/teams/cleanup.ts +31 -0
  11. package/extensions/teams/fs-lock.ts +87 -0
  12. package/extensions/teams/hooks.ts +363 -0
  13. package/extensions/teams/index.ts +18 -0
  14. package/extensions/teams/leader-attach-commands.ts +221 -0
  15. package/extensions/teams/leader-inbox.ts +214 -0
  16. package/extensions/teams/leader-info-commands.ts +140 -0
  17. package/extensions/teams/leader-lifecycle-commands.ts +559 -0
  18. package/extensions/teams/leader-messaging-commands.ts +148 -0
  19. package/extensions/teams/leader-plan-commands.ts +95 -0
  20. package/extensions/teams/leader-spawn-command.ts +149 -0
  21. package/extensions/teams/leader-task-commands.ts +435 -0
  22. package/extensions/teams/leader-team-command.ts +382 -0
  23. package/extensions/teams/leader-teams-tool.ts +1075 -0
  24. package/extensions/teams/leader.ts +925 -0
  25. package/extensions/teams/mailbox.ts +131 -0
  26. package/extensions/teams/model-policy.ts +142 -0
  27. package/extensions/teams/names.ts +121 -0
  28. package/extensions/teams/paths.ts +37 -0
  29. package/extensions/teams/protocol.ts +241 -0
  30. package/extensions/teams/spawn-types.ts +36 -0
  31. package/extensions/teams/task-store.ts +544 -0
  32. package/extensions/teams/team-attach-claim.ts +205 -0
  33. package/extensions/teams/team-config.ts +335 -0
  34. package/extensions/teams/team-discovery.ts +59 -0
  35. package/extensions/teams/teammate-rpc.ts +261 -0
  36. package/extensions/teams/teams-panel.ts +1186 -0
  37. package/extensions/teams/teams-style.ts +322 -0
  38. package/extensions/teams/teams-ui-shared.ts +89 -0
  39. package/extensions/teams/teams-widget.ts +212 -0
  40. package/extensions/teams/worker.ts +605 -0
  41. package/extensions/teams/worktree.ts +103 -0
  42. package/package.json +53 -0
  43. package/scripts/e2e-rpc-test.mjs +277 -0
  44. package/scripts/integration-claim-test.mts +157 -0
  45. package/scripts/integration-hooks-remediation-test.mts +382 -0
  46. package/scripts/integration-spawn-overrides-test.mts +398 -0
  47. package/scripts/integration-todo-test.mts +533 -0
  48. package/scripts/lib/pi-workers.ts +105 -0
  49. package/scripts/smoke-test.mts +764 -0
  50. package/scripts/start-tmux-team.sh +91 -0
  51. package/skills/agent-teams/SKILL.md +180 -0
  52. package/tsconfig.strict.json +22 -0
package/AGENTS.md ADDED
@@ -0,0 +1,14 @@
1
+ # AGENTS.md
2
+
3
+ Project-specific guidance for AI agents working in this repository.
4
+
5
+ ## Operating Intent (Critical)
6
+
7
+ This project is **agent-driven**, not user-operated.
8
+
9
+ - Treat the human as setting goals/outcomes, not executing operational steps.
10
+ - Prefer autonomous agent flows (tool actions, policies, retries, task transitions).
11
+ - Do **not** rely on manual user remediation as the default path.
12
+ - UI panels and slash commands are primarily for observability/debugging and emergency override.
13
+ - Quality-gate failures should be handled by agent policy (warn/followup/reopen/reopen_followup), not by asking the user to manually clear state.
14
+ - Human-in-the-loop steps should happen only when explicitly required by policy or requested by the user.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Thomas Mustier
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 ADDED
@@ -0,0 +1,119 @@
1
+ # indus-swarms (pi-agent-teams)
2
+
3
+ A lightweight extension for the `indusagi` CLI that brings Claude-style agent teams to your Pi workflows. The leader process manages shared task lists, mailboxes, and team status while spawning autonomous teammates (workers) that claim, execute, and report on tasks.
4
+
5
+ ## What it provides
6
+
7
+ 1. **Team coordination primitives** — shared task list files, dependency tracking, and auto-claiming keep multiple agents working without manual juggling.
8
+ 2. **Messaging layer** — direct `DM` mailboxes, broadcasts, and steering instructions let you nudge teammates from the leader session.
9
+ 3. **Lifecycle control** — graceful shutdown, kill, prune, and cleanup keep team artifacts tidy; widgets show real-time status.
10
+ 4. **Model/workspace control** — spawn teammates with fresh or branched contexts, shared workspaces or per-agent git worktrees, and optional plan/approval flows.
11
+ 5. **Hook + widget support** — leader-side hooks can enforce quality gates and the `/tw` widget surfaces tasks, inboxes, and shortcuts like `m` for message and `t` to toggle task view.
12
+
13
+ ## Installation
14
+
15
+ > Requires Node 20+ and the `indusagi` CLI. Install once per machine, then install the extension however you prefer:
16
+
17
+ ```bash
18
+ npm install indusagi indusagi-coding-agent
19
+ ```
20
+
21
+ **Option A — install from npm:**
22
+
23
+ ```bash
24
+ indusagi install npm:@tmustier/pi-agent-teams
25
+ ```
26
+
27
+ **Option A2 — install the renamed package (if published):**
28
+
29
+ ```bash
30
+ indusagi install indus-swarms
31
+ ```
32
+
33
+ **Option B — load directly for development:**
34
+
35
+ ```bash
36
+ indusagi -e /Users/varunisrani/indusagi-ts/indus-swarms/extensions/teams/index.ts
37
+ ```
38
+
39
+ **Option C — install from the local folder:**
40
+
41
+ ```bash
42
+ indusagi install /Users/varunisrani/indusagi-ts/indus-swarms
43
+ ```
44
+
45
+ Once installed, run `indusagi` as usual and the extension auto-discovers.
46
+
47
+ If you prefer installing directly via npm (without `indusagi install`), run:
48
+ ```
49
+ npm install indus-swarms
50
+ ```
51
+ Then load it via
52
+ ```
53
+ indusagi -e ./node_modules/indus-swarms/extensions/teams/index.ts
54
+ ```
55
+
56
+ ## Quick usage
57
+
58
+ 1. Start `indusagi`.
59
+ 2. Confirm the extension is active with `/team id` or `/team help`.
60
+ 3. Spawn teammates manually:
61
+ ```text
62
+ /team spawn alice shared
63
+ /team spawn bob branch worktree
64
+ ```
65
+ 4. Create tasks and assign them:
66
+ ```text
67
+ /team task add alice: Explore AGENTS.md
68
+ /team task list
69
+ /team task assign 1 bob
70
+ ```
71
+ 5. Communicate:
72
+ - `/team dm <name> <msg>` — mailbox DM
73
+ - `/team broadcast <msg>` — message everyone
74
+ - `/team steer <name> <msg>` — steering for RPC workers
75
+ 6. Monitor progress with `/tw` (or `/team panel`) and use shortcuts (`t` for current agent tasks, `m` for a DM, `k` to kill, etc.).
76
+ 7. When you are done:
77
+ ```text
78
+ /team shutdown
79
+ /team cleanup
80
+ ```
81
+
82
+ Alternatively, `/swarm <task>` lets the model spawn teammates, delegate tasks, and coordinate the work for you.
83
+
84
+ ## Environment variables
85
+
86
+ | Variable | Purpose | Default |
87
+ | --- | --- | --- |
88
+ | `INDUS_TEAMS_ROOT_DIR` | Root directory for all team artifacts (task lists, mailboxes, sessions). Defaults to `~/.indusagi/agent/teams` (legacy `~/.pi/agent/teams` also works). | `~/.indusagi/agent/teams` |
89
+ | `INDUS_TEAMS_DEFAULT_AUTO_CLAIM` | Auto-claim new tasks when teammates idle. | `1` |
90
+ | `INDUS_TEAMS_STYLE` | UI style (`normal`, `soviet`, `pirate`, or custom). | `normal` |
91
+ | `INDUS_TEAMS_HOOKS_ENABLED` | Enable leader-side hooks/quality gates. | `0` |
92
+ | `INDUS_TEAMS_HOOKS_DIR` | Directory holding `on_idle`, `on_task_completed`, `on_task_failed` hooks. | `<teamsRoot>/_hooks` |
93
+ | `INDUS_TEAMS_HOOK_TIMEOUT_MS` | Hook timeout in milliseconds. | `60000` |
94
+ | `INDUS_TEAMS_HOOKS_FAILURE_ACTION` | Policy when a hook fails (`warn`, `followup`, `reopen`, `reopen_followup`). | `warn` |
95
+ | `INDUS_TEAMS_HOOKS_MAX_REOPENS_PER_TASK` | Max reopen count when hooks requeue tasks. | `3` |
96
+ | `INDUS_TEAMS_HOOKS_FOLLOWUP_OWNER` | Owner of follow-up tasks created after hook failures (`member`, `lead`, `none`). | `member` |
97
+
98
+ Add custom styles under `~/.indusagi/agent/teams/_styles/<style>.json` to override naming and lifecycle copy.
99
+
100
+ ## Development & tests
101
+
102
+ ```bash
103
+ npm run check # typecheck + lint via tsx/eslint
104
+ npm run smoke-test # automated filesystem smoke test
105
+ node scripts/e2e-rpc-test.mjs # leader + RPC teammate handshake
106
+ ./scripts/start-tmux-team.sh # helper that launches leader + tmux worker panes
107
+ ```
108
+
109
+ Worker processes run `indusagi --mode rpc` with the same extension in worker mode via `scripts/lib/pi-workers.ts`.
110
+
111
+ ## Tips
112
+
113
+ - Use `/team attach list` and `/team attach <teamId>` to reconnect to another leader session.
114
+ - For structured automation, invoke the built-in `teams` tool manually via JSON (see `extensions/teams/leader-teams-tool.ts`).
115
+ - Keep `PI_TEAMS_ROOT_DIR` isolated per experiment to easily clean team directories.
116
+
117
+ ## License
118
+
119
+ MIT
@@ -0,0 +1,151 @@
1
+ # Claude Agent Teams parity roadmap (indus-swarms / pi-agent-teams)
2
+
3
+ Last updated: 2026-02-10
4
+
5
+ This document tracks **feature parity gaps** between:
6
+
7
+ - Claude Code **Agent Teams** (official docs)
8
+ - https://code.claude.com/docs/en/agent-teams#control-your-agent-team
9
+ - https://code.claude.com/docs/en/interactive-mode#task-list
10
+
11
+ …and this repository’s implementation:
12
+
13
+ - `indus-swarms` (pi-agent-teams Pi extension)
14
+
15
+ > Terminology note: this extension supports `PI_TEAMS_STYLE=<style>`.
16
+ > This doc often uses “comrade” as a generic stand-in for “worker/teammate”, but **styles can customize terminology, naming, and lifecycle copy**.
17
+ > Built-ins: `normal`, `soviet`, `pirate`. Custom styles live under `~/.pi/agent/teams/_styles/`.
18
+
19
+ ## Scope / philosophy
20
+
21
+ - Target the **same coordination primitives** as Claude Teams:
22
+ - shared task list
23
+ - mailbox messaging
24
+ - long-lived workers
25
+ - Prefer **inspectable, local-first artifacts** (files + lock files).
26
+ - Avoid guidance that bypasses Claude feature gating; we only document behavior.
27
+ - Accept that some Claude UX (terminal keybindings + split-pane integration) may not be achievable in Pi without deeper TUI/terminal integration.
28
+
29
+ ## Pi-specific extras (not Claude parity)
30
+
31
+ These are intentional differences / additions:
32
+
33
+ - **Configurable styles** (`/team style …`) for terminology + naming + lifecycle copy.
34
+ - **Git worktrees** for isolation (`/team spawn <name> … worktree`).
35
+ - **Session branching** (clone leader context into a teammate).
36
+ - A **status widget + interactive panel** (`/tw`, `/team panel`).
37
+
38
+ ## Parity matrix (docs-oriented)
39
+
40
+ Legend: ✅ implemented • 🟡 partial • ❌ missing
41
+
42
+ | Area | Claude docs behavior | Pi Teams status | Notes / next step | Priority |
43
+ | --- | --- | --- | --- | --- |
44
+ | Enablement | `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` + settings | N/A | Pi extension is available when installed/loaded. | — |
45
+ | Team config | `~/.claude/teams/<team>/config.json` w/ members | ✅ | `extensions/teams/team-config.ts` (under `~/.pi/agent/teams/...` or `PI_TEAMS_ROOT_DIR`). | P0 |
46
+ | Task list (shared) | `~/.claude/tasks/<taskListId>/` + states + deps | ✅ | File-per-task + deps (`blockedBy`/`blocks`); `/team task dep add|rm|ls`; self-claim skips blocked tasks. | P0 |
47
+ | Self-claim | Comrades self-claim next unassigned, unblocked task; file locking | ✅ | `claimNextAvailableTask()` + locks; enabled by default (`PI_TEAMS_DEFAULT_AUTO_CLAIM=1`). | P0 |
48
+ | Explicit assign | Lead assigns task to comrade | ✅ | `/team task assign` sets owner + pings via mailbox. | P0 |
49
+ | “Message” vs “broadcast” | Send to one comrade or all comrades | ✅ | `/team dm` + `/team broadcast` use mailbox; `/team send` uses RPC. Recipients = config workers + RPC map + active task owners. | P0 |
50
+ | Comrade↔comrade messaging | Comrades message each other directly | ✅ | Worker tool `team_message`; messages via mailbox + CC leader via `peer_dm_sent`. | P1 |
51
+ | Display modes | In-process selection (Shift+Up/Down); split panes (tmux/iTerm) | ❌ | Pi has widget/panel + commands, but no terminal-level comrade navigation/panes. | P2 |
52
+ | Delegate mode | Lead restricted to coordination-only tools | ✅ | `/team delegate [on|off]`; `tool_call` blocks `bash/edit/write`; widget shows `[delegate]`. | P1 |
53
+ | Plan approval | Comrade can be “plan required” and needs lead approval to implement | ✅ | `/team spawn <name> plan` → read-only tools; sends `plan_approval_request`; `/team plan approve|reject`. | P1 |
54
+ | Shutdown handshake | Lead requests shutdown; comrade can approve/reject | ✅ | Protocol: `shutdown_request` → `shutdown_approved` / `shutdown_rejected`. `/team shutdown <name>` (graceful), `/team kill <name>` (SIGTERM). Wording is style-controlled (e.g. “was asked to shut down”, “walked the plank”). | P1 |
55
+ | Cleanup team | “Clean up the team” removes shared resources after comrades stopped | ✅ | `/team cleanup [--force]` deletes only `<teamsRoot>/<teamId>` after safety checks. | P1 |
56
+ | Hooks / quality gates | `ComradeIdle`, `TaskCompleted` hooks | 🟡 | Optional leader-side hook runner (idle/task-complete/task-fail) via `PI_TEAMS_HOOKS_ENABLED=1` + scripts under `_hooks/`; inline failure surfacing + failure-action policies (`warn`/`followup`/`reopen`/`reopen_followup`) implemented; stable hook context payload exposed via `PI_TEAMS_HOOK_CONTEXT_JSON` + auto-remediation flow (reopen cap / follow-up owner policy / teammate notification). Runtime policy changes are agent-invocable via `teams` actions (`hooks_policy_get` / `hooks_policy_set`). | P2 |
57
+ | Task list UX | Ctrl+T toggle; show all/clear tasks by asking | 🟡 | Widget + `/team task list` + `/team task show` + `/team task clear`; panel supports fast `t`/`shift+t` toggle into task-centric view (`Ctrl+T` is reserved by Pi for thinking blocks). | P0 |
58
+ | Shared task list across sessions | `CLAUDE_CODE_TASK_LIST_ID=...` | ✅ | Worker env: `PI_TEAMS_TASK_LIST_ID` (manual workers). Leader: `/team task use <taskListId>` (persisted). Newly spawned workers inherit; existing workers need restart. | P1 |
59
+ | Join/attach flow | Join existing team context from another running session | 🟡 | `/team attach list`, `/team attach <teamId> [--claim]`, `/team detach` plus claim heartbeat/takeover handshake added. Widget/panel now show attached-mode banner + detach hint. | P2 |
60
+
61
+ ## Prioritized roadmap
62
+
63
+ ### P0 (done): collaboration primitives parity
64
+
65
+ 1) **Task dependency commands + UX** ✅
66
+ - `/team task dep add <id> <depId>` / `dep rm ...` / `dep ls <id>`
67
+ - `task list` output shows blocked status + deps/blocks summary
68
+ - `/team task show <id>` shows full description + `metadata.result`
69
+
70
+ 2) **Broadcast messaging** ✅
71
+ - `/team broadcast <msg...>` (mailbox broadcast)
72
+
73
+ 3) **Task list hygiene** ✅
74
+ - `/team task clear [completed|all] [--force]` (safe delete within `teamsRoot/teamId`)
75
+
76
+ ### P1 (done): governance + lifecycle parity
77
+
78
+ 4) **Shutdown handshake** ✅
79
+ - `shutdown_request` → `shutdown_approved` / `shutdown_rejected`
80
+ - Worker rejects when busy (streaming + active task), auto-approves when idle
81
+ - `/team shutdown <name> [reason...]` (graceful), `/team kill <name>` (force)
82
+
83
+ 5) **Plan approval** ✅
84
+ - `/team spawn <name> ... plan` sets `PI_TEAMS_PLAN_REQUIRED=1`
85
+ - Worker starts read-only; submits `plan_approval_request`
86
+ - `/team plan approve|reject <name>`
87
+ - Agent-driven equivalent via `teams` tool: `plan_approve` / `plan_reject`
88
+
89
+ 6) **Delegate mode (leader)** ✅
90
+ - `/team delegate [on|off]` (or `PI_TEAMS_DELEGATE_MODE=1`)
91
+ - Blocks `bash/edit/write` while active
92
+
93
+ 7) **Cleanup** ✅
94
+ - `/team cleanup [--force]` deletes only `<teamsRoot>/<teamId>` after safety checks.
95
+
96
+ 8) **Peer-to-peer messaging** ✅
97
+ - Worker tool `team_message`
98
+ - Mailbox transport; leader CC notifications
99
+
100
+ 9) **Shared task list across sessions** ✅
101
+ - `/team task use <taskListId>` + persisted `config.json`
102
+
103
+ ### P2: UX + “product-level” parity
104
+
105
+ 10) **Hooks / quality gates** 🟡 (partial)
106
+ - Implemented: optional leader-side hook runner (opt-in + timeout + logs).
107
+ - Implemented: inline failure surfacing (task metadata + widget warning + task-panel/task-show quality-gate details).
108
+ - Implemented: hook-failure policy controls via `PI_TEAMS_HOOKS_FAILURE_ACTION` (`warn`, `followup`, `reopen`, `reopen_followup`).
109
+ - Implemented: runtime team-level policy overrides (via `teams` tool: `hooks_policy_get` / `hooks_policy_set`) layered over env defaults.
110
+ - Implemented: standardized hook context contract (`PI_TEAMS_HOOK_CONTEXT_VERSION=1`, `PI_TEAMS_HOOK_CONTEXT_JSON`).
111
+ - Implemented: autonomous remediation helpers (auto-reopen cap, follow-up owner policy, teammate remediation notification).
112
+ - Implemented: deterministic integration coverage (`scripts/integration-hooks-remediation-test.mts`) for failed hook -> reopen/follow-up/nudge flow.
113
+ - Still missing: broader contract versioning story + richer policy visualization UX.
114
+
115
+ 11) **Better comrade interaction UX (within Pi constraints)** 🟡 (partial)
116
+ - Implemented: panel overview shows selected teammate context (active/last completed task + last transcript event).
117
+ - Implemented: faster keyboard controls (`w/s`, `1-9`, `m/d`).
118
+ - Implemented: task-centric panel mode (`t`/`shift+t`) with owned-task drilldown, dependency/block visibility, and quick jump back to transcript (`Ctrl+T` reserved by Pi).
119
+ - Implemented: in-panel task mutations for selected task (`c` complete, `p` pending, `i` in-progress, `u` unassign).
120
+ - Implemented: in-panel reassignment flow (`r`) with teammate picker.
121
+ - Implemented: agent-invocable task mutations via `teams` tool (`task_assign`, `task_unassign`, `task_set_status`) so flows do not require manual panel interaction.
122
+ - Implemented: agent-invocable dependency/messaging actions via `teams` tool (`task_dep_add|rm|ls`, `message_dm|broadcast|steer`).
123
+ - Implemented: agent-invocable lifecycle actions via `teams` tool (`member_spawn|shutdown|kill|prune`).
124
+ - Implemented: agent-invocable governance actions via `teams` tool (`plan_approve|plan_reject`).
125
+ - Implemented: agent-invocable model policy introspection/check actions via `teams` tool (`model_policy_get|model_policy_check`) to validate spawn overrides before execution.
126
+ - Next: optional tmux split-pane integration and deeper dependency/task editing flows in panel.
127
+
128
+ 12) **Join/attach flow** 🟡 (partial)
129
+ - Implemented: `/team attach list`, `/team attach <teamId> [--claim]`, `/team detach`.
130
+ - Implemented: explicit attach claim handshake with heartbeat + force takeover (`--claim`).
131
+ - Implemented: attached-mode affordances in widget/panel (external team banner + `/team detach` hint).
132
+
133
+ ## Where changes would land (code map)
134
+
135
+ - Leader orchestration: `extensions/teams/leader.ts`
136
+ - Leader `/team` command dispatch: `extensions/teams/leader-team-command.ts`
137
+ - Attach/discovery commands: `extensions/teams/leader-attach-commands.ts`, `extensions/teams/team-discovery.ts`, `extensions/teams/team-attach-claim.ts`
138
+ - Leader LLM tool (`teams`): `extensions/teams/leader-teams-tool.ts`
139
+ - Worker mailbox polling + self-claim + protocols: `extensions/teams/worker.ts`
140
+ - Task store + locking: `extensions/teams/task-store.ts`, `extensions/teams/fs-lock.ts`
141
+ - Mailbox store + locking: `extensions/teams/mailbox.ts`
142
+ - Team config: `extensions/teams/team-config.ts`
143
+ - Styles + naming: `extensions/teams/teams-style.ts`
144
+ - Optional workspace isolation: `extensions/teams/worktree.ts`
145
+
146
+ ## Testing strategy
147
+
148
+ - Keep tests hermetic by setting `PI_TEAMS_ROOT_DIR` to a temp directory.
149
+ - Extend:
150
+ - `scripts/smoke-test.mts` (run via `npm run smoke-test`) for filesystem-only behaviors
151
+ - `scripts/e2e-rpc-test.mjs` for protocol flows (shutdown handshake, plan approval)
@@ -0,0 +1,107 @@
1
+ # Field notes: using `indus-swarms` (pi-agent-teams) for real (setup + surprises)
2
+
3
+ Date: 2026-02-07
4
+
5
+ Goal: dogfood the Teams extension to implement its own roadmap (Claude parity), and capture anything that surprised/confused us while setting it up.
6
+
7
+ > Terminology note: the extension supports `PI_TEAMS_STYLE=<style>`. Built-ins: `normal`, `soviet`, `pirate`. You can also add custom styles via `~/.pi/agent/teams/_styles/<style>.json`.
8
+
9
+ ## Test run: test1
10
+
11
+ Decisions: tmux session `pi-teams-test1`; `PI_TEAMS_ROOT_DIR=~/projects/indus-swarms/test1`; `teamId=0baaa0e6-8020-4d9a-bf33-c1a65f99a2f7`; workers started manually in tmux (not `/team spawn`).
12
+
13
+ First impressions:
14
+ - Manual tmux workers are usable. Initially the leader showed “(no comrades)” because it only tracked RPC-spawned workers; now manual workers **upsert themselves into `config.json` on startup**, and the leader widget renders online workers from team config.
15
+ - Pinning `PI_TEAMS_ROOT_DIR` made reruns/id discovery predictable (no “find the new folder” step).
16
+ - tmux workflow feels close to Claude-style split panes; bootstrap ergonomics still need smoothing.
17
+ - Surprise: `/team spawn <name> branch` failed once with `Entry <id> not found` (branch-from leaf missing on disk); `/team spawn <name> fresh` worked.
18
+ - Surprise (automation): when driving the leader via `tmux send-keys`, back-to-back `/team ...` commands sometimes only executed the first one unless we inserted a small delay.
19
+
20
+ ## Setup (tmux-based)
21
+
22
+ ### Why tmux?
23
+
24
+ - Pi sessions are long-lived and interactive.
25
+ - Our harness (and many CI environments) dislike background processes that keep stdio open.
26
+ - tmux gives us:
27
+ - a stable place to run a leader session
28
+ - optional separate panes/windows for worker sessions
29
+ - the ability to attach/detach without killing the team
30
+
31
+ ### Environment knobs used
32
+
33
+ - `PI_TEAMS_ROOT_DIR` — isolate Teams artifacts from `~/.pi/agent/teams` while experimenting.
34
+ - Recommendation: use a *fresh, empty* temp directory per run so it’s easy to discover the current teamId by listing the directory.
35
+
36
+ ### Session bootstrap (manual)
37
+
38
+ (There is also a helper script now: `./scripts/start-tmux-team.sh`.)
39
+
40
+ 1. Pick a temp Teams root:
41
+
42
+ ```bash
43
+ export PI_TEAMS_ROOT_DIR="/tmp/pi-teams-$(date +%Y%m%d-%H%M%S)"
44
+ mkdir -p "$PI_TEAMS_ROOT_DIR"
45
+ ```
46
+
47
+ 2. Start leader in tmux:
48
+
49
+ ```bash
50
+ tmux new -s pi-teams -c ~/projects/indus-swarms \
51
+ "PI_TEAMS_ROOT_DIR=$PI_TEAMS_ROOT_DIR indusagi -e ~/projects/indus-swarms/extensions/teams/index.ts"
52
+ ```
53
+
54
+ 3. In the leader session:
55
+
56
+ ```
57
+ /team help
58
+ /team spawn alice branch
59
+ /team spawn bob branch
60
+ /team task add alice: add /team broadcast command
61
+ /team task add bob: add task dependency commands
62
+ /team task list
63
+ ```
64
+
65
+ 4. Optional: start **interactive worker panes** (instead of leader-spawned RPC workers).
66
+
67
+ This currently requires discovering the leader’s `teamId` first (see “Surprises” below).
68
+
69
+ ## Surprises / confusion points (so far)
70
+
71
+ - **TeamId discoverability**: the leader uses `sessionId` as `teamId`. That’s convenient internally, but not obvious externally.
72
+ - Workaround used: point `PI_TEAMS_ROOT_DIR` at a fresh directory and `ls` it to find the generated `<teamId>` folder.
73
+ - Note: the team directory isn’t necessarily created instantly on process start (we saw a short delay), so scripts may need a small retry loop.
74
+ - Update: implemented `/team id` and `/team env <name>` (prints env vars + a one-liner to start a manual worker).
75
+
76
+ - **tmux vs `/team spawn`**: `/team spawn` uses `indusagi --mode rpc` subprocesses.
77
+ - Pros: simple, managed lifecycle.
78
+ - Cons: you don’t see a full interactive comrade UI like Claude’s split-pane mode.
79
+ - We manually started workers in separate tmux windows (setting `PI_TEAMS_WORKER=1`, `PI_TEAMS_TEAM_ID=...`, etc). This now shows up in the leader widget because workers upsert themselves into `config.json`, and the leader renders online workers from team config.
80
+ - Update: leader now renders comrades from `team config` and also auto-adds unknown senders on idle notifications (so manual tmux workers feel first-class).
81
+ - Improvement idea: optional spawn mode that starts a worker in a new tmux pane/window.
82
+
83
+ - **Two messaging paths** (`/team send` vs `/team dm`):
84
+ - `/team send` = RPC prompt (immediate “user message”)
85
+ - `/team dm` = mailbox message (Claude-style)
86
+ - Improvement idea: clearer naming and/or a single “message” command with a mode flag.
87
+
88
+ - **Runaway tasks / timeboxing**: a vague task prompt can turn into a long “research spiral”.
89
+ - In manual-tmux mode, there isn’t a great way (yet) for the leader to *steer* an in-flight run (unlike `/team steer` for RPC-spawned comrades).
90
+ - Improvement idea: add a mailbox-level “steer” protocol message that workers can treat as an in-flight follow-up if they’re currently running.
91
+
92
+ - **Failure semantics are underspecified**: tool failures show up in the worker UI, but our task store currently only supports `pending|in_progress|completed`.
93
+ - Update: `/team stop <name>` now sends a mailbox `abort_request`; workers treat aborts as aborts and reset the task back to `pending` (keeping the `owner`) instead of marking it `completed` with an empty result.
94
+ - Improvement idea: add `failed` status (and have workers write `metadata.failureReason` + include it in idle notifications), and only mark `completed` when we have an explicit success signal.
95
+
96
+ - **Worker shutdown + self-claim interaction**: when a worker receives SIGTERM it unassigns its non-completed tasks; other idle workers may immediately self-claim those now-unowned tasks.
97
+ - This is good for liveness, but surprising the first time you see task ownership “jump”.
98
+
99
+ - **Nice surprise: results are persisted with the task**: on completion, the worker writes `metadata.result` + `metadata.completedAt` into the task JSON file.
100
+ - This made it easy to recover outputs even after closing tmux windows.
101
+
102
+ ## Next notes to capture
103
+
104
+ - How easy it is to recover after restarting the leader
105
+ - How often we hit file/lock contention
106
+ - Whether auto-claim behavior matches expectations in mixed assigned/unassigned task lists
107
+ - Whether worktree mode is essential in practice (and what breaks when no git repo exists)
@@ -0,0 +1,146 @@
1
+ # indus-swarms (pi-agent-teams extension) — Runtime Smoke Test Plan
2
+
3
+ ## Prerequisites
4
+
5
+ - `indusagi` CLI installed (`indusagi --version` → `0.12.x+`)
6
+ - `node_modules/` present (run `npm install` or symlink from main repo)
7
+ - `npx tsx` available for running `.mts` test scripts
8
+
9
+ ## 1. Automated Unit Smoke Test (no interactive session)
10
+
11
+ Exercises all core primitives directly via `tsx`:
12
+
13
+ ```bash
14
+ npx tsx scripts/smoke-test.mts
15
+ # or: npm run smoke-test
16
+ ```
17
+
18
+ **What it tests** (overview):
19
+
20
+ | Module | Coverage |
21
+ |------------------|-----------------------------------------------------------------|
22
+ | `names.ts` | `sanitizeName` character replacement, edge cases |
23
+ | `fs-lock.ts` | `withLock` returns value, cleans up lock file |
24
+ | `mailbox.ts` | `writeToMailbox`, `popUnreadMessages`, read-once semantics |
25
+ | `task-store.ts` | CRUD, `startAssignedTask`, `completeTask`, `claimNextAvailable`,|
26
+ | | `unassignTasksForAgent`, dependencies, `clearTasks` |
27
+ | `team-config.ts` | `ensureTeamConfig` (idempotent), `upsertMember`, `setMemberStatus`, `loadTeamConfig` |
28
+ | `protocol.ts` | Structured message parsers (valid + invalid JSON + wrong type) |
29
+ | `indusagi` CLI | `indusagi --version` executes (skipped in CI if `indusagi` not on PATH) |
30
+
31
+ **Expected result:** `PASSED: <n> FAILED: 0`
32
+
33
+ ## 2. Extension Loading Test
34
+
35
+ Verify Pi can load the extension entry point without crashing:
36
+
37
+ ```bash
38
+ indusagi --no-extensions -e extensions/teams/index.ts --help
39
+ ```
40
+
41
+ **Expected:** exits 0, shows Pi help output (no TypeScript/import errors).
42
+
43
+ ## 3. Interactive Smoke Test (manual)
44
+
45
+ ### 3a. Launch Pi with the extension
46
+
47
+ ```bash
48
+ # From the repo root:
49
+ indusagi --no-extensions -e extensions/teams/index.ts
50
+ ```
51
+
52
+ Or, if the extension is symlinked into `~/.pi/agent/extensions/indus-swarms`:
53
+
54
+ ```bash
55
+ indusagi # auto-loads from extensions dir
56
+ ```
57
+
58
+ ### 3b. Check extension is active
59
+
60
+ ```
61
+ /team help
62
+ ```
63
+
64
+ **Expected:** shows usage lines for `/team spawn`, `/team task`, etc.
65
+
66
+ ### 3c. Spawn a teammate ("comrade" in soviet style)
67
+
68
+ ```
69
+ /team spawn agent1 fresh shared
70
+ ```
71
+
72
+ **Expected:** notification "Spawned agent1" or similar, widget shows `Teammate agent1: idle` (or `Comrade agent1: idle` in soviet style).
73
+
74
+ ### 3d. Create and assign a task
75
+
76
+ ```
77
+ /team task add agent1: Say hello
78
+ /team task list
79
+ ```
80
+
81
+ **Expected:** task #1 created, assigned to agent1, status `pending` → `in_progress`.
82
+
83
+ ### 3e. Verify mailbox delivery
84
+
85
+ ```
86
+ /team dm agent1 ping from lead
87
+ ```
88
+
89
+ **Expected:** "DM queued for agent1" notification.
90
+
91
+ ### 3f. Delegate via tool
92
+
93
+ Ask the model:
94
+ > "Delegate a task to agent1: write a haiku about coding"
95
+
96
+ **Expected:** the `teams` tool is invoked, task created and assigned.
97
+
98
+ ### 3g. Shutdown
99
+
100
+ ```
101
+ /team shutdown agent1
102
+ /team kill agent1
103
+ ```
104
+
105
+ **Expected:** agent1 goes offline, widget updates.
106
+
107
+ Optional: stop all teammates without ending the leader session:
108
+
109
+ ```
110
+ /team shutdown
111
+ ```
112
+
113
+ **Expected:** all teammates stop; leader remains active until you exit it (e.g. ctrl+d).
114
+
115
+ If old/manual teammates still show as idle (stale config entries), prune them:
116
+
117
+ ```
118
+ /team prune
119
+ # or: /team prune --all
120
+ ```
121
+
122
+ ## 4. Worker-side Smoke (verifying child process)
123
+
124
+ To test the worker role directly:
125
+
126
+ ```bash
127
+ PI_TEAMS_WORKER=1 \
128
+ PI_TEAMS_TEAM_ID=test-team \
129
+ PI_TEAMS_AGENT_NAME=agent1 \
130
+ PI_TEAMS_LEAD_NAME=team-lead \
131
+ PI_TEAMS_STYLE=normal \
132
+ indusagi --no-extensions -e extensions/teams/index.ts --mode rpc
133
+ ```
134
+
135
+ **Expected:** process starts in RPC mode, registers `team_message` tool, polls mailbox.
136
+
137
+ ## 5. Checklist Summary
138
+
139
+ | # | Test | Method | Status |
140
+ |---|-------------------------------|------------|--------|
141
+ | 1 | Unit primitives (60 asserts) | Automated | ✅ |
142
+ | 2 | Extension loading | CLI | ✅ |
143
+ | 3 | Interactive spawn/task/dm | Manual | 📋 |
144
+ | 4 | Worker-side RPC | Manual | 📋 |
145
+
146
+ ✅ = verified in this run, 📋 = documented for manual execution.
@@ -0,0 +1,74 @@
1
+ // @ts-check
2
+ import eslint from "@eslint/js";
3
+ import tseslint from "typescript-eslint";
4
+
5
+ export default tseslint.config(
6
+ {
7
+ ignores: [
8
+ "node_modules/**",
9
+ "dist/**",
10
+ "build/**",
11
+ "coverage/**",
12
+ ".artifacts/**",
13
+ ".research/**",
14
+ ".resume-sessions/**",
15
+ ],
16
+ },
17
+
18
+ eslint.configs.recommended,
19
+ ...tseslint.configs.recommended,
20
+
21
+ {
22
+ files: ["extensions/**/*.ts", "scripts/**/*.ts", "scripts/**/*.mts"],
23
+ rules: {
24
+ // ━━ Project invariants (AGENTS.md) ━━
25
+ "@typescript-eslint/no-explicit-any": "error",
26
+ "@typescript-eslint/no-non-null-assertion": "error",
27
+ "@typescript-eslint/ban-ts-comment": [
28
+ "error",
29
+ {
30
+ "ts-ignore": true,
31
+ "ts-expect-error": true,
32
+ "ts-nocheck": true,
33
+ "ts-check": false,
34
+ },
35
+ ],
36
+
37
+ // Imports/types
38
+ "@typescript-eslint/consistent-type-imports": [
39
+ "error",
40
+ { prefer: "type-imports", disallowTypeAnnotations: false },
41
+ ],
42
+
43
+ // General correctness
44
+ eqeqeq: ["error", "always"],
45
+
46
+ // Prefer TS-aware unused-vars
47
+ "no-unused-vars": "off",
48
+ "@typescript-eslint/no-unused-vars": [
49
+ "warn",
50
+ {
51
+ argsIgnorePattern: "^_",
52
+ varsIgnorePattern: "^_",
53
+ caughtErrorsIgnorePattern: "^_",
54
+ },
55
+ ],
56
+ },
57
+ },
58
+
59
+ // Scripts/tests: console is expected
60
+ {
61
+ files: ["scripts/**/*.ts", "scripts/**/*.mts"],
62
+ rules: {
63
+ "no-console": "off",
64
+ },
65
+ },
66
+
67
+ // Extension source: discourage stray console.log
68
+ {
69
+ files: ["extensions/**/*.ts"],
70
+ rules: {
71
+ "no-console": "warn",
72
+ },
73
+ },
74
+ );
@@ -0,0 +1,23 @@
1
+ # pi-teams (extension)
2
+
3
+ This directory contains the **Teams** extension entrypoint:
4
+
5
+ - `index.ts` (leader/worker dispatch)
6
+
7
+ The full project README (usage, commands, tests) lives at the repo root:
8
+
9
+ - `../../README.md`
10
+
11
+ ## Storage root override
12
+
13
+ By default, all Teams artifacts are stored under the Pi agent directory:
14
+
15
+ - `~/.pi/agent/teams/<teamId>/...`
16
+
17
+ For tests/CI (or if you want to keep Teams state separate), set:
18
+
19
+ - `PI_TEAMS_ROOT_DIR=/absolute/path`
20
+
21
+ Then the extension will store:
22
+
23
+ - `<PI_TEAMS_ROOT_DIR>/<teamId>/...`