stagent 0.9.6 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. package/README.md +20 -44
  2. package/dist/cli.js +66 -18
  3. package/docs/.coverage-gaps.json +144 -56
  4. package/docs/.last-generated +1 -1
  5. package/docs/features/agent-intelligence.md +12 -2
  6. package/docs/features/chat.md +40 -5
  7. package/docs/features/cost-usage.md +1 -1
  8. package/docs/features/documents.md +5 -2
  9. package/docs/features/inbox-notifications.md +10 -2
  10. package/docs/features/keyboard-navigation.md +12 -3
  11. package/docs/features/provider-runtimes.md +20 -2
  12. package/docs/features/schedules.md +32 -4
  13. package/docs/features/settings.md +28 -5
  14. package/docs/features/shared-components.md +7 -3
  15. package/docs/features/tables.md +11 -2
  16. package/docs/features/tool-permissions.md +6 -2
  17. package/docs/features/workflows.md +14 -4
  18. package/docs/index.md +1 -1
  19. package/docs/journeys/developer.md +39 -2
  20. package/docs/journeys/personal-use.md +32 -8
  21. package/docs/journeys/power-user.md +45 -14
  22. package/docs/journeys/work-use.md +17 -8
  23. package/docs/manifest.json +15 -15
  24. package/docs/superpowers/plans/2026-04-07-instance-bootstrap.md +1691 -0
  25. package/docs/superpowers/plans/2026-04-08-schedule-orchestration.md +2983 -0
  26. package/docs/superpowers/plans/2026-04-11-schedule-maxturns-api-control.md +551 -0
  27. package/docs/superpowers/plans/2026-04-11-task-create-profile-validation.md +864 -0
  28. package/docs/superpowers/plans/2026-04-11-task-runtime-stagent-mcp-injection.md +739 -0
  29. package/docs/superpowers/plans/2026-04-14-chat-command-namespace-refactor.md +1390 -0
  30. package/docs/superpowers/plans/2026-04-14-chat-environment-integration.md +1561 -0
  31. package/docs/superpowers/plans/2026-04-14-chat-polish-bundle-v1.md +1219 -0
  32. package/docs/superpowers/plans/2026-04-14-chat-session-persistence-provider-closeout.md +399 -0
  33. package/docs/superpowers/specs/2026-04-08-chat-sse-resilience-hotfix-design.md +201 -0
  34. package/docs/superpowers/specs/2026-04-08-schedule-orchestration-design.md +371 -0
  35. package/docs/superpowers/specs/2026-04-08-swarm-visibility-design.md +213 -0
  36. package/next.config.mjs +1 -0
  37. package/package.json +3 -2
  38. package/src/__tests__/instrumentation-smoke.test.ts +15 -0
  39. package/src/app/analytics/page.tsx +1 -21
  40. package/src/app/api/chat/conversations/[id]/messages/route.ts +22 -1
  41. package/src/app/api/chat/conversations/[id]/skills/__tests__/activate.test.ts +141 -0
  42. package/src/app/api/chat/conversations/[id]/skills/activate/route.ts +74 -0
  43. package/src/app/api/chat/conversations/[id]/skills/deactivate/route.ts +33 -0
  44. package/src/app/api/chat/export/route.ts +52 -0
  45. package/src/app/api/chat/files/search/route.ts +50 -0
  46. package/src/app/api/diagnostics/chat-streams/route.ts +65 -0
  47. package/src/app/api/environment/rescan-if-stale/__tests__/route.test.ts +45 -0
  48. package/src/app/api/environment/rescan-if-stale/route.ts +23 -0
  49. package/src/app/api/environment/skills/route.ts +13 -0
  50. package/src/app/api/instance/config/route.ts +41 -0
  51. package/src/app/api/instance/init/route.ts +34 -0
  52. package/src/app/api/instance/upgrade/check/route.ts +26 -0
  53. package/src/app/api/instance/upgrade/route.ts +96 -0
  54. package/src/app/api/instance/upgrade/status/route.ts +35 -0
  55. package/src/app/api/memory/route.ts +0 -11
  56. package/src/app/api/notifications/route.ts +4 -2
  57. package/src/app/api/projects/[id]/route.ts +5 -155
  58. package/src/app/api/projects/__tests__/delete-project.test.ts +10 -19
  59. package/src/app/api/schedules/[id]/execute/route.ts +111 -0
  60. package/src/app/api/schedules/[id]/route.ts +9 -1
  61. package/src/app/api/schedules/__tests__/execute-route.test.ts +118 -0
  62. package/src/app/api/schedules/route.ts +3 -12
  63. package/src/app/api/settings/chat/pins/route.ts +94 -0
  64. package/src/app/api/settings/chat/saved-searches/__tests__/route.test.ts +119 -0
  65. package/src/app/api/settings/chat/saved-searches/route.ts +79 -0
  66. package/src/app/api/settings/environment/route.ts +26 -0
  67. package/src/app/api/settings/openai/login/route.ts +22 -0
  68. package/src/app/api/settings/openai/logout/route.ts +7 -0
  69. package/src/app/api/settings/openai/route.ts +21 -1
  70. package/src/app/api/settings/providers/route.ts +35 -8
  71. package/src/app/api/tables/[id]/enrich/__tests__/route.test.ts +153 -0
  72. package/src/app/api/tables/[id]/enrich/plan/route.ts +98 -0
  73. package/src/app/api/tables/[id]/enrich/route.ts +147 -0
  74. package/src/app/api/tables/[id]/enrich/runs/route.ts +25 -0
  75. package/src/app/api/tasks/[id]/execute/route.ts +52 -33
  76. package/src/app/api/tasks/[id]/respond/route.ts +31 -15
  77. package/src/app/api/tasks/[id]/resume/route.ts +24 -3
  78. package/src/app/api/workflows/[id]/resume/route.ts +59 -0
  79. package/src/app/api/workflows/[id]/status/route.ts +22 -8
  80. package/src/app/api/workspace/context/route.ts +2 -0
  81. package/src/app/api/workspace/fix-data-dir/route.ts +81 -0
  82. package/src/app/chat/page.tsx +11 -0
  83. package/src/app/documents/page.tsx +4 -1
  84. package/src/app/inbox/page.tsx +12 -5
  85. package/src/app/layout.tsx +42 -21
  86. package/src/app/page.tsx +0 -2
  87. package/src/app/settings/page.tsx +8 -9
  88. package/src/components/chat/__tests__/capability-banner.test.tsx +38 -0
  89. package/src/components/chat/__tests__/chat-session-provider.test.tsx +573 -0
  90. package/src/components/chat/__tests__/skill-row.test.tsx +91 -0
  91. package/src/components/chat/capability-banner.tsx +68 -0
  92. package/src/components/chat/chat-command-popover.tsx +670 -49
  93. package/src/components/chat/chat-input.tsx +104 -10
  94. package/src/components/chat/chat-message.tsx +12 -3
  95. package/src/components/chat/chat-session-provider.tsx +790 -0
  96. package/src/components/chat/chat-shell.tsx +151 -401
  97. package/src/components/chat/command-tab-bar.tsx +68 -0
  98. package/src/components/chat/conversation-template-picker.tsx +421 -0
  99. package/src/components/chat/help-dialog.tsx +39 -0
  100. package/src/components/chat/skill-composition-conflict-dialog.tsx +96 -0
  101. package/src/components/chat/skill-row.tsx +147 -0
  102. package/src/components/documents/document-browser.tsx +37 -19
  103. package/src/components/instance/__tests__/instance-section.test.tsx +125 -0
  104. package/src/components/instance/instance-section.tsx +382 -0
  105. package/src/components/instance/upgrade-badge.tsx +219 -0
  106. package/src/components/notifications/__tests__/batch-proposal-review.test.tsx +95 -0
  107. package/src/components/notifications/__tests__/notification-item.test.tsx +106 -0
  108. package/src/components/notifications/__tests__/permission-response-actions.test.tsx +70 -0
  109. package/src/components/notifications/batch-proposal-review.tsx +20 -5
  110. package/src/components/notifications/inbox-list.tsx +11 -2
  111. package/src/components/notifications/notification-item.tsx +56 -2
  112. package/src/components/notifications/pending-approval-host.tsx +56 -37
  113. package/src/components/notifications/permission-response-actions.tsx +155 -1
  114. package/src/components/schedules/schedule-create-sheet.tsx +19 -1
  115. package/src/components/schedules/schedule-edit-sheet.tsx +20 -1
  116. package/src/components/schedules/schedule-form.tsx +31 -0
  117. package/src/components/settings/__tests__/providers-runtimes-section.test.tsx +149 -0
  118. package/src/components/settings/auth-method-selector.tsx +19 -4
  119. package/src/components/settings/auth-status-badge.tsx +28 -3
  120. package/src/components/settings/environment-section.tsx +102 -0
  121. package/src/components/settings/openai-chatgpt-auth-control.tsx +278 -0
  122. package/src/components/settings/openai-runtime-section.tsx +7 -1
  123. package/src/components/settings/providers-runtimes-section.tsx +138 -19
  124. package/src/components/shared/__tests__/filter-hint.test.tsx +40 -0
  125. package/src/components/shared/__tests__/saved-searches-manager.test.tsx +147 -0
  126. package/src/components/shared/app-sidebar.tsx +4 -3
  127. package/src/components/shared/command-palette.tsx +266 -7
  128. package/src/components/shared/filter-hint.tsx +70 -0
  129. package/src/components/shared/filter-input.tsx +59 -0
  130. package/src/components/shared/saved-searches-manager.tsx +199 -0
  131. package/src/components/shared/theme-toggle.tsx +5 -24
  132. package/src/components/shared/workspace-indicator.tsx +61 -2
  133. package/src/components/tables/__tests__/table-enrichment-sheet.test.tsx +130 -0
  134. package/src/components/tables/table-create-sheet.tsx +4 -0
  135. package/src/components/tables/table-enrichment-runs.tsx +103 -0
  136. package/src/components/tables/table-enrichment-sheet.tsx +538 -0
  137. package/src/components/tables/table-spreadsheet.tsx +29 -5
  138. package/src/components/tables/table-toolbar.tsx +10 -1
  139. package/src/components/tasks/kanban-board.tsx +1 -0
  140. package/src/components/tasks/kanban-column.tsx +53 -14
  141. package/src/components/tasks/task-bento-grid.tsx +31 -2
  142. package/src/components/tasks/task-card.tsx +29 -3
  143. package/src/components/tasks/task-chip-bar.tsx +54 -1
  144. package/src/components/tasks/task-result-renderer.tsx +1 -1
  145. package/src/components/workflows/delay-step-body.tsx +109 -0
  146. package/src/components/workflows/hooks/use-workflow-status.ts +50 -0
  147. package/src/components/workflows/loop-status-view.tsx +1 -1
  148. package/src/components/workflows/shared/step-result.tsx +78 -0
  149. package/src/components/workflows/shared/workflow-header.tsx +141 -0
  150. package/src/components/workflows/shared/workflow-loading-skeleton.tsx +36 -0
  151. package/src/components/workflows/swarm-dashboard.tsx +2 -15
  152. package/src/components/workflows/views/loop-pattern-view.tsx +137 -0
  153. package/src/components/workflows/views/sequence-pattern-view.tsx +511 -0
  154. package/src/components/workflows/workflow-form-view.tsx +133 -16
  155. package/src/components/workflows/workflow-status-view.tsx +30 -740
  156. package/src/hooks/__tests__/use-chat-autocomplete-tabs.test.ts +47 -0
  157. package/src/hooks/__tests__/use-saved-searches.test.ts +70 -0
  158. package/src/hooks/use-active-skills.ts +110 -0
  159. package/src/hooks/use-chat-autocomplete.ts +120 -7
  160. package/src/hooks/use-enriched-skills.ts +19 -0
  161. package/src/hooks/use-pinned-entries.ts +104 -0
  162. package/src/hooks/use-recent-user-messages.ts +19 -0
  163. package/src/hooks/use-saved-searches.ts +142 -0
  164. package/src/instrumentation-node.ts +94 -0
  165. package/src/instrumentation.ts +4 -48
  166. package/src/lib/agents/__tests__/claude-agent-sdk-options.test.ts +56 -0
  167. package/src/lib/agents/__tests__/claude-agent.test.ts +212 -0
  168. package/src/lib/agents/__tests__/execution-manager.test.ts +1 -27
  169. package/src/lib/agents/__tests__/failure-reason.test.ts +68 -0
  170. package/src/lib/agents/__tests__/learned-context.test.ts +0 -11
  171. package/src/lib/agents/__tests__/learning-session.test.ts +158 -0
  172. package/src/lib/agents/__tests__/pattern-extractor.test.ts +48 -0
  173. package/src/lib/agents/__tests__/task-dispatch.test.ts +166 -0
  174. package/src/lib/agents/__tests__/tool-permissions.test.ts +60 -0
  175. package/src/lib/agents/claude-agent.ts +217 -21
  176. package/src/lib/agents/execution-manager.ts +0 -35
  177. package/src/lib/agents/handoff/bus.ts +2 -2
  178. package/src/lib/agents/learned-context.ts +0 -12
  179. package/src/lib/agents/learning-session.ts +18 -5
  180. package/src/lib/agents/profiles/__tests__/list-fused-profiles.test.ts +110 -0
  181. package/src/lib/agents/profiles/__tests__/registry.test.ts +53 -4
  182. package/src/lib/agents/profiles/builtins/upgrade-assistant/SKILL.md +97 -0
  183. package/src/lib/agents/profiles/builtins/upgrade-assistant/profile.yaml +36 -0
  184. package/src/lib/agents/profiles/list-fused-profiles.ts +104 -0
  185. package/src/lib/agents/profiles/registry.ts +18 -0
  186. package/src/lib/agents/profiles/types.ts +7 -1
  187. package/src/lib/agents/router.ts +3 -6
  188. package/src/lib/agents/runtime/__tests__/catalog.test.ts +130 -0
  189. package/src/lib/agents/runtime/__tests__/execution-target.test.ts +183 -0
  190. package/src/lib/agents/runtime/__tests__/openai-codex-auth.test.ts +118 -0
  191. package/src/lib/agents/runtime/anthropic-direct.ts +8 -0
  192. package/src/lib/agents/runtime/catalog.ts +121 -0
  193. package/src/lib/agents/runtime/claude-sdk.ts +32 -0
  194. package/src/lib/agents/runtime/codex-app-server-client.ts +11 -5
  195. package/src/lib/agents/runtime/execution-target.ts +456 -0
  196. package/src/lib/agents/runtime/index.ts +4 -0
  197. package/src/lib/agents/runtime/launch-failure.ts +101 -0
  198. package/src/lib/agents/runtime/openai-codex-auth.ts +389 -0
  199. package/src/lib/agents/runtime/openai-codex.ts +64 -60
  200. package/src/lib/agents/runtime/openai-direct.ts +8 -0
  201. package/src/lib/agents/runtime/types.ts +8 -0
  202. package/src/lib/agents/task-dispatch.ts +220 -0
  203. package/src/lib/agents/tool-permissions.ts +16 -1
  204. package/src/lib/book/chapter-mapping.ts +11 -0
  205. package/src/lib/book/content.ts +10 -0
  206. package/src/lib/chat/__tests__/active-skill-injection.test.ts +261 -0
  207. package/src/lib/chat/__tests__/active-streams.test.ts +49 -0
  208. package/src/lib/chat/__tests__/clean-filter-input.test.ts +68 -0
  209. package/src/lib/chat/__tests__/command-tabs.test.ts +68 -0
  210. package/src/lib/chat/__tests__/context-builder-files.test.ts +112 -0
  211. package/src/lib/chat/__tests__/dismissals.test.ts +65 -0
  212. package/src/lib/chat/__tests__/engine-sdk-options.test.ts +117 -0
  213. package/src/lib/chat/__tests__/finalize-safety-net.test.ts +139 -0
  214. package/src/lib/chat/__tests__/reconcile.test.ts +137 -0
  215. package/src/lib/chat/__tests__/skill-conflict.test.ts +35 -0
  216. package/src/lib/chat/__tests__/stream-telemetry.test.ts +151 -0
  217. package/src/lib/chat/__tests__/types.test.ts +28 -0
  218. package/src/lib/chat/active-skills.ts +31 -0
  219. package/src/lib/chat/active-streams.ts +27 -0
  220. package/src/lib/chat/clean-filter-input.ts +30 -0
  221. package/src/lib/chat/codex-engine.ts +46 -24
  222. package/src/lib/chat/command-tabs.ts +61 -0
  223. package/src/lib/chat/context-builder.ts +146 -4
  224. package/src/lib/chat/dismissals.ts +73 -0
  225. package/src/lib/chat/engine.ts +159 -18
  226. package/src/lib/chat/files/__tests__/search.test.ts +135 -0
  227. package/src/lib/chat/files/expand-mention.ts +76 -0
  228. package/src/lib/chat/files/search.ts +99 -0
  229. package/src/lib/chat/reconcile.ts +117 -0
  230. package/src/lib/chat/skill-composition.ts +210 -0
  231. package/src/lib/chat/skill-conflict.ts +105 -0
  232. package/src/lib/chat/stagent-tools.ts +7 -19
  233. package/src/lib/chat/stream-telemetry.ts +137 -0
  234. package/src/lib/chat/suggested-prompts.ts +28 -1
  235. package/src/lib/chat/system-prompt.ts +48 -1
  236. package/src/lib/chat/tool-catalog.ts +35 -4
  237. package/src/lib/chat/tools/__tests__/enrich-table-tool.test.ts +127 -0
  238. package/src/lib/chat/tools/__tests__/profile-tools.test.ts +51 -0
  239. package/src/lib/chat/tools/__tests__/schedule-tools.test.ts +261 -0
  240. package/src/lib/chat/tools/__tests__/settings-tools.test.ts +294 -0
  241. package/src/lib/chat/tools/__tests__/skill-tools.test.ts +474 -0
  242. package/src/lib/chat/tools/__tests__/task-tools.test.ts +399 -0
  243. package/src/lib/chat/tools/__tests__/workflow-tools-dedup.test.ts +351 -0
  244. package/src/lib/chat/tools/blueprint-tools.ts +190 -0
  245. package/src/lib/chat/tools/document-tools.ts +29 -13
  246. package/src/lib/chat/tools/helpers.ts +41 -0
  247. package/src/lib/chat/tools/notification-tools.ts +9 -5
  248. package/src/lib/chat/tools/profile-tools.ts +120 -23
  249. package/src/lib/chat/tools/project-tools.ts +33 -0
  250. package/src/lib/chat/tools/schedule-tools.ts +44 -11
  251. package/src/lib/chat/tools/skill-tools.ts +183 -0
  252. package/src/lib/chat/tools/table-tools.ts +71 -0
  253. package/src/lib/chat/tools/task-tools.ts +89 -21
  254. package/src/lib/chat/tools/workflow-tools.ts +275 -32
  255. package/src/lib/chat/types.ts +15 -0
  256. package/src/lib/constants/settings.ts +10 -18
  257. package/src/lib/data/__tests__/clear.test.ts +56 -2
  258. package/src/lib/data/clear.ts +17 -16
  259. package/src/lib/data/delete-project.ts +171 -0
  260. package/src/lib/db/__tests__/bootstrap.test.ts +1 -1
  261. package/src/lib/db/bootstrap.ts +62 -16
  262. package/src/lib/db/index.ts +5 -0
  263. package/src/lib/db/migrations/0009_add_app_instances.sql +25 -0
  264. package/src/lib/db/migrations/0024_add_workflow_resume_at.sql +10 -0
  265. package/src/lib/db/migrations/0025_drop_app_instances.sql +3 -0
  266. package/src/lib/db/migrations/0026_drop_license.sql +3 -0
  267. package/src/lib/db/migrations/meta/_journal.json +21 -0
  268. package/src/lib/db/schema.ts +94 -23
  269. package/src/lib/environment/__tests__/auto-promote.test.ts +132 -0
  270. package/src/lib/environment/__tests__/list-skills-enriched.test.ts +55 -0
  271. package/src/lib/environment/__tests__/skill-enrichment.test.ts +129 -0
  272. package/src/lib/environment/__tests__/skill-recommendations.test.ts +87 -0
  273. package/src/lib/environment/data.ts +9 -0
  274. package/src/lib/environment/list-skills.ts +176 -0
  275. package/src/lib/environment/parsers/__tests__/skill.test.ts +54 -0
  276. package/src/lib/environment/parsers/skill.ts +26 -5
  277. package/src/lib/environment/profile-generator.ts +54 -0
  278. package/src/lib/environment/skill-enrichment.ts +106 -0
  279. package/src/lib/environment/skill-recommendations.ts +66 -0
  280. package/src/lib/environment/workspace-context.ts +13 -1
  281. package/src/lib/filters/__tests__/parse.quoted.test.ts +40 -0
  282. package/src/lib/filters/__tests__/parse.test.ts +135 -0
  283. package/src/lib/filters/parse.ts +86 -0
  284. package/src/lib/import/dedup.ts +4 -54
  285. package/src/lib/instance/__tests__/bootstrap.test.ts +362 -0
  286. package/src/lib/instance/__tests__/detect.test.ts +115 -0
  287. package/src/lib/instance/__tests__/fingerprint.test.ts +48 -0
  288. package/src/lib/instance/__tests__/git-ops.test.ts +95 -0
  289. package/src/lib/instance/__tests__/settings.test.ts +83 -0
  290. package/src/lib/instance/__tests__/upgrade-poller.test.ts +181 -0
  291. package/src/lib/instance/bootstrap.ts +270 -0
  292. package/src/lib/instance/detect.ts +49 -0
  293. package/src/lib/instance/fingerprint.ts +76 -0
  294. package/src/lib/instance/git-ops.ts +95 -0
  295. package/src/lib/instance/settings.ts +61 -0
  296. package/src/lib/instance/types.ts +77 -0
  297. package/src/lib/instance/upgrade-poller.ts +205 -0
  298. package/src/lib/notifications/__tests__/visibility.test.ts +51 -0
  299. package/src/lib/notifications/visibility.ts +33 -0
  300. package/src/lib/schedules/__tests__/collision-check.test.ts +93 -0
  301. package/src/lib/schedules/__tests__/config.test.ts +62 -0
  302. package/src/lib/schedules/__tests__/firing-metrics.test.ts +99 -0
  303. package/src/lib/schedules/__tests__/integration.test.ts +82 -0
  304. package/src/lib/schedules/__tests__/slot-claim.test.ts +242 -0
  305. package/src/lib/schedules/__tests__/tick-scheduler.test.ts +102 -0
  306. package/src/lib/schedules/__tests__/turn-budget.test.ts +228 -0
  307. package/src/lib/schedules/collision-check.ts +105 -0
  308. package/src/lib/schedules/config.ts +53 -0
  309. package/src/lib/schedules/scheduler.ts +236 -17
  310. package/src/lib/schedules/slot-claim.ts +105 -0
  311. package/src/lib/settings/__tests__/openai-auth.test.ts +101 -0
  312. package/src/lib/settings/__tests__/openai-login-manager.test.ts +64 -0
  313. package/src/lib/settings/__tests__/runtime-setup.test.ts +33 -0
  314. package/src/lib/settings/openai-auth.ts +105 -10
  315. package/src/lib/settings/openai-login-manager.ts +260 -0
  316. package/src/lib/settings/runtime-setup.ts +14 -4
  317. package/src/lib/tables/__tests__/enrichment-planner.test.ts +124 -0
  318. package/src/lib/tables/__tests__/enrichment.test.ts +147 -0
  319. package/src/lib/tables/enrichment-planner.ts +454 -0
  320. package/src/lib/tables/enrichment.ts +328 -0
  321. package/src/lib/tables/query-builder.ts +5 -2
  322. package/src/lib/tables/trigger-evaluator.ts +3 -2
  323. package/src/lib/theme.ts +71 -0
  324. package/src/lib/usage/ledger.ts +2 -18
  325. package/src/lib/util/__tests__/similarity.test.ts +106 -0
  326. package/src/lib/util/similarity.ts +77 -0
  327. package/src/lib/utils/format-timestamp.ts +24 -0
  328. package/src/lib/utils/stagent-paths.ts +12 -0
  329. package/src/lib/validators/__tests__/blueprint.test.ts +172 -0
  330. package/src/lib/validators/__tests__/settings.test.ts +10 -0
  331. package/src/lib/validators/blueprint.ts +70 -9
  332. package/src/lib/validators/profile.ts +2 -2
  333. package/src/lib/validators/settings.ts +3 -1
  334. package/src/lib/workflows/__tests__/delay.test.ts +196 -0
  335. package/src/lib/workflows/__tests__/engine.test.ts +8 -0
  336. package/src/lib/workflows/__tests__/loop-executor.test.ts +54 -0
  337. package/src/lib/workflows/__tests__/post-action.test.ts +108 -0
  338. package/src/lib/workflows/blueprints/__tests__/render-prompt.test.ts +124 -0
  339. package/src/lib/workflows/blueprints/instantiator.ts +22 -1
  340. package/src/lib/workflows/blueprints/render-prompt.ts +71 -0
  341. package/src/lib/workflows/blueprints/types.ts +16 -2
  342. package/src/lib/workflows/delay.ts +106 -0
  343. package/src/lib/workflows/engine.ts +212 -7
  344. package/src/lib/workflows/loop-executor.ts +349 -24
  345. package/src/lib/workflows/post-action.ts +91 -0
  346. package/src/lib/workflows/types.ts +166 -1
  347. package/src/test/setup.ts +10 -0
  348. package/src/app/api/license/checkout/route.ts +0 -28
  349. package/src/app/api/license/portal/route.ts +0 -26
  350. package/src/app/api/license/route.ts +0 -89
  351. package/src/app/api/license/usage/route.ts +0 -63
  352. package/src/app/api/marketplace/browse/route.ts +0 -15
  353. package/src/app/api/marketplace/import/route.ts +0 -28
  354. package/src/app/api/marketplace/publish/route.ts +0 -40
  355. package/src/app/api/onboarding/email/route.ts +0 -53
  356. package/src/app/api/settings/telemetry/route.ts +0 -14
  357. package/src/app/api/sync/export/route.ts +0 -54
  358. package/src/app/api/sync/restore/route.ts +0 -37
  359. package/src/app/api/sync/sessions/route.ts +0 -24
  360. package/src/app/auth/callback/route.ts +0 -73
  361. package/src/app/marketplace/page.tsx +0 -19
  362. package/src/components/analytics/analytics-gate-card.tsx +0 -101
  363. package/src/components/marketplace/blueprint-card.tsx +0 -61
  364. package/src/components/marketplace/marketplace-browser.tsx +0 -131
  365. package/src/components/onboarding/email-capture-card.tsx +0 -104
  366. package/src/components/settings/activation-form.tsx +0 -95
  367. package/src/components/settings/cloud-account-section.tsx +0 -147
  368. package/src/components/settings/cloud-sync-section.tsx +0 -155
  369. package/src/components/settings/subscription-section.tsx +0 -410
  370. package/src/components/settings/telemetry-section.tsx +0 -80
  371. package/src/components/shared/premium-gate-overlay.tsx +0 -50
  372. package/src/components/shared/schedule-gate-dialog.tsx +0 -64
  373. package/src/components/shared/upgrade-banner.tsx +0 -112
  374. package/src/hooks/use-supabase-auth.ts +0 -79
  375. package/src/lib/billing/email.ts +0 -54
  376. package/src/lib/billing/products.ts +0 -80
  377. package/src/lib/billing/stripe.ts +0 -101
  378. package/src/lib/cloud/supabase-browser.ts +0 -32
  379. package/src/lib/cloud/supabase-client.ts +0 -56
  380. package/src/lib/license/__tests__/features.test.ts +0 -56
  381. package/src/lib/license/__tests__/key-format.test.ts +0 -88
  382. package/src/lib/license/__tests__/manager.test.ts +0 -64
  383. package/src/lib/license/__tests__/tier-limits.test.ts +0 -79
  384. package/src/lib/license/cloud-validation.ts +0 -60
  385. package/src/lib/license/features.ts +0 -44
  386. package/src/lib/license/key-format.ts +0 -101
  387. package/src/lib/license/limit-check.ts +0 -111
  388. package/src/lib/license/limit-queries.ts +0 -51
  389. package/src/lib/license/manager.ts +0 -345
  390. package/src/lib/license/notifications.ts +0 -59
  391. package/src/lib/license/tier-limits.ts +0 -71
  392. package/src/lib/marketplace/marketplace-client.ts +0 -107
  393. package/src/lib/sync/cloud-sync.ts +0 -235
  394. package/src/lib/telemetry/conversion-events.ts +0 -71
  395. package/src/lib/telemetry/queue.ts +0 -122
  396. package/src/lib/validators/license.ts +0 -33
package/README.md CHANGED
@@ -39,47 +39,6 @@ The AI agent stack is broken for business operators. You can spin up an agent in
39
39
 
40
40
  ---
41
41
 
42
- ## Community & Premium Editions
43
-
44
- Stagent is **free and fully functional** as a local-first tool. The Community Edition (Apache 2.0) includes everything you need to run AI agents, workflows, and schedules on your machine. Premium tiers add cloud sync, expanded limits, marketplace access, and analytics for power users and teams.
45
-
46
- ### Feature Comparison
47
-
48
- | Capability | Community (Free) | Premium |
49
- |---|---|---|
50
- | Local tasks & workflows | Unlimited | Unlimited |
51
- | Agent profiles | All built-in | All built-in |
52
- | Human-in-the-loop approval | Full | Full |
53
- | Agent memories per profile | 50 | 200 - Unlimited |
54
- | Learned context versions | 10 | 50 - Unlimited |
55
- | Active schedules | 5 | 20 - Unlimited |
56
- | History retention | 30 days | 180 days - Unlimited |
57
- | Cloud sync & backup | — | Solo and above |
58
- | Marketplace blueprints | Browse only | Import & Publish |
59
- | Outcome analytics | — | Operator and above |
60
-
61
- ### Soft Limits
62
-
63
- | Resource | Community Limit | At Limit |
64
- |---|---|---|
65
- | Agent memories | 50 per profile | New writes blocked, existing preserved |
66
- | Context versions | 10 per profile | New proposals blocked |
67
- | Active schedules | 5 | New schedule creation returns 402 |
68
- | Task history | 30 days | Older entries pruned daily |
69
-
70
- ### Pricing
71
-
72
- | Tier | Price | Best For |
73
- |---|---|---|
74
- | Community | Free forever | Individual developers, evaluation |
75
- | Solo | $19/mo | Power users, expanded limits |
76
- | Operator | $49/mo | Professionals, analytics, cloud sync |
77
- | Scale | $99/mo | Teams, marketplace publishing, unlimited |
78
-
79
- [Get Premium →](https://stagent.io/pricing)
80
-
81
- ---
82
-
83
42
  ## Runtime Bridge
84
43
 
85
44
  Run the same business process on different AI providers without changing a line of configuration. Stagent's shared runtime registry routes tasks, schedules, and workflow steps through **Claude Code** (Anthropic Claude Agent SDK) and **OpenAI Codex App Server**, landing everything in the same inbox, monitoring, and cost surfaces. Switching providers is a settings change, not a rewrite.
@@ -114,6 +73,9 @@ Run the same business process on different AI providers without changing a line
114
73
  | 📦 | **[Workflow Context Batching](#workflow-context-batching)** | Workflow-scoped proposal buffering with batch approve/reject for learned context |
115
74
  | 🧪 | **[E2E Test Automation](#e2e-test-automation)** | API-level end-to-end test suite covering both runtimes, 4 profiles, and 4 workflow patterns |
116
75
  | ⌨️ | **[Command Palette](#command-palette)** | Global `⌘K` search for fast navigation across tasks, projects, workflows, and settings |
76
+ | 🧱 | **[Skill Composition](#skill-composition)** | Activate up to 3 skills at once with conflict detection and runtime-aware capability gates |
77
+ | 🔎 | **[Filters & Saved Searches](#filters--saved-searches)** | `#key:value` filter grammar, pinned and saved searches surfaced in `⌘K` palette |
78
+ | 🛡️ | **[Upgrade Detection](#upgrade-detection)** | Hourly upstream check with in-app notifications and guided merge sessions |
117
79
  | 📖 | **[Playbook](#playbook)** | Built-in documentation with usage-stage awareness, adoption heatmap, and guided learning journeys |
118
80
  | 📚 | **[Living Book](#living-book)** | AI-native book reader with 9 chapters, agent-powered regeneration, staleness detection, and reading paths |
119
81
  | 🌐 | **[Environment](#environment)** | Control plane for Claude Code and Codex CLI environments with scanning, caching, sync, and templates |
@@ -123,7 +85,11 @@ Run the same business process on different AI providers without changing a line
123
85
 
124
86
  ## Architecture
125
87
 
126
- <img src="https://raw.githubusercontent.com/navam-io/stagent/main/public/readme/architecture.svg" alt="Stagent architecture diagram" width="900" />
88
+ <picture>
89
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/navam-io/stagent/main/public/readme/architecture-dark.svg">
90
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/navam-io/stagent/main/public/readme/architecture-light.svg">
91
+ <img src="https://raw.githubusercontent.com/navam-io/stagent/main/public/readme/architecture-light.svg" alt="Stagent architecture diagram" width="900" />
92
+ </picture>
127
93
 
128
94
  **Key design decisions:**
129
95
 
@@ -313,6 +279,9 @@ Pending permission requests now surface through a shell-level approval presenter
313
279
  #### Tool Permission Presets
314
280
  Pre-configured permission bundles that reduce friction for common tool approval patterns. Three layered presets — read-only (file reads, glob, grep), git-safe (adds git operations), and full-auto (adds write, edit, bash) — compose with existing "Always Allow" patterns. Presets are layered: enabling git-safe automatically includes read-only patterns; removing git-safe only strips its unique additions. Risk badges indicate the trust level of each preset. Manage presets from the Settings page alongside individual tool permissions.
315
281
 
282
+ #### Upgrade Detection
283
+ Hourly poller checks the upstream `origin/main` for new commits and surfaces them via an in-app `UpgradeBadge` + notification queue. If three consecutive checks fail, a single deduplicated "Upgrade check failing" notification is inserted (and cleared on the next successful tick). The `upgrade-assistant` profile drives guided merge sessions end-to-end — including free-form questions and 3-choice option cards when a merge conflict or drifted `main` requires operator input. Dev repos are fully gated via `STAGENT_DEV_MODE` and a `.git/stagent-dev-mode` sentinel so contributor pushes are never blocked.
284
+
316
285
  #### Schedules
317
286
  Time-based scheduling for agent tasks with human-friendly intervals (`5m`, `2h`, `1d`) and raw 5-field cron expressions. One-shot and recurring modes with pause/resume lifecycle, expiry limits, and max firings. Each firing creates a child task through the shared execution pipeline, and schedules can now target a runtime explicitly. Scheduler runs as a poll-based engine started via Next.js instrumentation hook.
318
287
 
@@ -346,6 +315,12 @@ Conversational control plane for all workspace primitives — projects, tasks, w
346
315
  |:-:|:-:|:-:|
347
316
  | <img src="https://raw.githubusercontent.com/navam-io/stagent/main/public/readme/chat-list.png" alt="Chat tool catalog with category tabs" width="380" /> | <img src="https://raw.githubusercontent.com/navam-io/stagent/main/public/readme/chat-model-selector.png" alt="Chat model selector with cost tiers" width="380" /> | <img src="https://raw.githubusercontent.com/navam-io/stagent/main/public/readme/chat-create-tab.png" alt="Chat Create category prompts" width="380" /> |
348
317
 
318
+ #### Skill Composition
319
+ Activate up to three skills in a single conversation with conflict detection and runtime-aware capability gates. The Skills tab in the chat popover surfaces `+ Add` buttons on inactive skills, active badges with deactivate actions, and an "N of M active" indicator. When two skills issue polarity-divergent directives on shared keywords, a conflict dialog previews the excerpts and lets you confirm with `force:true` or back out. Composition honors the runtime capability matrix — Claude Code and Codex App Server support up to 3 active skills, while Ollama stays at 1. Conversations persist active skills through an additive `active_skill_ids` column that preserves legacy single-skill reads.
320
+
321
+ #### Filters & Saved Searches
322
+ Structured `#key:value` filter grammar across chat, documents, and the `⌘K` palette. The shared `FilterInput` parser accepts bare clauses, quoted values (`#tag:"needs review"`), and free text — clauses AND with surface-specific Select filters and sync to URL params for shareable, refresh-persistent views. Save any filter expression with a rename footer; saved searches appear as a dedicated group in the mention popover and in the command palette, so views built in one surface are reachable from anywhere. Pinned saved searches sit at the top of both lists for zero-click recall.
323
+
349
324
  #### Monitoring
350
325
  Real-time agent log streaming via Server-Sent Events. Filter by task or event type, click entries to jump to task details, and auto-pause polling when the tab is hidden (Page Visibility API).
351
326
 
@@ -548,12 +523,13 @@ All 14 features shipped across three layers:
548
523
  |----------|---------|
549
524
  | **Documents** (5) | File attachments, preprocessing (5 formats), agent context injection, document browser, output generation |
550
525
  | **Agent Intelligence** (6) | Multi-agent routing, autonomous loops, multi-agent swarm, AI assist→workflows, agent self-improvement, workflow context batching |
551
- | **Agent Profiles** (2) | Agent profile catalog (21 profiles), workflow blueprints (8 templates) |
526
+ | **Agent Profiles** (2) | Agent profile catalog (<!-- STAT:builtinProfiles -->21<!-- /STAT --> profiles), workflow blueprints (<!-- STAT:workflowBlueprints -->13<!-- /STAT --> templates) |
552
527
  | **UI Enhancement** (13) | Ambient approvals, learned context UX, micro-visualizations, command palette, operational surface, profile surface, accessibility, UI density, kanban operations, board persistence, detail view redesign, playbook documentation, workflow UX overhaul |
553
528
  | **Platform** (8) | Scheduled prompt loops, tool permissions, provider runtimes, OpenAI Codex runtime, cross-provider profiles, parallel fork/join, tool permission presets, npm publish (deferred) |
554
529
  | **Runtime Quality** (2) | SDK runtime hardening, E2E test automation |
555
530
  | **Governance** (3) | Usage metering ledger, spend budget guardrails, cost & usage dashboard |
556
- | **Chat** (6) | Chat data layer, chat engine (5-tier context, CRUD tools), API routes (SSE streaming), UI shell, message rendering (Quick Access pills), input composer (tool catalog, model selector) |
531
+ | **Chat** (10) | Chat data layer, chat engine (5-tier context, CRUD tools), API routes (SSE streaming), UI shell, message rendering (Quick Access pills), input composer (tool catalog, model selector), skill composition (multi-skill with conflict detection), filter namespace (`#key:value` grammar), pinned + saved searches, conversation templates |
532
+ | **Platform Hardening** (2) | Runtime validation hardening (MCP-tool runtime-id validation with safe fallbacks), upgrade detection (hourly upstream poll + guided merge sessions) |
557
533
  | **Environment** (11) | Environment scanner, cache, dashboard, git checkpoint manager, sync engine, project onboarding, templates, cross-project comparison, skill portfolio, health scoring, agent profile from environment |
558
534
  | **Living Book** (5) | Content merge (chapters → playbook), author's notes, reading paths, markdown pipeline, self-updating chapters |
559
535
 
package/dist/cli.js CHANGED
@@ -130,8 +130,8 @@ var STAGENT_TABLES = [
130
130
  "user_table_triggers",
131
131
  "user_table_row_history",
132
132
  "snapshots",
133
- "license",
134
- "workflow_execution_stats"
133
+ "workflow_execution_stats",
134
+ "schedule_firing_metrics"
135
135
  ];
136
136
  function bootstrapStagentDatabase(sqlite2) {
137
137
  sqlite2.exec(`
@@ -154,6 +154,9 @@ function bootstrapStagentDatabase(sqlite2) {
154
154
  status TEXT DEFAULT 'planned' NOT NULL,
155
155
  assigned_agent TEXT,
156
156
  agent_profile TEXT,
157
+ effective_runtime_id TEXT,
158
+ effective_model_id TEXT,
159
+ runtime_fallback_reason TEXT,
157
160
  priority INTEGER DEFAULT 2 NOT NULL,
158
161
  result TEXT,
159
162
  session_id TEXT,
@@ -175,6 +178,7 @@ function bootstrapStagentDatabase(sqlite2) {
175
178
  status TEXT DEFAULT 'draft' NOT NULL,
176
179
  run_number INTEGER DEFAULT 0 NOT NULL,
177
180
  runtime_id TEXT,
181
+ resume_at INTEGER,
178
182
  created_at INTEGER NOT NULL,
179
183
  updated_at INTEGER NOT NULL,
180
184
  FOREIGN KEY (project_id) REFERENCES projects(id) ON UPDATE NO ACTION ON DELETE NO ACTION
@@ -276,6 +280,32 @@ function bootstrapStagentDatabase(sqlite2) {
276
280
  CREATE INDEX IF NOT EXISTS idx_schedules_next_fire_at ON schedules(next_fire_at);
277
281
  CREATE INDEX IF NOT EXISTS idx_schedules_project_id ON schedules(project_id);
278
282
 
283
+ -- schedule_firing_metrics is placed here (between schedules indexes and
284
+ -- notifications indexes) to satisfy its foreign-key dependency on schedules.
285
+ -- Future tables with FK dependencies should follow the same "place after
286
+ -- parent table" discipline rather than batching all CREATE TABLE at the top.
287
+ CREATE TABLE IF NOT EXISTS schedule_firing_metrics (
288
+ id TEXT PRIMARY KEY NOT NULL,
289
+ schedule_id TEXT NOT NULL,
290
+ task_id TEXT,
291
+ fired_at INTEGER NOT NULL,
292
+ slot_claimed_at INTEGER,
293
+ completed_at INTEGER,
294
+ slot_wait_ms INTEGER,
295
+ duration_ms INTEGER,
296
+ turn_count INTEGER,
297
+ max_turns_at_firing INTEGER,
298
+ event_loop_lag_ms REAL,
299
+ peak_rss_mb INTEGER,
300
+ chat_streams_active INTEGER,
301
+ concurrent_schedules INTEGER,
302
+ failure_reason TEXT,
303
+ FOREIGN KEY (schedule_id) REFERENCES schedules(id) ON UPDATE NO ACTION ON DELETE NO ACTION,
304
+ FOREIGN KEY (task_id) REFERENCES tasks(id) ON UPDATE NO ACTION ON DELETE NO ACTION
305
+ );
306
+
307
+ CREATE INDEX IF NOT EXISTS idx_sfm_schedule_time ON schedule_firing_metrics(schedule_id, fired_at);
308
+
279
309
  CREATE INDEX IF NOT EXISTS idx_notifications_task_id ON notifications(task_id);
280
310
  CREATE INDEX IF NOT EXISTS idx_notifications_read ON notifications(read);
281
311
  CREATE INDEX IF NOT EXISTS idx_documents_task_id ON documents(task_id);
@@ -344,6 +374,7 @@ function bootstrapStagentDatabase(sqlite2) {
344
374
 
345
375
  CREATE INDEX IF NOT EXISTS idx_views_surface ON views(surface);
346
376
  CREATE INDEX IF NOT EXISTS idx_views_surface_default ON views(surface, is_default);
377
+
347
378
  `);
348
379
  const addColumnIfMissing = (ddl) => {
349
380
  try {
@@ -357,6 +388,9 @@ function bootstrapStagentDatabase(sqlite2) {
357
388
  };
358
389
  addColumnIfMissing(`ALTER TABLE tasks ADD COLUMN agent_profile TEXT;`);
359
390
  sqlite2.exec(`CREATE INDEX IF NOT EXISTS idx_tasks_agent_profile ON tasks(agent_profile);`);
391
+ addColumnIfMissing(`ALTER TABLE tasks ADD COLUMN effective_runtime_id TEXT;`);
392
+ addColumnIfMissing(`ALTER TABLE tasks ADD COLUMN effective_model_id TEXT;`);
393
+ addColumnIfMissing(`ALTER TABLE tasks ADD COLUMN runtime_fallback_reason TEXT;`);
360
394
  addColumnIfMissing(`ALTER TABLE tasks ADD COLUMN workflow_id TEXT REFERENCES workflows(id);`);
361
395
  sqlite2.exec(`CREATE INDEX IF NOT EXISTS idx_tasks_workflow_id ON tasks(workflow_id);`);
362
396
  addColumnIfMissing(`ALTER TABLE tasks ADD COLUMN schedule_id TEXT REFERENCES schedules(id);`);
@@ -380,6 +414,9 @@ function bootstrapStagentDatabase(sqlite2) {
380
414
  addColumnIfMissing(`ALTER TABLE documents ADD COLUMN source TEXT DEFAULT 'upload';`);
381
415
  addColumnIfMissing(`ALTER TABLE documents ADD COLUMN conversation_id TEXT REFERENCES conversations(id);`);
382
416
  addColumnIfMissing(`ALTER TABLE documents ADD COLUMN message_id TEXT;`);
417
+ addColumnIfMissing(`ALTER TABLE conversations ADD COLUMN active_skill_id TEXT;`);
418
+ addColumnIfMissing(`ALTER TABLE conversations ADD COLUMN active_skill_ids TEXT DEFAULT '[]';`);
419
+ addColumnIfMissing(`ALTER TABLE workflows ADD COLUMN resume_at INTEGER;`);
383
420
  sqlite2.exec(`CREATE INDEX IF NOT EXISTS idx_documents_source ON documents(source);`);
384
421
  sqlite2.exec(`CREATE INDEX IF NOT EXISTS idx_documents_conversation_id ON documents(conversation_id);`);
385
422
  sqlite2.exec(`
@@ -491,6 +528,8 @@ function bootstrapStagentDatabase(sqlite2) {
491
528
  status TEXT DEFAULT 'active' NOT NULL,
492
529
  session_id TEXT,
493
530
  context_scope TEXT,
531
+ active_skill_id TEXT,
532
+ active_skill_ids TEXT DEFAULT '[]',
494
533
  created_at INTEGER NOT NULL,
495
534
  updated_at INTEGER NOT NULL,
496
535
  FOREIGN KEY (project_id) REFERENCES projects(id) ON UPDATE NO ACTION ON DELETE NO ACTION
@@ -605,6 +644,15 @@ function bootstrapStagentDatabase(sqlite2) {
605
644
  addColumnIfMissing(`ALTER TABLE schedules ADD COLUMN failure_streak INTEGER DEFAULT 0 NOT NULL;`);
606
645
  addColumnIfMissing(`ALTER TABLE schedules ADD COLUMN last_failure_reason TEXT;`);
607
646
  addColumnIfMissing(`ALTER TABLE channel_configs ADD COLUMN direction TEXT DEFAULT 'outbound' NOT NULL;`);
647
+ addColumnIfMissing(`ALTER TABLE tasks ADD COLUMN slot_claimed_at INTEGER;`);
648
+ addColumnIfMissing(`ALTER TABLE tasks ADD COLUMN lease_expires_at INTEGER;`);
649
+ addColumnIfMissing(`ALTER TABLE tasks ADD COLUMN failure_reason TEXT;`);
650
+ addColumnIfMissing(`ALTER TABLE tasks ADD COLUMN max_turns INTEGER;`);
651
+ addColumnIfMissing(`ALTER TABLE schedules ADD COLUMN max_turns INTEGER;`);
652
+ addColumnIfMissing(`ALTER TABLE schedules ADD COLUMN max_turns_set_at INTEGER;`);
653
+ addColumnIfMissing(`ALTER TABLE schedules ADD COLUMN max_run_duration_sec INTEGER;`);
654
+ addColumnIfMissing(`ALTER TABLE schedules ADD COLUMN turn_budget_breach_streak INTEGER DEFAULT 0 NOT NULL;`);
655
+ sqlite2.exec(`CREATE INDEX IF NOT EXISTS idx_tasks_running_scheduled ON tasks(status, source_type, lease_expires_at);`);
608
656
  sqlite2.exec(`
609
657
  CREATE TABLE IF NOT EXISTS channel_bindings (
610
658
  id TEXT PRIMARY KEY NOT NULL,
@@ -902,21 +950,6 @@ function bootstrapStagentDatabase(sqlite2) {
902
950
  CREATE INDEX IF NOT EXISTS idx_snapshots_type ON snapshots(type);
903
951
  CREATE INDEX IF NOT EXISTS idx_snapshots_created_at ON snapshots(created_at);
904
952
 
905
- CREATE TABLE IF NOT EXISTS license (
906
- id TEXT PRIMARY KEY NOT NULL,
907
- supabase_user_id TEXT,
908
- tier TEXT DEFAULT 'community' NOT NULL,
909
- status TEXT DEFAULT 'inactive' NOT NULL,
910
- email TEXT,
911
- activated_at INTEGER,
912
- expires_at INTEGER,
913
- last_validated_at INTEGER,
914
- grace_period_expires_at INTEGER,
915
- encrypted_token TEXT,
916
- created_at INTEGER NOT NULL,
917
- updated_at INTEGER NOT NULL
918
- );
919
-
920
953
  CREATE TABLE IF NOT EXISTS workflow_execution_stats (
921
954
  id TEXT PRIMARY KEY,
922
955
  pattern TEXT NOT NULL,
@@ -989,6 +1022,20 @@ function markAllMigrationsApplied(sqlite2, migrationsFolder, migrationsTable = "
989
1022
  var __dirname = dirname2(fileURLToPath(import.meta.url));
990
1023
  var appDir = join3(__dirname, "..");
991
1024
  var launchCwd = process.cwd();
1025
+ var _envLocalPath = join3(launchCwd, ".env.local");
1026
+ if (existsSync2(_envLocalPath)) {
1027
+ for (const line of readFileSync(_envLocalPath, "utf-8").split("\n")) {
1028
+ const trimmed = line.trim();
1029
+ if (!trimmed || trimmed.startsWith("#")) continue;
1030
+ const eqIdx = trimmed.indexOf("=");
1031
+ if (eqIdx === -1) continue;
1032
+ const key = trimmed.slice(0, eqIdx).trim();
1033
+ const val = trimmed.slice(eqIdx + 1).trim().replace(/^(['"])(.*)\1$/, "$2");
1034
+ if (key && !(key in process.env)) {
1035
+ process.env[key] = val;
1036
+ }
1037
+ }
1038
+ }
992
1039
  var pkg = JSON.parse(readFileSync(join3(appDir, "package.json"), "utf-8"));
993
1040
  function getHelpText() {
994
1041
  const dir = getStagentDataDir();
@@ -1010,7 +1057,8 @@ Examples:
1010
1057
  node dist/cli.js --data-dir ~/.stagent-dogfood --port 3100
1011
1058
  `;
1012
1059
  }
1013
- program.name("stagent").description("AI Business Operating System").version(pkg.version).addHelpText("after", getHelpText).option("-p, --port <number>", "port to start on", "3000").option("--data-dir <path>", "custom data directory (overrides STAGENT_DATA_DIR)").option("--reset", "delete the local database before starting").option("--no-open", "don't auto-open browser").parse();
1060
+ program.name("stagent").description("AI Business Operating System").version(pkg.version).addHelpText("after", getHelpText).option("-p, --port <number>", "port to start on", "3000").option("--data-dir <path>", "custom data directory (overrides STAGENT_DATA_DIR)").option("--reset", "delete the local database before starting").option("--no-open", "don't auto-open browser");
1061
+ program.parse();
1014
1062
  var opts = program.opts();
1015
1063
  if (opts.dataDir) {
1016
1064
  process.env.STAGENT_DATA_DIR = opts.dataDir;
@@ -1,71 +1,159 @@
1
1
  {
2
- "generated": "2026-04-03T23:30:00Z",
3
- "summary": {
4
- "totalFeatures": 82,
5
- "coveredFeatures": 78,
6
- "gapCount": 4,
7
- "unusedScreenshotCount": 0,
8
- "brokenReferences": 0,
9
- "orphanedImages": 14
10
- },
2
+ "generated": "2026-04-16T05:57:41Z",
11
3
  "gaps": [
12
4
  {
13
- "feature": "book-content-merge",
14
- "category": "Living Book",
15
- "screenshots": ["book-list.png"],
5
+ "feature": "ai-assist-workflow-creation",
6
+ "category": "Agent Intelligence",
7
+ "screenshots": [
8
+ "dashboard-create-form-ai-assist.png",
9
+ "dashboard-create-form-ai-applied.png",
10
+ "dashboard-create-form-ai-breakdown.png",
11
+ "dashboard-workflow-confirm.png"
12
+ ],
13
+ "journeyCoverage": [],
14
+ "suggestedPersona": "power-user"
15
+ },
16
+ {
17
+ "feature": "autonomous-loop-execution",
18
+ "category": "Schedules",
19
+ "screenshots": [
20
+ "schedules-detail.png"
21
+ ],
22
+ "journeyCoverage": [],
23
+ "suggestedPersona": "power-user"
24
+ },
25
+ {
26
+ "feature": "chat-composition-ui-v1",
27
+ "category": "Chat",
28
+ "screenshots": [
29
+ "chat-skills-tab.png"
30
+ ],
16
31
  "journeyCoverage": [],
17
- "suggestedPersona": "personal",
18
- "note": "Book reader captured but not referenced in any journey"
32
+ "suggestedPersona": "personal"
19
33
  },
20
34
  {
21
- "feature": "book-reading-paths",
22
- "category": "Living Book",
23
- "screenshots": ["book-list.png"],
35
+ "feature": "chat-dedup-variant-tolerance",
36
+ "category": "Chat",
37
+ "screenshots": [
38
+ "chat-conversation.png"
39
+ ],
24
40
  "journeyCoverage": [],
25
- "suggestedPersona": "personal",
26
- "note": "Book navigation not in any journey"
41
+ "suggestedPersona": "personal"
27
42
  },
28
43
  {
29
- "feature": "tables-document-import",
30
- "category": "Structured Data",
31
- "screenshots": [],
32
- "journeyCoverage": ["work-use"],
33
- "suggestedPersona": "work",
34
- "note": "Import wizard not captured (no dedicated screenshot) but tables mentioned in Work journey"
44
+ "feature": "chat-file-mentions",
45
+ "category": "Chat",
46
+ "screenshots": [
47
+ "chat-mentions-popover.png",
48
+ "chat-entities-tab.png"
49
+ ],
50
+ "journeyCoverage": [],
51
+ "suggestedPersona": "personal"
52
+ },
53
+ {
54
+ "feature": "chat-settings-tool",
55
+ "category": "Chat",
56
+ "screenshots": [
57
+ "chat-tools-tab.png"
58
+ ],
59
+ "journeyCoverage": [],
60
+ "suggestedPersona": "personal"
61
+ },
62
+ {
63
+ "feature": "chat-skill-composition",
64
+ "category": "Agent Intelligence",
65
+ "screenshots": [
66
+ "chat-skills-tab.png",
67
+ "chat-slash-popover.png"
68
+ ],
69
+ "journeyCoverage": [],
70
+ "suggestedPersona": "power-user"
35
71
  },
36
72
  {
37
- "feature": "database-snapshot-backup",
38
- "category": "Platform",
39
- "screenshots": ["settings-snapshots.png"],
73
+ "feature": "instance-bootstrap",
74
+ "category": "Platform/Runtime",
75
+ "screenshots": [
76
+ "settings-instance.png"
77
+ ],
40
78
  "journeyCoverage": [],
41
- "suggestedPersona": "developer",
42
- "note": "New feature - settings snapshot card captured, not yet in any journey"
79
+ "suggestedPersona": "developer"
80
+ },
81
+ {
82
+ "feature": "multi-agent-swarm",
83
+ "category": "Agent Intelligence",
84
+ "screenshots": [
85
+ "dashboard-create-form-ai-breakdown.png"
86
+ ],
87
+ "journeyCoverage": [],
88
+ "suggestedPersona": "power-user"
89
+ },
90
+ {
91
+ "feature": "task-definition-ai",
92
+ "category": "Agent Intelligence",
93
+ "screenshots": [
94
+ "dashboard-create-form-ai-assist.png",
95
+ "dashboard-create-form-empty.png",
96
+ "dashboard-create-form-filled.png"
97
+ ],
98
+ "journeyCoverage": [],
99
+ "suggestedPersona": "power-user"
100
+ },
101
+ {
102
+ "feature": "upgrade-detection",
103
+ "category": "Platform/Runtime",
104
+ "screenshots": [
105
+ "settings-instance.png"
106
+ ],
107
+ "journeyCoverage": [],
108
+ "suggestedPersona": "developer"
43
109
  }
44
110
  ],
45
- "brokenReferences": [
46
- { "file": "developer.md", "screenshot": "settings-ollama-connected.png", "status": "STALE", "note": "Old screenshot in public/readme/, not in current screengrabs/" },
47
- { "file": "developer.md", "screenshot": "settings-channels-add-form.png", "status": "STALE", "note": "Old screenshot in public/readme/" },
48
- { "file": "developer.md", "screenshot": "settings-channels-telegram-form.png", "status": "STALE", "note": "Old screenshot in public/readme/" },
49
- { "file": "developer.md", "screenshot": "settings-channels-webhook-form.png", "status": "STALE", "note": "Old screenshot in public/readme/" },
50
- { "file": "developer.md", "screenshot": "chat-conversation.png", "status": "STALE", "note": "Old screenshot in public/readme/" },
51
- { "file": "developer.md", "screenshot": "schedules-detail.png", "status": "STALE", "note": "Old screenshot in public/readme/" },
52
- { "file": "personal-use.md", "screenshot": "dashboard-card-detail.png", "status": "STALE", "note": "Old screenshot in public/readme/" },
53
- { "file": "personal-use.md", "screenshot": "settings-channels.png", "status": "STALE", "note": "Old screenshot in public/readme/" },
54
- { "file": "power-user.md", "screenshot": "settings-ollama-connected.png", "status": "STALE", "note": "Old screenshot in public/readme/" },
55
- { "file": "power-user.md", "screenshot": "chat-model-selector.png", "status": "STALE", "note": "Old screenshot in public/readme/" },
56
- { "file": "power-user.md", "screenshot": "schedules-detail.png", "status": "STALE", "note": "Old screenshot in public/readme/" },
57
- { "file": "power-user.md", "screenshot": "chat-create-tab.png", "status": "STALE", "note": "Old screenshot in public/readme/" },
58
- { "file": "work-use.md", "screenshot": "chat-conversation.png", "status": "STALE", "note": "Old screenshot in public/readme/" },
59
- { "file": "work-use.md", "screenshot": "settings-channels.png", "status": "STALE", "note": "Old screenshot in public/readme/" }
111
+ "unusedScreenshots": [
112
+ "analytics-list.png",
113
+ "chat-actions-tab.png",
114
+ "chat-conversation.png",
115
+ "chat-entities-tab.png",
116
+ "chat-mentions-popover.png",
117
+ "chat-model-picker.png",
118
+ "chat-search-filter.png",
119
+ "chat-skills-tab.png",
120
+ "chat-slash-popover.png",
121
+ "chat-tools-tab.png",
122
+ "dashboard-below-fold.png",
123
+ "dashboard-create-form-ai-applied.png",
124
+ "dashboard-create-form-ai-assist.png",
125
+ "dashboard-create-form-ai-breakdown.png",
126
+ "dashboard-create-form-empty.png",
127
+ "dashboard-create-form-filled.png",
128
+ "dashboard-workflow-confirm.png",
129
+ "schedules-create-form-empty.png",
130
+ "schedules-create-form-filled.png",
131
+ "schedules-detail.png",
132
+ "settings-browser-tools.png",
133
+ "settings-channels-add-form.png",
134
+ "settings-instance.png",
135
+ "settings-ollama-connected.png",
136
+ "settings-ollama.png",
137
+ "tables-detail-details.png",
138
+ "tables-detail-triggers.png",
139
+ "tables-detail.png",
140
+ "trust-tier-popover.png",
141
+ "workflows-create-form-delay.png"
142
+ ],
143
+ "contentMismatches": [
144
+ {
145
+ "journey": "work-use.md",
146
+ "step": "Step 14",
147
+ "screenshot": "inbox-expanded.png",
148
+ "severity": "WRONG",
149
+ "issue": "Shows task detail page, not expanded inbox notification. Needs recapture."
150
+ }
60
151
  ],
61
- "orphanedImages": [
62
- "book-chapter-header.png", "book-chapter-nav.png", "book-reader.png",
63
- "book-settings.png", "book-toc.png", "book-try-it-now.png",
64
- "chat-conversation.png", "chat-create-tab.png", "chat-model-selector.png",
65
- "chat-quick-access.png", "dashboard-card-detail.png", "playbook-list.png",
66
- "schedules-detail.png", "schedules-edit-form.png", "settings-browser-tools.png",
67
- "settings-channels-add-form.png", "settings-channels-telegram-form.png",
68
- "settings-channels-webhook-form.png", "settings-channels.png",
69
- "settings-ollama-connected.png"
70
- ]
71
- }
152
+ "summary": {
153
+ "totalFeatures": 50,
154
+ "coveredFeatures": 39,
155
+ "gapCount": 11,
156
+ "unusedScreenshotCount": 30,
157
+ "contentMismatchCount": 1
158
+ }
159
+ }
@@ -1 +1 @@
1
- 2026-04-03T23:43:05Z
1
+ 2026-04-16T06:32:25Z
@@ -4,9 +4,9 @@ category: "feature-reference"
4
4
  section: "agent-intelligence"
5
5
  route: "cross-cutting"
6
6
  tags: [ai-assist, routing, autonomous, swarm, self-improvement, context, parallel, episodic-memory, handoffs]
7
- features: ["task-definition-ai", "multi-agent-routing", "autonomous-loop-execution", "multi-agent-swarm", "agent-self-improvement", "workflow-context-batching", "parallel-research-fork-join", "agent-episodic-memory", "agent-async-handoffs"]
7
+ features: ["task-definition-ai", "multi-agent-routing", "autonomous-loop-execution", "multi-agent-swarm", "agent-self-improvement", "workflow-context-batching", "parallel-research-fork-join", "agent-episodic-memory", "agent-async-handoffs", "chat-skill-composition"]
8
8
  screengrabCount: 0
9
- lastUpdated: "2026-03-31"
9
+ lastUpdated: "2026-04-15"
10
10
  ---
11
11
 
12
12
  # Agent Intelligence
@@ -65,6 +65,16 @@ Agents can hand off work to other agents asynchronously through a message bus:
65
65
 
66
66
  This enables multi-agent workflows where a researcher discovers a code issue and hands it off to the code reviewer without requiring a pre-built workflow definition.
67
67
 
68
+ ### Skill Composition
69
+
70
+ Chat conversations on capable runtimes can run multiple skills simultaneously, layering specialized behaviors (research, code review, document drafting) onto a single session. The composition engine enforces three guardrails:
71
+
72
+ - **Capability gating** — only runtimes that advertise `supportsSkillComposition` accept more than one active skill; others fall back to single-skill mode with a visible hint.
73
+ - **Conflict heuristic** — new skills whose tools or instructions overlap with an active one trigger a confirmation dialog before the swap is applied.
74
+ - **Prompt-budget eviction** — when the combined skill prompts approach the model's context budget, the oldest low-priority skill is evicted automatically so the conversation stays responsive.
75
+
76
+ The active stack persists on the conversation row (`conversations.active_skill_ids`), and the `mergeActiveSkillIds` helper keeps updates atomic across concurrent activations. See the [Chat](./chat.md) feature doc for the user-facing flow.
77
+
68
78
  ### Workflow Context Batching
69
79
 
70
80
  In multi-step workflows, context from earlier steps is batched and forwarded to downstream steps. This prevents information loss across the workflow and ensures each step has the full picture of prior results.
@@ -3,10 +3,10 @@ title: "Chat"
3
3
  category: "feature-reference"
4
4
  section: "chat"
5
5
  route: "/chat"
6
- tags: ["chat", "conversation", "ai", "tool-catalog", "mentions", "channels", "bidirectional"]
7
- features: ["chat-data-layer", "chat-engine", "chat-api-routes", "chat-ui-shell", "chat-message-rendering", "chat-input-composer", "bidirectional-channel-chat"]
6
+ tags: ["chat", "conversation", "ai", "tool-catalog", "mentions", "channels", "bidirectional", "skills", "templates", "filters", "saved-searches"]
7
+ features: ["chat-data-layer", "chat-engine", "chat-api-routes", "chat-ui-shell", "chat-message-rendering", "chat-input-composer", "bidirectional-channel-chat", "chat-skill-composition", "chat-composition-ui-v1", "chat-conversation-templates", "chat-filter-namespace", "chat-pinned-saved-searches", "saved-search-polish-v1"]
8
8
  screengrabCount: 4
9
- lastUpdated: "2026-03-31"
9
+ lastUpdated: "2026-04-15"
10
10
  ---
11
11
 
12
12
  # Chat
@@ -18,10 +18,10 @@ The Chat page is your AI-powered command center for everything in your workspace
18
18
  ![Chat tool catalog](../screengrabs/chat-list.png)
19
19
  *Tool catalog with hero heading, category tabs (Explore / Create / Debug / Automate), Smart Picks row, and conversation sidebar*
20
20
 
21
- ![Model selector](../screengrabs/chat-model-selector.png)
21
+ ![Model selector](../screengrabs/chat-model-picker.png)
22
22
  *Model selector dropdown showing Claude and Codex models organized by provider with cost tiers*
23
23
 
24
- ![Create category tab](../screengrabs/chat-create-tab.png)
24
+ ![Create category tab](../screengrabs/chat-actions-tab.png)
25
25
  *Create category selected, showing prompts for spinning up tasks, workflows, and projects*
26
26
 
27
27
  ![Active conversation](../screengrabs/chat-conversation.png)
@@ -61,6 +61,41 @@ Every chat starts a new conversation that is saved automatically. Your conversat
61
61
 
62
62
  When bidirectional chat is enabled on a Slack or Telegram delivery channel, messages sent to Stagent from those platforms create conversations visible in the Chat sidebar. The same chat engine handles both web and channel conversations, including tool access, permission handling, and multi-turn context.
63
63
 
64
+ ### Skill Composition
65
+
66
+ On runtimes that support multiple active skills, you can stack specialized behaviors onto a single conversation. Open the slash (`/`) popover and switch to the **Skills** tab — each skill card has an **+ Add** button. Active skills show a badge, and the header reads "N of M active" so you always know where you stand against the runtime's cap (`maxActiveSkills`).
67
+
68
+ - **Modes** — add a skill in `replace` mode to swap it in, or `add` mode to layer it on top of the current stack.
69
+ - **Conflict heuristic** — if a new skill clashes with one already active (overlapping tool needs, contradictory instructions), a confirmation dialog surfaces the conflict so you can choose which to keep.
70
+ - **Prompt-budget eviction** — when the active skill set approaches the model's context budget, the oldest or lowest-priority skill is evicted automatically and shown in a lightweight toast.
71
+ - **Capability gating** — runtimes that do not support composition (currently gated by `RuntimeFeatures.supportsSkillComposition`) render the Skills tab read-only with a "composition disabled on this runtime" hint.
72
+
73
+ The currently active skills are persisted on the conversation itself (`conversations.active_skill_ids`) so re-opening a conversation restores the exact same stack.
74
+
75
+ ### Conversation Templates
76
+
77
+ Rather than starting every conversation from a blank prompt, you can kick one off from a saved blueprint. Three entry points:
78
+
79
+ - **Empty-state button** — the chat hero shows a "Start from template" button when no conversation is active.
80
+ - **Slash command** — type `/new-from-template` in the composer to open the picker inline.
81
+ - **Command palette** — press `⌘K` and pick the **Templates** group to browse by name.
82
+
83
+ Each template resolves its opening prompt from the blueprint's optional `chatPrompt` field (falling back to the first step's prompt template if `chatPrompt` is not set). Variables in the prompt are filled in at launch so the conversation opens already primed with context.
84
+
85
+ ### Filter Namespace
86
+
87
+ Type `#` in the chat search, the `@` popover, or the Skills popover to filter by namespace. Values can be double-quoted to include spaces — for example, `#scope:"customer support"` matches only entries whose scope equals that phrase. Supported qualifiers include `#scope:`, `#type:`, and surface-specific keys. The same `FilterInput` component powers the `/documents` list page and the `⌘K` palette, so the syntax is identical everywhere.
88
+
89
+ ### Saved Searches
90
+
91
+ Frequently used filter + query combinations can be pinned and reused:
92
+
93
+ - **Save a view** — run any search, then click **Save view** in the footer to name and pin it.
94
+ - **Reuse from the palette** — `⌘K` shows a **Saved** group at the top; pick one to re-apply instantly.
95
+ - **Reuse from mentions** — the `@` popover also surfaces saved searches in a dedicated group for in-composer reuse.
96
+
97
+ Saved searches round-trip via `GET/PUT /api/settings/chat/saved-searches`, and the `cleanFilterInput()` helper strips any mention-trigger residue (`@`, `#`, `/`) so a pinned query stays clean no matter where you saved it from.
98
+
64
99
  ### Streaming Responses
65
100
 
66
101
  Responses stream in token by token with a blinking cursor. Markdown formatting -- headings, lists, code blocks with syntax highlighting, tables, and links -- renders as the text streams in. Code blocks include a copy button and language label.
@@ -15,7 +15,7 @@ Track spend across providers and monitor token consumption with the cost and usa
15
15
 
16
16
  ## Screenshots
17
17
 
18
- ![Cost and usage dashboard with spend breakdown](../screengrabs/cost-usage-list.png)
18
+ ![Cost and usage dashboard with spend breakdown](../screengrabs/costs-list.png)
19
19
  *The cost and usage dashboard showing spend metrics, provider breakdown, and budget pacing indicators.*
20
20
 
21
21
  ![Cost and usage below fold](../screengrabs/cost-usage-below-fold.png)
@@ -4,9 +4,9 @@ category: "feature-reference"
4
4
  section: "documents"
5
5
  route: "/documents"
6
6
  tags: [documents, upload, preprocessing, pdf, office, text-extraction, agent-context]
7
- features: ["document-manager", "file-attachment-data-layer", "document-preprocessing", "agent-document-context", "document-output-generation"]
7
+ features: ["document-manager", "file-attachment-data-layer", "document-preprocessing", "agent-document-context", "document-output-generation", "chat-filter-namespace", "chat-pinned-saved-searches"]
8
8
  screengrabCount: 2
9
- lastUpdated: "2026-03-31"
9
+ lastUpdated: "2026-04-15"
10
10
  ---
11
11
 
12
12
  # Documents
@@ -26,6 +26,9 @@ The Document Library is where you upload, manage, and organize files that agents
26
26
  ### Table and Grid Views
27
27
  Toggle between a table view for dense scanning (file name, type, size, processing status, timestamps) and a grid view with visual cards. Both views support selection for bulk operations.
28
28
 
29
+ ### FilterInput and Saved Searches
30
+ The `/documents` list page is the reference consumer for the shared **FilterInput** component. Type `#type:pdf` or `#scope:"legal review"` to filter by namespace — double-quoted values cleanly handle phrases with spaces. Combine filters with a free-text search, then click **Save view** in the footer to pin the combination as a saved search. Saved searches are available across surfaces (Chat, Tables, Documents) via the `⌘K` palette **Saved** group.
31
+
29
32
  ### Upload Dialog with Drag-and-Drop
30
33
  The upload dialog accepts files via drag-and-drop or file picker. A visual indicator shows supported file types. Multiple files can be uploaded in a single batch.
31
34