iosm-cli 0.2.0 → 0.2.1

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 (90) hide show
  1. package/README.md +58 -47
  2. package/dist/core/agent-teams.d.ts.map +1 -1
  3. package/dist/core/agent-teams.js +38 -11
  4. package/dist/core/agent-teams.js.map +1 -1
  5. package/dist/core/failure-retrospective.d.ts +12 -0
  6. package/dist/core/failure-retrospective.d.ts.map +1 -0
  7. package/dist/core/failure-retrospective.js +115 -0
  8. package/dist/core/failure-retrospective.js.map +1 -0
  9. package/dist/core/project-index/index.d.ts +17 -0
  10. package/dist/core/project-index/index.d.ts.map +1 -0
  11. package/dist/core/project-index/index.js +323 -0
  12. package/dist/core/project-index/index.js.map +1 -0
  13. package/dist/core/project-index/types.d.ts +34 -0
  14. package/dist/core/project-index/types.d.ts.map +1 -0
  15. package/dist/core/project-index/types.js +2 -0
  16. package/dist/core/project-index/types.js.map +1 -0
  17. package/dist/core/sdk.d.ts.map +1 -1
  18. package/dist/core/sdk.js +8 -0
  19. package/dist/core/sdk.js.map +1 -1
  20. package/dist/core/shared-memory.d.ts +46 -0
  21. package/dist/core/shared-memory.d.ts.map +1 -0
  22. package/dist/core/shared-memory.js +253 -0
  23. package/dist/core/shared-memory.js.map +1 -0
  24. package/dist/core/slash-commands.d.ts.map +1 -1
  25. package/dist/core/slash-commands.js +5 -1
  26. package/dist/core/slash-commands.js.map +1 -1
  27. package/dist/core/subagents.js +1 -1
  28. package/dist/core/subagents.js.map +1 -1
  29. package/dist/core/swarm/gates.d.ts +9 -0
  30. package/dist/core/swarm/gates.d.ts.map +1 -0
  31. package/dist/core/swarm/gates.js +65 -0
  32. package/dist/core/swarm/gates.js.map +1 -0
  33. package/dist/core/swarm/index.d.ts +9 -0
  34. package/dist/core/swarm/index.d.ts.map +1 -0
  35. package/dist/core/swarm/index.js +9 -0
  36. package/dist/core/swarm/index.js.map +1 -0
  37. package/dist/core/swarm/locks.d.ts +21 -0
  38. package/dist/core/swarm/locks.d.ts.map +1 -0
  39. package/dist/core/swarm/locks.js +93 -0
  40. package/dist/core/swarm/locks.js.map +1 -0
  41. package/dist/core/swarm/planner.d.ts +16 -0
  42. package/dist/core/swarm/planner.d.ts.map +1 -0
  43. package/dist/core/swarm/planner.js +137 -0
  44. package/dist/core/swarm/planner.js.map +1 -0
  45. package/dist/core/swarm/retry.d.ts +16 -0
  46. package/dist/core/swarm/retry.d.ts.map +1 -0
  47. package/dist/core/swarm/retry.js +32 -0
  48. package/dist/core/swarm/retry.js.map +1 -0
  49. package/dist/core/swarm/scheduler.d.ts +48 -0
  50. package/dist/core/swarm/scheduler.d.ts.map +1 -0
  51. package/dist/core/swarm/scheduler.js +554 -0
  52. package/dist/core/swarm/scheduler.js.map +1 -0
  53. package/dist/core/swarm/spawn.d.ts +16 -0
  54. package/dist/core/swarm/spawn.d.ts.map +1 -0
  55. package/dist/core/swarm/spawn.js +42 -0
  56. package/dist/core/swarm/spawn.js.map +1 -0
  57. package/dist/core/swarm/state-store.d.ts +35 -0
  58. package/dist/core/swarm/state-store.d.ts.map +1 -0
  59. package/dist/core/swarm/state-store.js +106 -0
  60. package/dist/core/swarm/state-store.js.map +1 -0
  61. package/dist/core/swarm/types.d.ts +116 -0
  62. package/dist/core/swarm/types.d.ts.map +1 -0
  63. package/dist/core/swarm/types.js +2 -0
  64. package/dist/core/swarm/types.js.map +1 -0
  65. package/dist/core/system-prompt.d.ts.map +1 -1
  66. package/dist/core/system-prompt.js +3 -2
  67. package/dist/core/system-prompt.js.map +1 -1
  68. package/dist/core/tools/shared-memory.d.ts +23 -0
  69. package/dist/core/tools/shared-memory.d.ts.map +1 -0
  70. package/dist/core/tools/shared-memory.js +134 -0
  71. package/dist/core/tools/shared-memory.js.map +1 -0
  72. package/dist/core/tools/task.d.ts +8 -1
  73. package/dist/core/tools/task.d.ts.map +1 -1
  74. package/dist/core/tools/task.js +664 -123
  75. package/dist/core/tools/task.js.map +1 -1
  76. package/dist/modes/interactive/components/login-dialog.d.ts +1 -0
  77. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  78. package/dist/modes/interactive/components/login-dialog.js +27 -4
  79. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  80. package/dist/modes/interactive/components/subagent-message.d.ts.map +1 -1
  81. package/dist/modes/interactive/components/subagent-message.js +14 -0
  82. package/dist/modes/interactive/components/subagent-message.js.map +1 -1
  83. package/dist/modes/interactive/interactive-mode.d.ts +38 -0
  84. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  85. package/dist/modes/interactive/interactive-mode.js +1362 -31
  86. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  87. package/docs/cli-reference.md +11 -1
  88. package/docs/interactive-mode.md +42 -3
  89. package/docs/orchestration-and-subagents.md +96 -169
  90. package/package.json +4 -3
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- <h1 align="center">IOSM CLI v0.2.0</h1>
1
+ <h1 align="center">IOSM CLI v0.2.1</h1>
2
2
 
3
3
  <p align="center">
4
4
  <strong>AI Engineering Runtime for Professional Developers</strong>
@@ -26,7 +26,7 @@
26
26
  It is a runtime for production codebases:
27
27
  - a terminal-native coding agent with direct filesystem and shell tooling
28
28
  - primary operating profiles: **full** (default) and **iosm** (advanced, methodology-driven engineering cycles)
29
- - smart orchestration for complex tasks: parallel/sequential agents, dependency ordering, lock coordination, and worktree isolation
29
+ - swarm-first orchestration for complex tasks: `Scopes -> Touches -> Locks -> Gates -> Done`, continuous dispatch, retries, checkpoints
30
30
  - built-in semantic embeddings search (`semantic_search` tool + `/semantic` + `iosm semantic`)
31
31
  - repeatable codebase improvement workflows via **IOSM** (Improve -> Optimize -> Shrink -> Modularize)
32
32
  - auditable artifact history for cycles, decisions, and metric evolution across runs
@@ -131,30 +131,28 @@ Shift+Tab # switch profile to iosm
131
131
  ```
132
132
 
133
133
  Core commands to unlock full runtime value:
134
- - `/orchestrate` run parallel/sequential subagents with dependencies, locks, and optional worktrees
134
+ - direct prompt to main agent default for simple tasks (single-agent flow)
135
+ - `/orchestrate` — manual legacy multi-agent orchestration (explicit team-run control)
136
+ - `/swarm` — recommended multi-agent orchestration runtime for complex/risky changes (`run`, `from-singular`, `watch`, `retry`, `resume`)
135
137
  - `/init` + `/iosm` — execute measurable IOSM cycles with artifacts and quality gates
136
138
  - `/mcp` — connect external tool ecosystems in interactive UI
137
139
  - `/semantic` — configure semantic provider, build/rebuild embeddings index, run meaning-based retrieval
138
140
  - `/memory` — persist project facts and constraints across sessions
139
141
 
140
- ## Real-World Example: Agent-Orchestrated IOSM Refactor
142
+ ## Real-World Example: Swarm-First IOSM Refactor
141
143
 
142
144
  ```console
143
145
  $ iosm
144
- IOSM CLI v0.2.0 [full]
146
+ IOSM CLI v0.2.1 [full]
145
147
 
146
- you> Refactor authentication module with parallel agents, then finalize in IOSM mode
147
- iosm> /orchestrate --parallel --agents 4 \
148
- --profiles iosm_analyst,explore,iosm_verifier,full \
149
- --depends 3>1,4>2 --locks schema,config --worktree \
150
- Refactor auth and reduce integration risk
151
- iosm> Team run started: #77
152
-
153
- iosm> agent[1] architecture map complete
154
- iosm> agent[2] implementation patch set prepared
155
- iosm> agent[3] verification suite and rollback checks ready
156
- iosm> agent[4] integration validation passed
157
- iosm> Consolidated patch plan generated
148
+ you> /singular Refactor auth and split session handling from token validation
149
+ iosm> Option 1 selected
150
+ iosm> Start with Swarm (Recommended)
151
+ iosm> /swarm from-singular 2026-03-10-210201 --option 1
152
+ iosm> Swarm run started: swarm_1741632000000_ab12cd
153
+ iosm> status: running (ready/running/blocked/done visible via /swarm watch)
154
+ iosm> Touches -> Locks -> Gates pipeline completed
155
+ iosm> integration report written to .iosm/orchestrate/swarm_1741632000000_ab12cd/reports/
158
156
 
159
157
  iosm> switch profile: iosm (Shift+Tab)
160
158
  iosm> /init
@@ -168,13 +166,10 @@ iosm> Result: simplicity +18%, modularity +11%, performance +6%
168
166
  iosm> Artifacts written to .iosm/cycles/2026-03-10-001/
169
167
  ```
170
168
 
171
- For broader tasks, delegate in parallel:
169
+ For plain-language execution without `/singular`:
172
170
 
173
171
  ```bash
174
- /orchestrate --parallel --agents 4 \
175
- --profiles iosm_analyst,explore,iosm_verifier,full \
176
- --depends 3>1,4>2 --locks schema,config --worktree \
177
- Refactor auth and reduce integration risk
172
+ /swarm run "Refactor auth and reduce integration risk" --max-parallel 3 --budget-usd 12
178
173
  ```
179
174
 
180
175
  ## Architecture Overview
@@ -190,7 +185,7 @@ Agent Runtime (interactive + JSON + JSON-RPC + SDK)
190
185
 
191
186
  Tooling Layer (read/edit/bash + search/structural/data/security tools + MCP tools)
192
187
 
193
- Orchestration Engine (/orchestrate, subagents, dependencies, locks, worktrees)
188
+ Swarm Runtime (/swarm run|from-singular|watch|retry|resume)
194
189
 
195
190
  IOSM Layer (/init, /iosm cycles, metrics, governance)
196
191
 
@@ -199,8 +194,8 @@ Artifacts + Memory (.iosm/cycles/*, checkpoints, /memory state)
199
194
 
200
195
  ## Design Principles
201
196
 
202
- - **AI executes structured engineering loops, not ad hoc chats.** Core flow is orchestration + IOSM cycle execution (`/orchestrate` -> `/init` -> `/iosm`).
203
- - **Complex work needs orchestration.** Parallel agents, dependency ordering, locks, and optional worktree isolation reduce collision and blast radius.
197
+ - **AI executes structured engineering loops, not ad hoc chats.** Core flow for risky tasks is ` /singular -> /contract -> /swarm -> /iosm `.
198
+ - **Complex work needs controlled execution.** Swarm applies `Scopes -> Touches -> Locks -> Gates -> Done` with continuous dispatch and bounded retries.
204
199
  - **Refactoring must be measurable.** IOSM cycles capture baseline, hypotheses, and metric deltas instead of untracked edits.
205
200
  - **Every important run must be auditable.** Artifacts and memory preserve decisions and outcomes across sessions.
206
201
  - **Adoption should be progressive.** Start in `full` profile for speed; move to `iosm` profile for advanced cycles and governance when needed.
@@ -211,7 +206,7 @@ Artifacts + Memory (.iosm/cycles/*, checkpoints, /memory state)
211
206
 
212
207
  | Profile | Best For | What `/init` Does | Advanced Command |
213
208
  |------|----------|-------------------|------------------|
214
- | **full** (default) | Daily coding for any level | Generates/updates `AGENTS.md` from real repo scan and prepares `.iosm/agents/` | Use `/orchestrate` and built-in tools directly |
209
+ | **full** (default) | Daily coding for any level | Generates/updates `AGENTS.md` from real repo scan and prepares `.iosm/agents/` | Use `/swarm` (canonical) and built-in tools directly |
215
210
  | **iosm** (advanced) | High-risk refactors and system-level engineering loops | Bootstraps full IOSM workspace (`iosm.yaml`, `IOSM.md`, `.iosm/cycles/...`) with optional agent verification | `/iosm [target-index] [--max-iterations N] [--force-init]` |
216
211
 
217
212
  Typical advanced flow:
@@ -222,30 +217,43 @@ iosm --profile iosm
222
217
  /iosm 0.95 --max-iterations 5
223
218
  ```
224
219
 
225
- ## Smart Orchestration
226
-
227
- For complex work, use explicit multi-agent orchestration instead of one long monolithic prompt.
228
-
229
- `/orchestrate` supports:
230
- - parallel or sequential execution (`--parallel` / `--sequential`)
231
- - controlled concurrency (`--max-parallel`)
232
- - per-agent profiles and working directories (`--profiles`, `--cwd`)
233
- - dependency DAGs (`--depends 2>1,3>2`)
234
- - write safety (`--locks`) and optional git worktree isolation (`--worktree`)
220
+ ## Swarm-First Execution
221
+
222
+ For complex/risky work, use the canonical swarm runtime instead of one monolithic prompt.
223
+
224
+ Default routing rule:
225
+ - simple tasks -> direct prompt to one agent
226
+ - manual legacy multi-agent split -> `/orchestrate`
227
+ - complex/risky changes (multi-agent orchestration level) -> `/swarm`
228
+
229
+ `/swarm` supports:
230
+ - contract-bound execution (run blocks until effective `/contract` exists)
231
+ - run-level parallel workers via `--max-parallel` (1..20)
232
+ - continuous dispatch over DAG tasks (ready -> locks -> gates -> checkpoint)
233
+ - intra-task parallelism: one swarm task can fan out to delegated subagents (up to 10) when beneficial
234
+ - run-scoped shared memory (`shared_memory_write` / `shared_memory_read`) across tasks and delegates that share the same `run_id`
235
+ - standalone `task` executions auto-generate internal `run_id/task_id`, enabling shared memory for root + delegates without manual IDs
236
+ - hierarchical touches-based locking and lock downgrade
237
+ - task gates + run gates separation
238
+ - retries by taxonomy (`permission`, `dependency/import`, `test`, `timeout`, `unknown`)
239
+ - checkpoints/recovery (`/swarm resume`) and focused retries (`/swarm retry`)
240
+ - scheduler guards (`progress heuristic` + `conflict density guard`) for stable throughput under contention
241
+ - high-risk spawn candidates require explicit confirmation during run
235
242
 
236
243
  Example:
237
244
 
238
245
  ```bash
239
- /orchestrate --parallel --agents 4 \
240
- --profiles iosm_analyst,explore,iosm_verifier,full \
241
- --max-parallel 2 \
242
- --depends 3>1,4>2 \
243
- --locks schema,config \
244
- --worktree \
245
- Improve auth reliability and performance with verification gates
246
+ /swarm run "Improve auth reliability and performance with verification gates" \
247
+ --max-parallel 3 \
248
+ --budget-usd 15
246
249
  ```
247
250
 
248
- Track and resume delegated execution with `/subagent-runs`, `/subagent-resume`, `/team-runs`, and `/team-status`.
251
+ Bridge from decision mode:
252
+
253
+ ```bash
254
+ /singular "Refactor auth and split session handling from token validation"
255
+ # choose option -> Start with Swarm (Recommended)
256
+ ```
249
257
 
250
258
  ## Core Commands
251
259
 
@@ -254,10 +262,12 @@ Track and resume delegated execution with `/subagent-runs`, `/subagent-resume`,
254
262
  | Start clean context | `/new` or `/clear` | Reset session state before a new task or after context drift |
255
263
  | Configure auth | `/login` or `/auth` | Set provider credentials with guided flow |
256
264
  | Select active model | `/model` | Choose provider/model category for current workload |
257
- | Launch multi-agent execution | `/orchestrate ...` | Split complex tasks across agents with dependencies, locks, and optional worktrees |
265
+ | Launch controlled execution | `/swarm run ...` | Execute complex tasks with contract boundaries, locks, gates, retries, and checkpoints |
266
+ | Bridge decision to execution | `/swarm from-singular ...` | Apply selected `/singular` option under effective contract policy |
267
+ | Legacy orchestration | `/orchestrate --parallel ...` | Keep previous team-run flow when you explicitly need legacy semantics |
258
268
  | Initialize IOSM workspace | `/init` | Bootstrap/update IOSM files and cycle workspace |
259
269
  | Run IOSM cycle | `/iosm [target-index] [--max-iterations N]` | Execute measurable improve/verify loops with artifact output |
260
- | Track delegated runs | `/subagent-runs`, `/subagent-resume`, `/team-runs`, `/team-status` | Monitor and resume orchestration pipelines |
270
+ | Track swarm runs | `/swarm watch`, `/swarm resume`, `/swarm retry` | Observe state, resume checkpoints, and recover failed tasks |
261
271
  | Manage MCP servers | `/mcp` | Inspect/add/enable external tool servers interactively |
262
272
  | Manage semantic search | `/semantic` | Configure provider with auto model discovery (OpenRouter/Ollama), index codebase, query by intent/meaning |
263
273
  | Define engineering contract | `/contract` | Field-by-field interactive contract editor with auto-save and automatic JSON generation |
@@ -290,7 +300,8 @@ Key manager actions:
290
300
  - `Option 2`: alternative strategy with different trade-offs.
291
301
  - `Option 3`: defer/do-not-implement-now path.
292
302
  - Each option includes affected files, step-by-step plan, risks, and when-to-choose guidance.
293
- - User selects `1/2/3` (or exits) before coding starts.
303
+ - User selects `1/2/3`, then chooses `Start with Swarm` or `Continue without Swarm`.
304
+ - `Start with Swarm` executes selected option via `/swarm from-singular ...` under effective `/contract`.
294
305
 
295
306
  Legacy note:
296
307
  - `/blast` and `/shadow` are removed from active workflow.
@@ -1 +1 @@
1
- {"version":3,"file":"agent-teams.d.ts","sourceRoot":"","sources":["../../src/core/agent-teams.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,CAAC;AAEpF,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,GAAG,YAAY,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,cAAc,EAAE,CAAC;CACxB;AAUD,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,GAAG,YAAY,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC5F,GAAG,aAAa,CA2BhB;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAQhF;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,aAAa,EAAE,CAkBrE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,cAAc,CAAC;CACvB,GAAG,aAAa,GAAG,SAAS,CAsB5B"}
1
+ {"version":3,"file":"agent-teams.d.ts","sourceRoot":"","sources":["../../src/core/agent-teams.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,CAAC;AAEpF,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,GAAG,YAAY,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,cAAc,EAAE,CAAC;CACxB;AAeD,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,GAAG,YAAY,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC5F,GAAG,aAAa,CA2BhB;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAQhF;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,aAAa,EAAE,CAkBrE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,cAAc,CAAC;CACvB,GAAG,aAAa,GAAG,SAAS,CAwC5B"}
@@ -1,11 +1,16 @@
1
1
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
+ import lockfile from "proper-lockfile";
3
4
  function getTeamsDir(cwd) {
4
5
  return join(cwd, ".iosm", "subagents", "teams");
5
6
  }
6
7
  function getTeamRunPath(cwd, runId) {
7
8
  return join(getTeamsDir(cwd), `${runId}.json`);
8
9
  }
10
+ function sleepSync(ms) {
11
+ const waiter = new Int32Array(new SharedArrayBuffer(4));
12
+ Atomics.wait(waiter, 0, 0, ms);
13
+ }
9
14
  export function createTeamRun(input) {
10
15
  const runId = `team_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
11
16
  const tasks = input.assignments.map((assignment, index) => {
@@ -67,24 +72,46 @@ export function listTeamRuns(cwd, limit = 20) {
67
72
  return runs;
68
73
  }
69
74
  export function updateTeamTaskStatus(input) {
70
- const existing = getTeamRun(input.cwd, input.runId);
71
- if (!existing)
72
- return undefined;
73
- const nextTasks = existing.tasks.map((task) => task.id === input.taskId ? { ...task, status: input.status } : task);
74
- if (!nextTasks.some((task) => task.id === input.taskId)) {
75
+ const runPath = getTeamRunPath(input.cwd, input.runId);
76
+ if (!existsSync(runPath))
75
77
  return undefined;
76
- }
77
- const next = {
78
- ...existing,
79
- tasks: nextTasks,
80
- };
78
+ let release;
81
79
  try {
82
80
  mkdirSync(getTeamsDir(input.cwd), { recursive: true });
83
- writeFileSync(getTeamRunPath(input.cwd, input.runId), JSON.stringify(next, null, 2), "utf8");
81
+ const maxLockAttempts = 12;
82
+ for (let attempt = 1; attempt <= maxLockAttempts; attempt += 1) {
83
+ try {
84
+ release = lockfile.lockSync(runPath, { realpath: false });
85
+ break;
86
+ }
87
+ catch (error) {
88
+ const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
89
+ if (code !== "ELOCKED" || attempt === maxLockAttempts) {
90
+ return undefined;
91
+ }
92
+ sleepSync(Math.min(120, 10 + attempt * 10));
93
+ }
94
+ }
95
+ if (!release)
96
+ return undefined;
97
+ const raw = readFileSync(runPath, "utf8");
98
+ const existing = JSON.parse(raw);
99
+ const nextTasks = existing.tasks.map((task) => task.id === input.taskId ? { ...task, status: input.status } : task);
100
+ if (!nextTasks.some((task) => task.id === input.taskId)) {
101
+ return undefined;
102
+ }
103
+ const next = {
104
+ ...existing,
105
+ tasks: nextTasks,
106
+ };
107
+ writeFileSync(runPath, JSON.stringify(next, null, 2), "utf8");
84
108
  return next;
85
109
  }
86
110
  catch {
87
111
  return undefined;
88
112
  }
113
+ finally {
114
+ release?.();
115
+ }
89
116
  }
90
117
  //# sourceMappingURL=agent-teams.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-teams.js","sourceRoot":"","sources":["../../src/core/agent-teams.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type TeamTaskStatus = \"pending\" | \"running\" | \"done\" | \"error\" | \"cancelled\";\n\nexport interface TeamTaskRecord {\n\tid: string;\n\tagentIndex: number;\n\tprofile: string;\n\tcwd: string;\n\tlockKey?: string;\n\tdependsOn: string[];\n\tstatus: TeamTaskStatus;\n}\n\nexport interface TeamRunRecord {\n\trunId: string;\n\tcreatedAt: string;\n\tmode: \"parallel\" | \"sequential\";\n\tagents: number;\n\tmaxParallel?: number;\n\ttask: string;\n\ttasks: TeamTaskRecord[];\n}\n\nfunction getTeamsDir(cwd: string): string {\n\treturn join(cwd, \".iosm\", \"subagents\", \"teams\");\n}\n\nfunction getTeamRunPath(cwd: string, runId: string): string {\n\treturn join(getTeamsDir(cwd), `${runId}.json`);\n}\n\nexport function createTeamRun(input: {\n\tcwd: string;\n\tmode: \"parallel\" | \"sequential\";\n\tagents: number;\n\tmaxParallel?: number;\n\ttask: string;\n\tassignments: Array<{ profile: string; cwd: string; lockKey?: string; dependsOn: number[] }>;\n}): TeamRunRecord {\n\tconst runId = `team_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;\n\tconst tasks: TeamTaskRecord[] = input.assignments.map((assignment, index) => {\n\t\tconst id = `task_${index + 1}`;\n\t\tconst dependsOn = assignment.dependsOn.map((dep) => `task_${dep}`);\n\t\treturn {\n\t\t\tid,\n\t\t\tagentIndex: index + 1,\n\t\t\tprofile: assignment.profile,\n\t\t\tcwd: assignment.cwd,\n\t\t\tlockKey: assignment.lockKey,\n\t\t\tdependsOn,\n\t\t\tstatus: \"pending\",\n\t\t};\n\t});\n\tconst record: TeamRunRecord = {\n\t\trunId,\n\t\tcreatedAt: new Date().toISOString(),\n\t\tmode: input.mode,\n\t\tagents: input.agents,\n\t\tmaxParallel: input.maxParallel,\n\t\ttask: input.task,\n\t\ttasks,\n\t};\n\tmkdirSync(getTeamsDir(input.cwd), { recursive: true });\n\twriteFileSync(getTeamRunPath(input.cwd, runId), JSON.stringify(record, null, 2), \"utf8\");\n\treturn record;\n}\n\nexport function getTeamRun(cwd: string, runId: string): TeamRunRecord | undefined {\n\tconst path = getTeamRunPath(cwd, runId);\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\treturn JSON.parse(readFileSync(path, \"utf8\")) as TeamRunRecord;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function listTeamRuns(cwd: string, limit = 20): TeamRunRecord[] {\n\tconst dir = getTeamsDir(cwd);\n\tif (!existsSync(dir)) return [];\n\tconst names = readdirSync(dir)\n\t\t.filter((name) => name.toLowerCase().endsWith(\".json\"))\n\t\t.sort()\n\t\t.reverse()\n\t\t.slice(0, Math.max(1, limit));\n\tconst runs: TeamRunRecord[] = [];\n\tfor (const name of names) {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(readFileSync(join(dir, name), \"utf8\")) as TeamRunRecord;\n\t\t\truns.push(parsed);\n\t\t} catch {\n\t\t\t// ignore malformed files\n\t\t}\n\t}\n\treturn runs;\n}\n\nexport function updateTeamTaskStatus(input: {\n\tcwd: string;\n\trunId: string;\n\ttaskId: string;\n\tstatus: TeamTaskStatus;\n}): TeamRunRecord | undefined {\n\tconst existing = getTeamRun(input.cwd, input.runId);\n\tif (!existing) return undefined;\n\n\tconst nextTasks = existing.tasks.map((task) =>\n\t\ttask.id === input.taskId ? { ...task, status: input.status } : task,\n\t);\n\tif (!nextTasks.some((task) => task.id === input.taskId)) {\n\t\treturn undefined;\n\t}\n\n\tconst next: TeamRunRecord = {\n\t\t...existing,\n\t\ttasks: nextTasks,\n\t};\n\ttry {\n\t\tmkdirSync(getTeamsDir(input.cwd), { recursive: true });\n\t\twriteFileSync(getTeamRunPath(input.cwd, input.runId), JSON.stringify(next, null, 2), \"utf8\");\n\t\treturn next;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}
1
+ {"version":3,"file":"agent-teams.js","sourceRoot":"","sources":["../../src/core/agent-teams.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,QAAQ,MAAM,iBAAiB,CAAC;AAwBvC,SAAS,WAAW,CAAC,GAAW;IAC/B,OAAO,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,cAAc,CAAC,GAAW,EAAE,KAAa;IACjD,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,SAAS,CAAC,EAAU;IAC5B,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAO7B;IACA,MAAM,KAAK,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IAC9E,MAAM,KAAK,GAAqB,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE;QAC3E,MAAM,EAAE,GAAG,QAAQ,KAAK,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC;QACnE,OAAO;YACN,EAAE;YACF,UAAU,EAAE,KAAK,GAAG,CAAC;YACrB,OAAO,EAAE,UAAU,CAAC,OAAO;YAC3B,GAAG,EAAE,UAAU,CAAC,GAAG;YACnB,OAAO,EAAE,UAAU,CAAC,OAAO;YAC3B,SAAS;YACT,MAAM,EAAE,SAAS;SACjB,CAAC;IACH,CAAC,CAAC,CAAC;IACH,MAAM,MAAM,GAAkB;QAC7B,KAAK;QACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK;KACL,CAAC;IACF,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,aAAa,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACzF,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,KAAa;IACpD,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAkB,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,KAAK,GAAG,EAAE;IACnD,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC;SAC5B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;SACtD,IAAI,EAAE;SACN,OAAO,EAAE;SACT,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAoB,EAAE,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAkB,CAAC;YAClF,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACR,yBAAyB;QAC1B,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAKpC;IACA,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACvD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3C,IAAI,OAAiC,CAAC;IACtC,IAAI,CAAC;QACJ,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,eAAe,GAAG,EAAE,CAAC;QAC3B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,eAAe,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;YAChE,IAAI,CAAC;gBACJ,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC1D,MAAM;YACP,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,MAAM,IAAI,GAAG,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7F,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,KAAK,eAAe,EAAE,CAAC;oBACvD,OAAO,SAAS,CAAC;gBAClB,CAAC;gBACD,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC;YAC7C,CAAC;QACF,CAAC;QACD,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QAC/B,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAC;QAClD,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC7C,IAAI,CAAC,EAAE,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CACnE,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACzD,OAAO,SAAS,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,GAAkB;YAC3B,GAAG,QAAQ;YACX,KAAK,EAAE,SAAS;SAChB,CAAC;QACF,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;YAAS,CAAC;QACV,OAAO,EAAE,EAAE,CAAC;IACb,CAAC;AACF,CAAC","sourcesContent":["import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\n\nexport type TeamTaskStatus = \"pending\" | \"running\" | \"done\" | \"error\" | \"cancelled\";\n\nexport interface TeamTaskRecord {\n\tid: string;\n\tagentIndex: number;\n\tprofile: string;\n\tcwd: string;\n\tlockKey?: string;\n\tdependsOn: string[];\n\tstatus: TeamTaskStatus;\n}\n\nexport interface TeamRunRecord {\n\trunId: string;\n\tcreatedAt: string;\n\tmode: \"parallel\" | \"sequential\";\n\tagents: number;\n\tmaxParallel?: number;\n\ttask: string;\n\ttasks: TeamTaskRecord[];\n}\n\nfunction getTeamsDir(cwd: string): string {\n\treturn join(cwd, \".iosm\", \"subagents\", \"teams\");\n}\n\nfunction getTeamRunPath(cwd: string, runId: string): string {\n\treturn join(getTeamsDir(cwd), `${runId}.json`);\n}\n\nfunction sleepSync(ms: number): void {\n\tconst waiter = new Int32Array(new SharedArrayBuffer(4));\n\tAtomics.wait(waiter, 0, 0, ms);\n}\n\nexport function createTeamRun(input: {\n\tcwd: string;\n\tmode: \"parallel\" | \"sequential\";\n\tagents: number;\n\tmaxParallel?: number;\n\ttask: string;\n\tassignments: Array<{ profile: string; cwd: string; lockKey?: string; dependsOn: number[] }>;\n}): TeamRunRecord {\n\tconst runId = `team_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;\n\tconst tasks: TeamTaskRecord[] = input.assignments.map((assignment, index) => {\n\t\tconst id = `task_${index + 1}`;\n\t\tconst dependsOn = assignment.dependsOn.map((dep) => `task_${dep}`);\n\t\treturn {\n\t\t\tid,\n\t\t\tagentIndex: index + 1,\n\t\t\tprofile: assignment.profile,\n\t\t\tcwd: assignment.cwd,\n\t\t\tlockKey: assignment.lockKey,\n\t\t\tdependsOn,\n\t\t\tstatus: \"pending\",\n\t\t};\n\t});\n\tconst record: TeamRunRecord = {\n\t\trunId,\n\t\tcreatedAt: new Date().toISOString(),\n\t\tmode: input.mode,\n\t\tagents: input.agents,\n\t\tmaxParallel: input.maxParallel,\n\t\ttask: input.task,\n\t\ttasks,\n\t};\n\tmkdirSync(getTeamsDir(input.cwd), { recursive: true });\n\twriteFileSync(getTeamRunPath(input.cwd, runId), JSON.stringify(record, null, 2), \"utf8\");\n\treturn record;\n}\n\nexport function getTeamRun(cwd: string, runId: string): TeamRunRecord | undefined {\n\tconst path = getTeamRunPath(cwd, runId);\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\treturn JSON.parse(readFileSync(path, \"utf8\")) as TeamRunRecord;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function listTeamRuns(cwd: string, limit = 20): TeamRunRecord[] {\n\tconst dir = getTeamsDir(cwd);\n\tif (!existsSync(dir)) return [];\n\tconst names = readdirSync(dir)\n\t\t.filter((name) => name.toLowerCase().endsWith(\".json\"))\n\t\t.sort()\n\t\t.reverse()\n\t\t.slice(0, Math.max(1, limit));\n\tconst runs: TeamRunRecord[] = [];\n\tfor (const name of names) {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(readFileSync(join(dir, name), \"utf8\")) as TeamRunRecord;\n\t\t\truns.push(parsed);\n\t\t} catch {\n\t\t\t// ignore malformed files\n\t\t}\n\t}\n\treturn runs;\n}\n\nexport function updateTeamTaskStatus(input: {\n\tcwd: string;\n\trunId: string;\n\ttaskId: string;\n\tstatus: TeamTaskStatus;\n}): TeamRunRecord | undefined {\n\tconst runPath = getTeamRunPath(input.cwd, input.runId);\n\tif (!existsSync(runPath)) return undefined;\n\tlet release: (() => void) | undefined;\n\ttry {\n\t\tmkdirSync(getTeamsDir(input.cwd), { recursive: true });\n\t\tconst maxLockAttempts = 12;\n\t\tfor (let attempt = 1; attempt <= maxLockAttempts; attempt += 1) {\n\t\t\ttry {\n\t\t\t\trelease = lockfile.lockSync(runPath, { realpath: false });\n\t\t\t\tbreak;\n\t\t\t} catch (error) {\n\t\t\t\tconst code = error && typeof error === \"object\" && \"code\" in error ? String(error.code) : \"\";\n\t\t\t\tif (code !== \"ELOCKED\" || attempt === maxLockAttempts) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tsleepSync(Math.min(120, 10 + attempt * 10));\n\t\t\t}\n\t\t}\n\t\tif (!release) return undefined;\n\t\tconst raw = readFileSync(runPath, \"utf8\");\n\t\tconst existing = JSON.parse(raw) as TeamRunRecord;\n\t\tconst nextTasks = existing.tasks.map((task) =>\n\t\t\ttask.id === input.taskId ? { ...task, status: input.status } : task,\n\t\t);\n\t\tif (!nextTasks.some((task) => task.id === input.taskId)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst next: TeamRunRecord = {\n\t\t\t...existing,\n\t\t\ttasks: nextTasks,\n\t\t};\n\t\twriteFileSync(runPath, JSON.stringify(next, null, 2), \"utf8\");\n\t\treturn next;\n\t} catch {\n\t\treturn undefined;\n\t} finally {\n\t\trelease?.();\n\t}\n}\n"]}
@@ -0,0 +1,12 @@
1
+ export type FailureCause = "token_limit" | "logic_error" | "aborted" | "timeout" | "dependency_env" | "empty_output" | "unknown";
2
+ export declare function classifyFailureCause(errorMessage: string): FailureCause;
3
+ export declare function isRetrospectiveRetryable(cause: FailureCause): boolean;
4
+ export declare function buildRetrospectiveDirective(input: {
5
+ cause: FailureCause;
6
+ errorMessage: string;
7
+ attempt: number;
8
+ target: "root" | "delegate";
9
+ }): string;
10
+ export declare function formatFailureCauseCounts(counts: Partial<Record<FailureCause, number>>): string;
11
+ export declare function dominantFailureCause(counts: Partial<Record<FailureCause, number>>): FailureCause | undefined;
12
+ //# sourceMappingURL=failure-retrospective.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failure-retrospective.d.ts","sourceRoot":"","sources":["../../src/core/failure-retrospective.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GACrB,aAAa,GACb,aAAa,GACb,SAAS,GACT,SAAS,GACT,gBAAgB,GAChB,cAAc,GACd,SAAS,CAAC;AAYb,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,YAAY,CAUvE;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAErE;AAgDD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE;IAClD,KAAK,EAAE,YAAY,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC;CAC5B,GAAG,MAAM,CAYT;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAe9F;AAED,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,GAC3C,YAAY,GAAG,SAAS,CAY1B"}
@@ -0,0 +1,115 @@
1
+ const tokenLimitPattern = /(token limit|max(?:imum)? tokens?|too many tokens?|context length|context window|prompt is too long|input too long|length exceeded)/i;
2
+ const logicPattern = /(logic|invariant|assert(?:ion)?|expect\(|failed assumption|incorrect result|wrong output|invalid state|regression|failed dependency)/i;
3
+ const abortPattern = /(operation aborted|aborted|signal aborted)/i;
4
+ const timeoutPattern = /(timeout|timed out|deadline exceeded|took too long|hang(?:ing)?)/i;
5
+ const dependencyPattern = /(module not found|cannot find module|dependency|package|importerror|missing dependency|command not found|enoent|env(?:ironment)?)/i;
6
+ const emptyOutputPattern = /(empty output|no output|returned empty)/i;
7
+ export function classifyFailureCause(errorMessage) {
8
+ const message = errorMessage.trim();
9
+ if (!message)
10
+ return "unknown";
11
+ if (emptyOutputPattern.test(message))
12
+ return "empty_output";
13
+ if (tokenLimitPattern.test(message))
14
+ return "token_limit";
15
+ if (abortPattern.test(message))
16
+ return "aborted";
17
+ if (timeoutPattern.test(message))
18
+ return "timeout";
19
+ if (dependencyPattern.test(message))
20
+ return "dependency_env";
21
+ if (logicPattern.test(message))
22
+ return "logic_error";
23
+ return "unknown";
24
+ }
25
+ export function isRetrospectiveRetryable(cause) {
26
+ return cause !== "empty_output" && cause !== "aborted";
27
+ }
28
+ function guidanceForCause(cause) {
29
+ switch (cause) {
30
+ case "token_limit":
31
+ return [
32
+ "- Narrow scope to only the minimum files/commands needed.",
33
+ "- Produce concise output (bullet points + critical diffs only).",
34
+ "- Avoid broad scans and repeated large reads.",
35
+ ];
36
+ case "logic_error":
37
+ return [
38
+ "- Diagnose why the prior approach failed before changing code.",
39
+ "- Use an alternative strategy, not a repeat of the same path.",
40
+ "- Prefer smallest verifiable step and validate assumptions explicitly.",
41
+ ];
42
+ case "aborted":
43
+ return [
44
+ "- Stop retries for this task execution; cancellation came from an external signal.",
45
+ "- Report cancellation context (where it happened and what was in progress).",
46
+ "- Resume only via an explicit new task/run request.",
47
+ ];
48
+ case "timeout":
49
+ return [
50
+ "- Split work into smaller bounded steps.",
51
+ "- Reduce expensive commands and long-running checks.",
52
+ "- Prioritize fast targeted verification first.",
53
+ ];
54
+ case "dependency_env":
55
+ return [
56
+ "- Verify environment/dependency preconditions first.",
57
+ "- Prefer deterministic remediation steps and minimal commands.",
58
+ "- If blocked by environment, report exact missing prerequisite.",
59
+ ];
60
+ case "empty_output":
61
+ return [
62
+ "- Ensure the response includes a concrete result summary.",
63
+ "- If still impossible, return a clear blocked reason.",
64
+ ];
65
+ default:
66
+ return [
67
+ "- Re-evaluate assumptions and reduce scope.",
68
+ "- Try a different implementation approach.",
69
+ "- Produce a concise, verifiable outcome.",
70
+ ];
71
+ }
72
+ }
73
+ export function buildRetrospectiveDirective(input) {
74
+ const guidance = guidanceForCause(input.cause).join("\n");
75
+ return [
76
+ "[RETROSPECTIVE_RETRY]",
77
+ `target: ${input.target}`,
78
+ `attempt: ${input.attempt}`,
79
+ `cause: ${input.cause}`,
80
+ `previous_error: ${input.errorMessage.replace(/\s+/g, " ").trim()}`,
81
+ "retry_policy:",
82
+ guidance,
83
+ "[/RETROSPECTIVE_RETRY]",
84
+ ].join("\n");
85
+ }
86
+ export function formatFailureCauseCounts(counts) {
87
+ const ordered = [
88
+ "token_limit",
89
+ "logic_error",
90
+ "aborted",
91
+ "timeout",
92
+ "dependency_env",
93
+ "empty_output",
94
+ "unknown",
95
+ ];
96
+ const parts = ordered
97
+ .map((cause) => ({ cause, count: counts[cause] ?? 0 }))
98
+ .filter((item) => item.count > 0)
99
+ .map((item) => `${item.cause}=${item.count}`);
100
+ return parts.join(", ");
101
+ }
102
+ export function dominantFailureCause(counts) {
103
+ const entries = Object.entries(counts);
104
+ let best;
105
+ let bestCount = 0;
106
+ for (const [cause, count] of entries) {
107
+ const normalized = count ?? 0;
108
+ if (normalized > bestCount) {
109
+ best = cause;
110
+ bestCount = normalized;
111
+ }
112
+ }
113
+ return best;
114
+ }
115
+ //# sourceMappingURL=failure-retrospective.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failure-retrospective.js","sourceRoot":"","sources":["../../src/core/failure-retrospective.ts"],"names":[],"mappings":"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","sourcesContent":["export type FailureCause =\n\t| \"token_limit\"\n\t| \"logic_error\"\n\t| \"aborted\"\n\t| \"timeout\"\n\t| \"dependency_env\"\n\t| \"empty_output\"\n\t| \"unknown\";\n\nconst tokenLimitPattern =\n\t/(token limit|max(?:imum)? tokens?|too many tokens?|context length|context window|prompt is too long|input too long|length exceeded)/i;\nconst logicPattern =\n\t/(logic|invariant|assert(?:ion)?|expect\\(|failed assumption|incorrect result|wrong output|invalid state|regression|failed dependency)/i;\nconst abortPattern = /(operation aborted|aborted|signal aborted)/i;\nconst timeoutPattern = /(timeout|timed out|deadline exceeded|took too long|hang(?:ing)?)/i;\nconst dependencyPattern =\n\t/(module not found|cannot find module|dependency|package|importerror|missing dependency|command not found|enoent|env(?:ironment)?)/i;\nconst emptyOutputPattern = /(empty output|no output|returned empty)/i;\n\nexport function classifyFailureCause(errorMessage: string): FailureCause {\n\tconst message = errorMessage.trim();\n\tif (!message) return \"unknown\";\n\tif (emptyOutputPattern.test(message)) return \"empty_output\";\n\tif (tokenLimitPattern.test(message)) return \"token_limit\";\n\tif (abortPattern.test(message)) return \"aborted\";\n\tif (timeoutPattern.test(message)) return \"timeout\";\n\tif (dependencyPattern.test(message)) return \"dependency_env\";\n\tif (logicPattern.test(message)) return \"logic_error\";\n\treturn \"unknown\";\n}\n\nexport function isRetrospectiveRetryable(cause: FailureCause): boolean {\n\treturn cause !== \"empty_output\" && cause !== \"aborted\";\n}\n\nfunction guidanceForCause(cause: FailureCause): string[] {\n\tswitch (cause) {\n\t\tcase \"token_limit\":\n\t\t\treturn [\n\t\t\t\t\"- Narrow scope to only the minimum files/commands needed.\",\n\t\t\t\t\"- Produce concise output (bullet points + critical diffs only).\",\n\t\t\t\t\"- Avoid broad scans and repeated large reads.\",\n\t\t\t];\n\t\tcase \"logic_error\":\n\t\t\treturn [\n\t\t\t\t\"- Diagnose why the prior approach failed before changing code.\",\n\t\t\t\t\"- Use an alternative strategy, not a repeat of the same path.\",\n\t\t\t\t\"- Prefer smallest verifiable step and validate assumptions explicitly.\",\n\t\t\t];\n\t\tcase \"aborted\":\n\t\t\treturn [\n\t\t\t\t\"- Stop retries for this task execution; cancellation came from an external signal.\",\n\t\t\t\t\"- Report cancellation context (where it happened and what was in progress).\",\n\t\t\t\t\"- Resume only via an explicit new task/run request.\",\n\t\t\t];\n\t\tcase \"timeout\":\n\t\t\treturn [\n\t\t\t\t\"- Split work into smaller bounded steps.\",\n\t\t\t\t\"- Reduce expensive commands and long-running checks.\",\n\t\t\t\t\"- Prioritize fast targeted verification first.\",\n\t\t\t];\n\t\tcase \"dependency_env\":\n\t\t\treturn [\n\t\t\t\t\"- Verify environment/dependency preconditions first.\",\n\t\t\t\t\"- Prefer deterministic remediation steps and minimal commands.\",\n\t\t\t\t\"- If blocked by environment, report exact missing prerequisite.\",\n\t\t\t];\n\t\tcase \"empty_output\":\n\t\t\treturn [\n\t\t\t\t\"- Ensure the response includes a concrete result summary.\",\n\t\t\t\t\"- If still impossible, return a clear blocked reason.\",\n\t\t\t];\n\t\tdefault:\n\t\t\treturn [\n\t\t\t\t\"- Re-evaluate assumptions and reduce scope.\",\n\t\t\t\t\"- Try a different implementation approach.\",\n\t\t\t\t\"- Produce a concise, verifiable outcome.\",\n\t\t\t];\n\t}\n}\n\nexport function buildRetrospectiveDirective(input: {\n\tcause: FailureCause;\n\terrorMessage: string;\n\tattempt: number;\n\ttarget: \"root\" | \"delegate\";\n}): string {\n\tconst guidance = guidanceForCause(input.cause).join(\"\\n\");\n\treturn [\n\t\t\"[RETROSPECTIVE_RETRY]\",\n\t\t`target: ${input.target}`,\n\t\t`attempt: ${input.attempt}`,\n\t\t`cause: ${input.cause}`,\n\t\t`previous_error: ${input.errorMessage.replace(/\\s+/g, \" \").trim()}`,\n\t\t\"retry_policy:\",\n\t\tguidance,\n\t\t\"[/RETROSPECTIVE_RETRY]\",\n\t].join(\"\\n\");\n}\n\nexport function formatFailureCauseCounts(counts: Partial<Record<FailureCause, number>>): string {\n\tconst ordered: FailureCause[] = [\n\t\t\"token_limit\",\n\t\t\"logic_error\",\n\t\t\"aborted\",\n\t\t\"timeout\",\n\t\t\"dependency_env\",\n\t\t\"empty_output\",\n\t\t\"unknown\",\n\t];\n\tconst parts = ordered\n\t\t.map((cause) => ({ cause, count: counts[cause] ?? 0 }))\n\t\t.filter((item) => item.count > 0)\n\t\t.map((item) => `${item.cause}=${item.count}`);\n\treturn parts.join(\", \");\n}\n\nexport function dominantFailureCause(\n\tcounts: Partial<Record<FailureCause, number>>,\n): FailureCause | undefined {\n\tconst entries = Object.entries(counts) as Array<[FailureCause, number | undefined]>;\n\tlet best: FailureCause | undefined;\n\tlet bestCount = 0;\n\tfor (const [cause, count] of entries) {\n\t\tconst normalized = count ?? 0;\n\t\tif (normalized > bestCount) {\n\t\t\tbest = cause;\n\t\t\tbestCount = normalized;\n\t\t}\n\t}\n\treturn best;\n}\n"]}
@@ -0,0 +1,17 @@
1
+ import type { BuildProjectIndexOptions, ProjectIndex, ProjectIndexQueryResult, RepoScaleMode } from "./types.js";
2
+ export type { BuildProjectIndexOptions, ProjectIndex, ProjectIndexEntry, ProjectIndexMeta, ProjectIndexQueryResult, RepoScaleMode, } from "./types.js";
3
+ export declare function getProjectIndexPath(cwd: string): string;
4
+ export declare function loadProjectIndex(cwd: string): ProjectIndex | undefined;
5
+ export declare function saveProjectIndex(cwd: string, index: ProjectIndex): void;
6
+ export declare function buildProjectIndex(cwd: string, options?: BuildProjectIndexOptions): ProjectIndex;
7
+ export declare function ensureProjectIndex(cwd: string, modeHint?: RepoScaleMode): {
8
+ index: ProjectIndex;
9
+ rebuilt: boolean;
10
+ };
11
+ export declare function queryProjectIndex(index: ProjectIndex, queryText: string, limit?: number): ProjectIndexQueryResult;
12
+ export declare function inferRepoScaleMode(input: {
13
+ totalFiles: number;
14
+ sourceFiles: number;
15
+ }): RepoScaleMode;
16
+ export declare function collectChangedFilesSince(index: ProjectIndex, cwd: string): string[];
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/project-index/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,wBAAwB,EACxB,YAAY,EAGZ,uBAAuB,EACvB,aAAa,EACb,MAAM,YAAY,CAAC;AACpB,YAAY,EACX,wBAAwB,EACxB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,uBAAuB,EACvB,aAAa,GACb,MAAM,YAAY,CAAC;AAwHpB,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAUtE;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAIvE;AA+ED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,wBAAwB,GAAG,YAAY,CA0C/F;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,GAAG;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAkBnH;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,uBAAuB,CAW7G;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,aAAa,CAEpG;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBnF"}