iosm-cli 0.1.3 → 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 (132) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +88 -46
  3. package/dist/core/agent-teams.d.ts.map +1 -1
  4. package/dist/core/agent-teams.js +38 -11
  5. package/dist/core/agent-teams.js.map +1 -1
  6. package/dist/core/blast.d.ts +62 -0
  7. package/dist/core/blast.d.ts.map +1 -0
  8. package/dist/core/blast.js +448 -0
  9. package/dist/core/blast.js.map +1 -0
  10. package/dist/core/contract.d.ts +54 -0
  11. package/dist/core/contract.d.ts.map +1 -0
  12. package/dist/core/contract.js +300 -0
  13. package/dist/core/contract.js.map +1 -0
  14. package/dist/core/failure-retrospective.d.ts +12 -0
  15. package/dist/core/failure-retrospective.d.ts.map +1 -0
  16. package/dist/core/failure-retrospective.js +115 -0
  17. package/dist/core/failure-retrospective.js.map +1 -0
  18. package/dist/core/project-index/index.d.ts +17 -0
  19. package/dist/core/project-index/index.d.ts.map +1 -0
  20. package/dist/core/project-index/index.js +323 -0
  21. package/dist/core/project-index/index.js.map +1 -0
  22. package/dist/core/project-index/types.d.ts +34 -0
  23. package/dist/core/project-index/types.d.ts.map +1 -0
  24. package/dist/core/project-index/types.js +2 -0
  25. package/dist/core/project-index/types.js.map +1 -0
  26. package/dist/core/sdk.d.ts.map +1 -1
  27. package/dist/core/sdk.js +8 -0
  28. package/dist/core/sdk.js.map +1 -1
  29. package/dist/core/semantic/config.d.ts.map +1 -1
  30. package/dist/core/semantic/config.js +5 -0
  31. package/dist/core/semantic/config.js.map +1 -1
  32. package/dist/core/semantic/index.d.ts +1 -1
  33. package/dist/core/semantic/index.d.ts.map +1 -1
  34. package/dist/core/semantic/index.js +1 -1
  35. package/dist/core/semantic/index.js.map +1 -1
  36. package/dist/core/semantic/runtime.d.ts.map +1 -1
  37. package/dist/core/semantic/runtime.js +12 -1
  38. package/dist/core/semantic/runtime.js.map +1 -1
  39. package/dist/core/semantic/types.d.ts +6 -0
  40. package/dist/core/semantic/types.d.ts.map +1 -1
  41. package/dist/core/semantic/types.js +6 -0
  42. package/dist/core/semantic/types.js.map +1 -1
  43. package/dist/core/shadow-guard.d.ts +30 -0
  44. package/dist/core/shadow-guard.d.ts.map +1 -0
  45. package/dist/core/shadow-guard.js +81 -0
  46. package/dist/core/shadow-guard.js.map +1 -0
  47. package/dist/core/shared-memory.d.ts +46 -0
  48. package/dist/core/shared-memory.d.ts.map +1 -0
  49. package/dist/core/shared-memory.js +253 -0
  50. package/dist/core/shared-memory.js.map +1 -0
  51. package/dist/core/singular.d.ts +73 -0
  52. package/dist/core/singular.d.ts.map +1 -0
  53. package/dist/core/singular.js +413 -0
  54. package/dist/core/singular.js.map +1 -0
  55. package/dist/core/slash-commands.d.ts.map +1 -1
  56. package/dist/core/slash-commands.js +14 -2
  57. package/dist/core/slash-commands.js.map +1 -1
  58. package/dist/core/subagents.js +1 -1
  59. package/dist/core/subagents.js.map +1 -1
  60. package/dist/core/swarm/gates.d.ts +9 -0
  61. package/dist/core/swarm/gates.d.ts.map +1 -0
  62. package/dist/core/swarm/gates.js +65 -0
  63. package/dist/core/swarm/gates.js.map +1 -0
  64. package/dist/core/swarm/index.d.ts +9 -0
  65. package/dist/core/swarm/index.d.ts.map +1 -0
  66. package/dist/core/swarm/index.js +9 -0
  67. package/dist/core/swarm/index.js.map +1 -0
  68. package/dist/core/swarm/locks.d.ts +21 -0
  69. package/dist/core/swarm/locks.d.ts.map +1 -0
  70. package/dist/core/swarm/locks.js +93 -0
  71. package/dist/core/swarm/locks.js.map +1 -0
  72. package/dist/core/swarm/planner.d.ts +16 -0
  73. package/dist/core/swarm/planner.d.ts.map +1 -0
  74. package/dist/core/swarm/planner.js +137 -0
  75. package/dist/core/swarm/planner.js.map +1 -0
  76. package/dist/core/swarm/retry.d.ts +16 -0
  77. package/dist/core/swarm/retry.d.ts.map +1 -0
  78. package/dist/core/swarm/retry.js +32 -0
  79. package/dist/core/swarm/retry.js.map +1 -0
  80. package/dist/core/swarm/scheduler.d.ts +48 -0
  81. package/dist/core/swarm/scheduler.d.ts.map +1 -0
  82. package/dist/core/swarm/scheduler.js +554 -0
  83. package/dist/core/swarm/scheduler.js.map +1 -0
  84. package/dist/core/swarm/spawn.d.ts +16 -0
  85. package/dist/core/swarm/spawn.d.ts.map +1 -0
  86. package/dist/core/swarm/spawn.js +42 -0
  87. package/dist/core/swarm/spawn.js.map +1 -0
  88. package/dist/core/swarm/state-store.d.ts +35 -0
  89. package/dist/core/swarm/state-store.d.ts.map +1 -0
  90. package/dist/core/swarm/state-store.js +106 -0
  91. package/dist/core/swarm/state-store.js.map +1 -0
  92. package/dist/core/swarm/types.d.ts +116 -0
  93. package/dist/core/swarm/types.d.ts.map +1 -0
  94. package/dist/core/swarm/types.js +2 -0
  95. package/dist/core/swarm/types.js.map +1 -0
  96. package/dist/core/system-prompt.d.ts.map +1 -1
  97. package/dist/core/system-prompt.js +6 -3
  98. package/dist/core/system-prompt.js.map +1 -1
  99. package/dist/core/tools/semantic-search.d.ts.map +1 -1
  100. package/dist/core/tools/semantic-search.js +1 -0
  101. package/dist/core/tools/semantic-search.js.map +1 -1
  102. package/dist/core/tools/shared-memory.d.ts +23 -0
  103. package/dist/core/tools/shared-memory.d.ts.map +1 -0
  104. package/dist/core/tools/shared-memory.js +134 -0
  105. package/dist/core/tools/shared-memory.js.map +1 -0
  106. package/dist/core/tools/task.d.ts +8 -1
  107. package/dist/core/tools/task.d.ts.map +1 -1
  108. package/dist/core/tools/task.js +664 -123
  109. package/dist/core/tools/task.js.map +1 -1
  110. package/dist/main.d.ts.map +1 -1
  111. package/dist/main.js +8 -1
  112. package/dist/main.js.map +1 -1
  113. package/dist/modes/interactive/components/custom-editor.d.ts +8 -0
  114. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  115. package/dist/modes/interactive/components/custom-editor.js +70 -1
  116. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  117. package/dist/modes/interactive/components/login-dialog.d.ts +1 -0
  118. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  119. package/dist/modes/interactive/components/login-dialog.js +27 -4
  120. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  121. package/dist/modes/interactive/components/subagent-message.d.ts.map +1 -1
  122. package/dist/modes/interactive/components/subagent-message.js +14 -0
  123. package/dist/modes/interactive/components/subagent-message.js.map +1 -1
  124. package/dist/modes/interactive/interactive-mode.d.ts +81 -0
  125. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  126. package/dist/modes/interactive/interactive-mode.js +3481 -870
  127. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  128. package/docs/cli-reference.md +29 -1
  129. package/docs/configuration.md +5 -0
  130. package/docs/interactive-mode.md +171 -2
  131. package/docs/orchestration-and-subagents.md +96 -169
  132. package/package.json +4 -3
package/CHANGELOG.md CHANGED
@@ -9,6 +9,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  _No unreleased changes._
11
11
 
12
+ ## [0.2.0] - 2026-03-11
13
+
14
+ ### Added
15
+
16
+ - **Interactive engineering contract manager (`/contract`)** — field-by-field contract editing with immediate save-on-enter and automatic JSON generation for project scope
17
+ - **Layered contract model** — explicit `project`, `session`, and `effective` contract layers with copy/delete flows and merged runtime enforcement
18
+ - **Singular feasibility mode (`/singular`)** — command-first feasibility analysis that combines repository baseline scan with a standard agent pass and returns exactly three implementation options
19
+ - **Option-driven execution handoff** — `/singular` now produces concrete file targets, step plans, trade-offs, and decision guidance before implementation starts
20
+ - **Regression coverage for large paste UX** — multiline unbracketed paste now covered by dedicated tests to ensure one submission flow and compact marker rendering
21
+
22
+ ### Changed
23
+
24
+ - **Feasibility workflow naming** — `/blast` replaced by `/singular` for feature feasibility decisions
25
+ - **Profile cleanup** — `/shadow` workflow removed to avoid duplication with plan-oriented analysis
26
+ - **Contract interaction model** — removed extra save step in field editor; entering value immediately persists to selected scope
27
+
28
+ ### Fixed
29
+
30
+ - **TUI width safety** — startup resources block now truncates long lines to terminal width, preventing render crashes on narrow terminals
31
+ - **Paste queue behavior** — large pasted multiline input is treated as a single paste event instead of fragmented queued submissions
32
+
33
+ ### Documentation
34
+
35
+ - Expanded README with dedicated decision workflow section (`/contract` vs `/singular`), command migration notes, and clearer contract layer distinctions
36
+ - Extended interactive mode docs with explicit `effective/session/project` explanations and migration guidance from removed commands
37
+ - Updated CLI reference with interactive feasibility/contract command behavior and migration notes
38
+
12
39
  ## [0.1.3] - 2026-03-10
13
40
 
14
41
  ### Added
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- <h1 align="center">IOSM CLI v0.1.3</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.1.3 [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,17 +262,51 @@ 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 |
273
+ | Define engineering contract | `/contract` | Field-by-field interactive contract editor with auto-save and automatic JSON generation |
274
+ | Analyze feasibility variants | `/singular <feature request>` | Runs baseline + standard agent pass, then returns 3 implementation options and recommendation |
263
275
  | Manage memory | `/memory` | Add/edit/remove persistent project facts and constraints |
264
276
  | Save/restore state | `/checkpoint` / `/rollback` | Safe experimentation with fast rollback |
265
277
  | Diagnose runtime | `/doctor` | Verify model/auth/MCP/resources when behavior is inconsistent |
266
278
  | Manage settings | `/settings` | Tune runtime defaults and operational preferences |
267
279
 
280
+ ## Decision Workflow: `/contract` + `/singular`
281
+
282
+ ### `/contract` (interactive contract manager)
283
+
284
+ - No manual JSON editing in terminal.
285
+ - You edit fields directly (`goal`, `scope_include`, `scope_exclude`, `constraints`, `quality_gates`, `definition_of_done`, `risks`, and additional planning fields).
286
+ - Press `Enter` on a field value and it is saved immediately.
287
+ - Contract JSON is built automatically.
288
+
289
+ Key manager actions:
290
+ - `Open effective contract` = read merged runtime contract (`project + session`).
291
+ - `Edit session contract` = temporary overlay for current session only.
292
+ - `Edit project contract` = persistent baseline in `.iosm/contract.json`.
293
+
294
+ ### `/singular <request>` (feature feasibility analyzer)
295
+
296
+ - Command-first flow: write request, run analysis, receive decision options.
297
+ - Uses standard agent-style repository run (not static form output), then merges with baseline repository scan.
298
+ - Produces exactly 3 options:
299
+ - `Option 1`: practical implementation path (usually recommended).
300
+ - `Option 2`: alternative strategy with different trade-offs.
301
+ - `Option 3`: defer/do-not-implement-now path.
302
+ - Each option includes affected files, step-by-step plan, risks, and when-to-choose guidance.
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`.
305
+
306
+ Legacy note:
307
+ - `/blast` and `/shadow` are removed from active workflow.
308
+ - Use `/singular` for feasibility decisions and `/contract` for engineering constraints.
309
+
268
310
  ## IOSM In One Line
269
311
 
270
312
  **IOSM** gives you a repeatable loop for improving codebases with explicit quality gates, metrics, and artifact history instead of one-off AI edits.
@@ -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":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAwBjC,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,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,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAEhC,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;IACF,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QACzD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAkB;QAC3B,GAAG,QAAQ;QACX,KAAK,EAAE,SAAS;KAChB,CAAC;IACF,IAAI,CAAC;QACJ,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,aAAa,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7F,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC","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,62 @@
1
+ import type { EngineeringContract } from "./contract.js";
2
+ export type BlastProfile = "quick" | "full";
3
+ export type BlastSeverity = "low" | "medium" | "high";
4
+ export interface BlastFinding {
5
+ id: string;
6
+ title: string;
7
+ severity: BlastSeverity;
8
+ category: string;
9
+ detail: string;
10
+ path?: string;
11
+ line?: number;
12
+ recommendation?: string;
13
+ }
14
+ export interface BlastRunOptions {
15
+ profile: BlastProfile;
16
+ autosave?: boolean;
17
+ contract?: EngineeringContract;
18
+ }
19
+ export interface BlastRunResult {
20
+ runId: string;
21
+ profile: BlastProfile;
22
+ startedAt: string;
23
+ completedAt: string;
24
+ durationMs: number;
25
+ scannedFiles: number;
26
+ scannedLines: number;
27
+ findings: BlastFinding[];
28
+ summary: string;
29
+ nextSteps: string[];
30
+ reportMarkdown: string;
31
+ contract: EngineeringContract;
32
+ autosaved: boolean;
33
+ reportPath?: string;
34
+ findingsPath?: string;
35
+ }
36
+ export interface BlastLastRun {
37
+ runId: string;
38
+ reportPath: string;
39
+ findingsPath: string;
40
+ metaPath?: string;
41
+ summary?: string;
42
+ profile?: BlastProfile;
43
+ completedAt?: string;
44
+ findings?: number;
45
+ }
46
+ export interface BlastServiceOptions {
47
+ cwd: string;
48
+ }
49
+ export declare class BlastService {
50
+ private readonly cwd;
51
+ constructor(options: BlastServiceOptions);
52
+ getAuditsRoot(): string;
53
+ getLastRun(): BlastLastRun | undefined;
54
+ run(options: BlastRunOptions): Promise<BlastRunResult>;
55
+ private saveRunArtifacts;
56
+ private scanRepository;
57
+ private walkFiles;
58
+ private buildSummary;
59
+ private buildNextSteps;
60
+ private buildReportMarkdown;
61
+ }
62
+ //# sourceMappingURL=blast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blast.d.ts","sourceRoot":"","sources":["../../src/core/blast.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,CAAC;AAC5C,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAkFD,MAAM,WAAW,mBAAmB;IACnC,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,qBAAa,YAAY;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;gBAEjB,OAAO,EAAE,mBAAmB;IAIxC,aAAa,IAAI,MAAM;IAIvB,UAAU,IAAI,YAAY,GAAG,SAAS;IA+ChC,GAAG,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAqD5D,OAAO,CAAC,gBAAgB;IAiCxB,OAAO,CAAC,cAAc;IAgKtB,OAAO,CAAC,SAAS;IAiCjB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,cAAc;IAoBtB,OAAO,CAAC,mBAAmB;CAoE3B"}