crewly 1.15.0 → 1.16.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 (205) hide show
  1. package/README.md +6 -4
  2. package/config/roles/developer/prompt.md +1 -1
  3. package/config/runtime_scripts/runtime-config.json +7 -0
  4. package/config/skills/agent/core/count-json/SKILL.md +61 -0
  5. package/config/skills/agent/core/count-json/execute.sh +52 -0
  6. package/config/skills/agent/core/count-json/execute.test.sh +35 -0
  7. package/config/skills/agent/core/record-prediction/SKILL.md +61 -0
  8. package/config/skills/agent/core/record-prediction/execute.sh +90 -0
  9. package/config/skills/agent/core/record-prediction/execute.test.sh +67 -0
  10. package/config/skills/agent/core/resolve-prediction/SKILL.md +61 -0
  11. package/config/skills/agent/core/resolve-prediction/execute.sh +87 -0
  12. package/config/skills/agent/core/resolve-prediction/execute.test.sh +74 -0
  13. package/config/skills/agent/core/set-focus/SKILL.md +64 -0
  14. package/config/skills/agent/core/set-focus/execute.sh +73 -0
  15. package/config/skills/agent/core/set-focus/execute.test.sh +67 -0
  16. package/config/skills/agent/core/suppress-noise/SKILL.md +59 -0
  17. package/config/skills/agent/core/suppress-noise/execute.sh +68 -0
  18. package/config/skills/agent/core/suppress-noise/execute.test.sh +58 -0
  19. package/dist/backend/backend/src/constants.d.ts +61 -0
  20. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  21. package/dist/backend/backend/src/constants.js +71 -0
  22. package/dist/backend/backend/src/constants.js.map +1 -1
  23. package/dist/backend/backend/src/controllers/agent-self-improvement/agent-self-improvement.controller.d.ts +76 -0
  24. package/dist/backend/backend/src/controllers/agent-self-improvement/agent-self-improvement.controller.d.ts.map +1 -0
  25. package/dist/backend/backend/src/controllers/agent-self-improvement/agent-self-improvement.controller.js +262 -0
  26. package/dist/backend/backend/src/controllers/agent-self-improvement/agent-self-improvement.controller.js.map +1 -0
  27. package/dist/backend/backend/src/controllers/oauth/oauth.routes.d.ts.map +1 -1
  28. package/dist/backend/backend/src/controllers/oauth/oauth.routes.js +31 -0
  29. package/dist/backend/backend/src/controllers/oauth/oauth.routes.js.map +1 -1
  30. package/dist/backend/backend/src/controllers/request-types.d.ts +6 -2
  31. package/dist/backend/backend/src/controllers/request-types.d.ts.map +1 -1
  32. package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
  33. package/dist/backend/backend/src/controllers/team/team.controller.js +4 -0
  34. package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
  35. package/dist/backend/backend/src/index.d.ts +1 -0
  36. package/dist/backend/backend/src/index.d.ts.map +1 -1
  37. package/dist/backend/backend/src/index.js +53 -0
  38. package/dist/backend/backend/src/index.js.map +1 -1
  39. package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
  40. package/dist/backend/backend/src/routes/api.routes.js +6 -0
  41. package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
  42. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +10 -0
  43. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  44. package/dist/backend/backend/src/services/agent/agent-registration.service.js +32 -4
  45. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  46. package/dist/backend/backend/src/services/agent/opencode-runtime.service.d.ts +114 -0
  47. package/dist/backend/backend/src/services/agent/opencode-runtime.service.d.ts.map +1 -0
  48. package/dist/backend/backend/src/services/agent/opencode-runtime.service.js +185 -0
  49. package/dist/backend/backend/src/services/agent/opencode-runtime.service.js.map +1 -0
  50. package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -1
  51. package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js +22 -1
  52. package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
  53. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.d.ts +1 -1
  54. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -1
  55. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js +15 -3
  56. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -1
  57. package/dist/backend/backend/src/services/agent/runtime-service.factory.d.ts.map +1 -1
  58. package/dist/backend/backend/src/services/agent/runtime-service.factory.js +9 -0
  59. package/dist/backend/backend/src/services/agent/runtime-service.factory.js.map +1 -1
  60. package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts +23 -0
  61. package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -1
  62. package/dist/backend/backend/src/services/ai/prompt-builder.service.js +45 -0
  63. package/dist/backend/backend/src/services/ai/prompt-builder.service.js.map +1 -1
  64. package/dist/backend/backend/src/services/ai/prompt-modules/memory-reference.module.d.ts +43 -3
  65. package/dist/backend/backend/src/services/ai/prompt-modules/memory-reference.module.d.ts.map +1 -1
  66. package/dist/backend/backend/src/services/ai/prompt-modules/memory-reference.module.js +85 -4
  67. package/dist/backend/backend/src/services/ai/prompt-modules/memory-reference.module.js.map +1 -1
  68. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts +2 -0
  69. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts.map +1 -1
  70. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-module.interface.js.map +1 -1
  71. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
  72. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js +6 -0
  73. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
  74. package/dist/backend/backend/src/services/ai/self-improvement/agent-memory-provider.d.ts +45 -0
  75. package/dist/backend/backend/src/services/ai/self-improvement/agent-memory-provider.d.ts.map +1 -0
  76. package/dist/backend/backend/src/services/ai/self-improvement/agent-memory-provider.js +59 -0
  77. package/dist/backend/backend/src/services/ai/self-improvement/agent-memory-provider.js.map +1 -0
  78. package/dist/backend/backend/src/services/ai/self-improvement/consolidation-scheduler.service.d.ts +137 -0
  79. package/dist/backend/backend/src/services/ai/self-improvement/consolidation-scheduler.service.d.ts.map +1 -0
  80. package/dist/backend/backend/src/services/ai/self-improvement/consolidation-scheduler.service.js +216 -0
  81. package/dist/backend/backend/src/services/ai/self-improvement/consolidation-scheduler.service.js.map +1 -0
  82. package/dist/backend/backend/src/services/ai/self-improvement/prediction-calibration.service.d.ts +4 -1
  83. package/dist/backend/backend/src/services/ai/self-improvement/prediction-calibration.service.d.ts.map +1 -1
  84. package/dist/backend/backend/src/services/ai/self-improvement/prediction-calibration.service.js +3 -1
  85. package/dist/backend/backend/src/services/ai/self-improvement/prediction-calibration.service.js.map +1 -1
  86. package/dist/backend/backend/src/services/mcp-tool-definitions.d.ts +1 -1
  87. package/dist/backend/backend/src/services/mcp-tool-definitions.js +1 -1
  88. package/dist/backend/backend/src/services/mcp-tool-definitions.js.map +1 -1
  89. package/dist/backend/backend/src/services/runtime-adapter.d.ts +10 -1
  90. package/dist/backend/backend/src/services/runtime-adapter.d.ts.map +1 -1
  91. package/dist/backend/backend/src/services/runtime-adapter.js +12 -1
  92. package/dist/backend/backend/src/services/runtime-adapter.js.map +1 -1
  93. package/dist/backend/backend/src/services/settings/settings.service.d.ts.map +1 -1
  94. package/dist/backend/backend/src/services/settings/settings.service.js +1 -0
  95. package/dist/backend/backend/src/services/settings/settings.service.js.map +1 -1
  96. package/dist/backend/backend/src/services/v3/fallback-trigger-cleanup.subscriber.d.ts +78 -0
  97. package/dist/backend/backend/src/services/v3/fallback-trigger-cleanup.subscriber.d.ts.map +1 -0
  98. package/dist/backend/backend/src/services/v3/fallback-trigger-cleanup.subscriber.js +129 -0
  99. package/dist/backend/backend/src/services/v3/fallback-trigger-cleanup.subscriber.js.map +1 -0
  100. package/dist/backend/backend/src/services/v3/kr-skill-measurer.service.d.ts +117 -0
  101. package/dist/backend/backend/src/services/v3/kr-skill-measurer.service.d.ts.map +1 -0
  102. package/dist/backend/backend/src/services/v3/kr-skill-measurer.service.js +214 -0
  103. package/dist/backend/backend/src/services/v3/kr-skill-measurer.service.js.map +1 -0
  104. package/dist/backend/backend/src/services/v3/mission-reminder.service.d.ts +2 -0
  105. package/dist/backend/backend/src/services/v3/mission-reminder.service.d.ts.map +1 -1
  106. package/dist/backend/backend/src/services/v3/mission-reminder.service.js +16 -0
  107. package/dist/backend/backend/src/services/v3/mission-reminder.service.js.map +1 -1
  108. package/dist/backend/backend/src/types/index.d.ts +11 -1
  109. package/dist/backend/backend/src/types/index.d.ts.map +1 -1
  110. package/dist/backend/backend/src/types/index.js.map +1 -1
  111. package/dist/backend/backend/src/types/settings.types.d.ts +1 -1
  112. package/dist/backend/backend/src/types/settings.types.d.ts.map +1 -1
  113. package/dist/backend/backend/src/types/settings.types.js +7 -0
  114. package/dist/backend/backend/src/types/settings.types.js.map +1 -1
  115. package/dist/backend/backend/src/types/team-template.types.d.ts +2 -2
  116. package/dist/backend/backend/src/types/team-template.types.d.ts.map +1 -1
  117. package/dist/backend/backend/src/types/team-template.types.js +1 -1
  118. package/dist/backend/backend/src/types/team-template.types.js.map +1 -1
  119. package/dist/backend/backend/src/utils/terminal-string-ops.d.ts +2 -0
  120. package/dist/backend/backend/src/utils/terminal-string-ops.d.ts.map +1 -1
  121. package/dist/backend/backend/src/utils/terminal-string-ops.js +14 -0
  122. package/dist/backend/backend/src/utils/terminal-string-ops.js.map +1 -1
  123. package/dist/backend/build-info.json +2 -2
  124. package/dist/cli/backend/src/constants.d.ts +61 -0
  125. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  126. package/dist/cli/backend/src/constants.js +71 -0
  127. package/dist/cli/backend/src/constants.js.map +1 -1
  128. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts +10 -0
  129. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  130. package/dist/cli/backend/src/services/agent/agent-registration.service.js +32 -4
  131. package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
  132. package/dist/cli/backend/src/services/agent/opencode-runtime.service.d.ts +114 -0
  133. package/dist/cli/backend/src/services/agent/opencode-runtime.service.d.ts.map +1 -0
  134. package/dist/cli/backend/src/services/agent/opencode-runtime.service.js +185 -0
  135. package/dist/cli/backend/src/services/agent/opencode-runtime.service.js.map +1 -0
  136. package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -1
  137. package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js +22 -1
  138. package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
  139. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts +1 -1
  140. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -1
  141. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js +15 -3
  142. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -1
  143. package/dist/cli/backend/src/services/agent/runtime-service.factory.d.ts.map +1 -1
  144. package/dist/cli/backend/src/services/agent/runtime-service.factory.js +9 -0
  145. package/dist/cli/backend/src/services/agent/runtime-service.factory.js.map +1 -1
  146. package/dist/cli/backend/src/services/ai/prompt-builder.service.d.ts +23 -0
  147. package/dist/cli/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -1
  148. package/dist/cli/backend/src/services/ai/prompt-builder.service.js +45 -0
  149. package/dist/cli/backend/src/services/ai/prompt-builder.service.js.map +1 -1
  150. package/dist/cli/backend/src/services/ai/prompt-modules/memory-reference.module.d.ts +43 -3
  151. package/dist/cli/backend/src/services/ai/prompt-modules/memory-reference.module.d.ts.map +1 -1
  152. package/dist/cli/backend/src/services/ai/prompt-modules/memory-reference.module.js +85 -4
  153. package/dist/cli/backend/src/services/ai/prompt-modules/memory-reference.module.js.map +1 -1
  154. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts +2 -0
  155. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts.map +1 -1
  156. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.js.map +1 -1
  157. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
  158. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js +6 -0
  159. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
  160. package/dist/cli/backend/src/services/ai/self-improvement/agent-memory-provider.d.ts +45 -0
  161. package/dist/cli/backend/src/services/ai/self-improvement/agent-memory-provider.d.ts.map +1 -0
  162. package/dist/cli/backend/src/services/ai/self-improvement/agent-memory-provider.js +59 -0
  163. package/dist/cli/backend/src/services/ai/self-improvement/agent-memory-provider.js.map +1 -0
  164. package/dist/cli/backend/src/services/ai/self-improvement/attention.service.d.ts +74 -0
  165. package/dist/cli/backend/src/services/ai/self-improvement/attention.service.d.ts.map +1 -0
  166. package/dist/cli/backend/src/services/ai/self-improvement/attention.service.js +132 -0
  167. package/dist/cli/backend/src/services/ai/self-improvement/attention.service.js.map +1 -0
  168. package/dist/cli/backend/src/services/ai/self-improvement/memory-consolidation.service.d.ts +107 -0
  169. package/dist/cli/backend/src/services/ai/self-improvement/memory-consolidation.service.d.ts.map +1 -0
  170. package/dist/cli/backend/src/services/ai/self-improvement/memory-consolidation.service.js +183 -0
  171. package/dist/cli/backend/src/services/ai/self-improvement/memory-consolidation.service.js.map +1 -0
  172. package/dist/cli/backend/src/services/ai/self-improvement/prediction-calibration.service.d.ts +100 -0
  173. package/dist/cli/backend/src/services/ai/self-improvement/prediction-calibration.service.d.ts.map +1 -0
  174. package/dist/cli/backend/src/services/ai/self-improvement/prediction-calibration.service.js +130 -0
  175. package/dist/cli/backend/src/services/ai/self-improvement/prediction-calibration.service.js.map +1 -0
  176. package/dist/cli/backend/src/services/mcp-tool-definitions.d.ts +1 -1
  177. package/dist/cli/backend/src/services/mcp-tool-definitions.js +1 -1
  178. package/dist/cli/backend/src/services/mcp-tool-definitions.js.map +1 -1
  179. package/dist/cli/backend/src/services/settings/settings.service.d.ts.map +1 -1
  180. package/dist/cli/backend/src/services/settings/settings.service.js +1 -0
  181. package/dist/cli/backend/src/services/settings/settings.service.js.map +1 -1
  182. package/dist/cli/backend/src/types/index.d.ts +11 -1
  183. package/dist/cli/backend/src/types/index.d.ts.map +1 -1
  184. package/dist/cli/backend/src/types/index.js.map +1 -1
  185. package/dist/cli/backend/src/types/settings.types.d.ts +1 -1
  186. package/dist/cli/backend/src/types/settings.types.d.ts.map +1 -1
  187. package/dist/cli/backend/src/types/settings.types.js +7 -0
  188. package/dist/cli/backend/src/types/settings.types.js.map +1 -1
  189. package/dist/cli/backend/src/types/team-template.types.d.ts +2 -2
  190. package/dist/cli/backend/src/types/team-template.types.d.ts.map +1 -1
  191. package/dist/cli/backend/src/types/team-template.types.js +1 -1
  192. package/dist/cli/backend/src/types/team-template.types.js.map +1 -1
  193. package/dist/cli/backend/src/utils/terminal-string-ops.d.ts +2 -0
  194. package/dist/cli/backend/src/utils/terminal-string-ops.d.ts.map +1 -1
  195. package/dist/cli/backend/src/utils/terminal-string-ops.js +14 -0
  196. package/dist/cli/backend/src/utils/terminal-string-ops.js.map +1 -1
  197. package/dist/cli/cli/src/commands/onboard.d.ts +2 -2
  198. package/dist/cli/cli/src/commands/onboard.d.ts.map +1 -1
  199. package/dist/cli/cli/src/commands/onboard.js +15 -7
  200. package/dist/cli/cli/src/commands/onboard.js.map +1 -1
  201. package/frontend/dist/assets/{index-203224f9.js → index-019817e2.js} +272 -272
  202. package/frontend/dist/assets/index-a56613e7.css +42 -0
  203. package/frontend/dist/index.html +2 -2
  204. package/package.json +1 -1
  205. package/frontend/dist/assets/index-dcaf6c88.css +0 -42
package/README.md CHANGED
@@ -7,12 +7,12 @@
7
7
 
8
8
  **Website:** [crewlyai.com](https://crewlyai.com/)
9
9
 
10
- Crewly is an open-source multi-agent orchestration platform that coordinates AI coding agents (Claude Code, Gemini CLI, Codex) to work together as a team. It provides a web dashboard for real-time monitoring, task management, and team coordination — all running locally on your machine.
10
+ Crewly is an open-source multi-agent orchestration platform that coordinates AI coding agents (Claude Code, Gemini CLI, Codex, OpenCode) to work together as a team. It provides a web dashboard for real-time monitoring, task management, and team coordination — all running locally on your machine.
11
11
 
12
12
  ## Features
13
13
 
14
14
  - **Multi-agent teams** — Create teams with different roles (developer, QA, PM, orchestrator) and watch them collaborate
15
- - **Multi-runtime support** — Use Claude Code, Gemini CLI, or OpenAI Codex — mix and match per agent
15
+ - **Multi-runtime support** — Use Claude Code, Gemini CLI, OpenAI Codex, or OpenCode — mix and match per agent
16
16
  - **Real-time dashboard** — Monitor all agents through live terminal streams, task boards, and activity feeds
17
17
  - **Skill system** — Agents coordinate through bash skills (report status, delegate tasks, manage memory)
18
18
  - **Agent memory** — Persistent knowledge that agents build and share across sessions
@@ -49,8 +49,9 @@ The `init` command walks you through provider selection, installs agent skills,
49
49
  | **Claude Code** (default) | `npm install -g @anthropic-ai/claude-code` | `claude --version` |
50
50
  | **Gemini CLI** | `npm install -g @google/gemini-cli` | `gemini --version` |
51
51
  | **Codex (OpenAI)** | `npm install -g @openai/codex` | `codex --version` |
52
+ | **OpenCode** | `npm install -g opencode-ai` | `opencode --version` |
52
53
 
53
- **API keys:** Gemini CLI requires `GEMINI_API_KEY`. Codex requires an OpenAI API key. Claude Code authenticates through its own login flow.
54
+ **API keys:** Gemini CLI requires `GEMINI_API_KEY`. Codex requires an OpenAI API key. Claude Code authenticates through its own login flow. OpenCode uses whichever provider you connect via `opencode auth login` (or the `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `GEMINI_API_KEY` env vars Crewly already exports to agent sessions).
54
55
 
55
56
  ## Architecture
56
57
 
@@ -98,7 +99,8 @@ Storage: ~/.crewly/ (global) + project/.crewly/ (per-project)
98
99
  |---------|-----------------|-------|
99
100
  | **Claude Code** | `claude --dangerously-skip-permissions` | Default runtime |
100
101
  | **Gemini CLI** | `gemini --yolo` | Requires `GEMINI_API_KEY` |
101
- | **Codex (OpenAI)** | `codex --full-auto` | Requires OpenAI API key |
102
+ | **Codex (OpenAI)** | `codex -a never -s danger-full-access` | Requires OpenAI API key |
103
+ | **OpenCode** | `opencode --auto` | Any provider/model (`-m provider/model`); reads `AGENTS.md`; auth via `opencode auth login` |
102
104
 
103
105
  You can change the default runtime or customize launch commands in **Settings**.
104
106
 
@@ -273,7 +273,7 @@ When you are **idle and have no assigned tasks**, proactively check the Task Poo
273
273
 
274
274
  Call the `poll-tasks` skill to query and claim work from the shared Task Pool:
275
275
  ```bash
276
- bash {{AGENT_SKILLS_PATH}}/core/poll-tasks/execute.sh '{"sessionName":"{{SESSION_NAME}}","role":"{{ROLE}}","skills":["typescript","react"],"projectPath":"{{PROJECT_PATH}}"}'
276
+ bash {{AGENT_SKILLS_PATH}}/core/poll-tasks/execute.sh '{"sessionName":"{{SESSION_NAME}}","role":"{{ROLE}}","skills":{{MEMBER_SKILLS_JSON}},"projectPath":"{{PROJECT_PATH}}"}'
277
277
  ```
278
278
 
279
279
  ### Parameters
@@ -21,6 +21,13 @@
21
21
  "timeout": 90000,
22
22
  "description": "OpenAI's Codex CLI for advanced code understanding"
23
23
  },
24
+ "opencode-cli": {
25
+ "displayName": "OpenCode",
26
+ "initScript": "",
27
+ "welcomeMessage": "Ask anything",
28
+ "timeout": 90000,
29
+ "description": "OpenCode open-source TUI coding agent (opencode.ai), any provider/model"
30
+ },
24
31
  "crewly-agent": {
25
32
  "displayName": "Crewly Agent",
26
33
  "initScript": "",
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: Count JSON
3
+ description: Run a command that prints JSON and count the entries matching a field=value filter. Built for skill_output Key Results (e.g. "tickets in review") so a KR can be measured from any board or API that speaks JSON.
4
+ version: 1.0.0
5
+ category: measurement
6
+ skillType: claude-skill
7
+ assignableRoles:
8
+ - orchestrator
9
+ - team-leader
10
+ - developer
11
+ - devops
12
+ - operations
13
+ - ops
14
+ triggers:
15
+ - count json
16
+ - measure kr
17
+ tags:
18
+ - okr
19
+ - measurement
20
+ - json
21
+ execution:
22
+ type: script
23
+ script:
24
+ file: execute.sh
25
+ interpreter: bash
26
+ timeoutMs: 60000
27
+ ---
28
+
29
+ # Count JSON
30
+
31
+ Runs a command, reads the JSON it prints (an array, or an object holding an
32
+ array under `items` / `tickets` / `data`), applies an optional `field=value`
33
+ filter, and prints `{"count": N, "total": M, "filter": "..."}`.
34
+
35
+ Made for `measurementSource: "skill_output"` Key Results:
36
+
37
+ ```json
38
+ { "measurementConfig": { "skill": "count-json",
39
+ "args": { "command": "cd /opt/app/web && make tickets TICKET_ARGS=--json",
40
+ "field": "status", "value": "review" },
41
+ "jsonPath": ".count" } }
42
+ ```
43
+
44
+ ## Parameters
45
+
46
+ | Name | Required | Meaning |
47
+ |---|---|---|
48
+ | `command` | yes | Shell command whose stdout is JSON (or a `file` path instead) |
49
+ | `file` | no | Read JSON from this file instead of running a command |
50
+ | `field` | no | Top-level field to filter on |
51
+ | `value` | no | Value that `field` must equal (string compare) |
52
+ | `arrayPath` | no | jq path to the array when it is nested (default: auto-detect) |
53
+
54
+ ## Output
55
+
56
+ ```json
57
+ {"count": 6, "total": 21, "filter": "status=review"}
58
+ ```
59
+
60
+ The command runs with a 50 s timeout; a non-JSON result exits 1 with an error
61
+ object on stderr.
@@ -0,0 +1,52 @@
1
+ #!/bin/bash
2
+ # count-json — run a command (or read a file) that yields JSON, count entries
3
+ # matching field=value. Output: {"count":N,"total":M,"filter":"field=value"}
4
+ #
5
+ # Usage: execute.sh '{"command":"...","field":"status","value":"review"}'
6
+ # execute.sh '{"file":"/tmp/board.json","field":"status","value":"open"}'
7
+ set -uo pipefail
8
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
+ source "${SCRIPT_DIR}/../../_common/lib.sh"
10
+
11
+ INPUT="${1:-}"
12
+ [ -z "$INPUT" ] && error_exit "Usage: execute.sh '{\"command\":\"...\",\"field\":\"status\",\"value\":\"review\"}'"
13
+
14
+ COMMAND=$(printf '%s' "$INPUT" | jq -r '.command // empty')
15
+ FILE=$(printf '%s' "$INPUT" | jq -r '.file // empty')
16
+ FIELD=$(printf '%s' "$INPUT" | jq -r '.field // empty')
17
+ VALUE=$(printf '%s' "$INPUT" | jq -r '.value // empty')
18
+ ARRAY_PATH=$(printf '%s' "$INPUT" | jq -r '.arrayPath // empty')
19
+ TIMEOUT_S="${COUNT_JSON_TIMEOUT_S:-50}"
20
+
21
+ [ -z "$COMMAND" ] && [ -z "$FILE" ] && error_exit "command or file is required"
22
+
23
+ if [ -n "$FILE" ]; then
24
+ [ -f "$FILE" ] || error_exit "file not found: $FILE"
25
+ RAW=$(cat "$FILE")
26
+ else
27
+ if command -v timeout >/dev/null 2>&1; then
28
+ RAW=$(timeout "$TIMEOUT_S" bash -c "$COMMAND" 2>/dev/null)
29
+ else
30
+ RAW=$(bash -c "$COMMAND" 2>/dev/null)
31
+ fi
32
+ [ $? -ne 0 ] && [ -z "$RAW" ] && error_exit "command failed or produced no output"
33
+ fi
34
+
35
+ # Skip any non-JSON preamble (progress lines, banners).
36
+ JSON=$(printf '%s' "$RAW" | awk 'found||/^[[{]/{found=1; print}')
37
+ [ -z "$JSON" ] && error_exit "no JSON found in output"
38
+
39
+ if [ -n "$ARRAY_PATH" ]; then
40
+ SELECT="$ARRAY_PATH"
41
+ else
42
+ SELECT='if type=="array" then . elif (.items|type)=="array" then .items elif (.tickets|type)=="array" then .tickets elif (.data|type)=="array" then .data else [] end'
43
+ fi
44
+
45
+ if [ -n "$FIELD" ]; then
46
+ printf '%s' "$JSON" | jq -c --arg f "$FIELD" --arg v "$VALUE" \
47
+ "($SELECT) as \$arr | {count: (\$arr | map(select((.[\$f] // \"\" | tostring) == \$v)) | length), total: (\$arr | length), filter: (\$f + \"=\" + \$v)}" \
48
+ || error_exit "output is not valid JSON"
49
+ else
50
+ printf '%s' "$JSON" | jq -c "($SELECT) as \$arr | {count: (\$arr | length), total: (\$arr | length), filter: \"\"}" \
51
+ || error_exit "output is not valid JSON"
52
+ fi
@@ -0,0 +1,35 @@
1
+ #!/bin/bash
2
+ # Tests for count-json — run with: bash execute.test.sh
3
+ set -u
4
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ EXEC="$HERE/execute.sh"
6
+ PASS=0; FAIL=0
7
+ check() {
8
+ local name="$1"; local got="$2"; local want="$3"
9
+ if [ "$got" = "$want" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $name"; echo " want: $want"; echo " got: $got"; fi
10
+ }
11
+ run() { bash "$EXEC" "$1" 2>/dev/null; }
12
+ run_err() { bash "$EXEC" "$1" 2>&1 >/dev/null | jq -r '.error' 2>/dev/null; }
13
+
14
+ TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT
15
+ printf '%s' '[{"ticketId":"T1","status":"open"},{"ticketId":"T2","status":"review"},{"ticketId":"T3","status":"review"},{"ticketId":"T4","status":"blocked"}]' > "$TMP/board.json"
16
+ printf '%s' 'fetching...
17
+ {"items":[{"s":"a"},{"s":"b"}]}' > "$TMP/nested.txt"
18
+
19
+ ARGS=$(jq -cn --arg f "$TMP/board.json" '{file:$f, field:"status", value:"review"}')
20
+ check "filter by field=value" "$(run "$ARGS")" '{"count":2,"total":4,"filter":"status=review"}'
21
+
22
+ ARGS=$(jq -cn --arg f "$TMP/board.json" '{file:$f}')
23
+ check "no filter counts all" "$(run "$ARGS")" '{"count":4,"total":4,"filter":""}'
24
+
25
+ ARGS=$(jq -cn --arg c "cat $TMP/nested.txt" '{command:$c, field:"s", value:"b"}')
26
+ check "command with preamble and nested items" "$(run "$ARGS")" '{"count":1,"total":2,"filter":"s=b"}'
27
+
28
+ ARGS=$(jq -cn --arg f "$TMP/board.json" '{file:$f, arrayPath:".", field:"status", value:"open"}')
29
+ check "explicit arrayPath" "$(run "$ARGS")" '{"count":1,"total":4,"filter":"status=open"}'
30
+
31
+ check "non-JSON errors" "$(run_err '{"command":"echo not json"}')" "no JSON found in output"
32
+ check "missing input errors" "$(run_err '{}')" "command or file is required"
33
+
34
+ echo "=== Results: $PASS passed, $FAIL failed ==="
35
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: Record Prediction
3
+ description: Record a prediction with a confidence level so your calibration can be measured once it resolves.
4
+ version: 1.0.0
5
+ category: memory
6
+ skillType: claude-skill
7
+ assignableRoles:
8
+ - developer
9
+ - qa
10
+ - tpm
11
+ - designer
12
+ - frontend-developer
13
+ - backend-developer
14
+ - fullstack-dev
15
+ - qa-engineer
16
+ - product-manager
17
+ - architect
18
+ - generalist
19
+ - sales
20
+ - support
21
+ - orchestrator
22
+ triggers:
23
+ - record prediction
24
+ - I predict
25
+ - confidence
26
+ - estimate
27
+ tags:
28
+ - memory
29
+ - calibration
30
+ - self-improvement
31
+ execution:
32
+ type: script
33
+ script:
34
+ file: execute.sh
35
+ interpreter: bash
36
+ timeoutMs: 15000
37
+ ---
38
+
39
+ # Record Prediction
40
+
41
+ Write down a falsifiable prediction ("this PR lands today", "the flaky test is a race in the mock") with a confidence between 0 and 1. Later, close it with `resolve-prediction`. Your calibration score (how well confidence tracks reality) is shown in your prompt once predictions resolve, with guidance when you are over- or under-confident.
42
+
43
+ ## Parameters
44
+
45
+ | Flag | JSON Field | Required | Description |
46
+ |------|-----------|----------|-------------|
47
+ | `--statement` / `-p` | `statement` | Yes | What you predict will happen |
48
+ | `--confidence` / `-c` | `confidence` | Yes | 0–1 (e.g. `0.7`) |
49
+ | `--resolve-by` | `resolveBy` | No | ISO date by which it should be resolved |
50
+ | `--session` / `-s` | `sessionName` | No | Your session name — defaults to `$CREWLY_SESSION_NAME` |
51
+
52
+ ## Examples
53
+
54
+ ```bash
55
+ bash execute.sh --statement "checkout PR merges before Friday" --confidence 0.7 --resolve-by 2026-10-03
56
+ bash execute.sh '{"statement":"checkout PR merges before Friday","confidence":0.7}'
57
+ ```
58
+
59
+ ## Output
60
+
61
+ `{ "success": true, "id": "pred-...", "prediction": {...} }` — keep the `id`; you need it to resolve.
@@ -0,0 +1,90 @@
1
+ #!/bin/bash
2
+ # =============================================================================
3
+ # record-prediction — Record a prediction with a confidence level
4
+ #
5
+ # Backed by POST /api/agents/:sessionName/self-improvement/predictions.
6
+ #
7
+ # Usage:
8
+ # bash execute.sh --statement "PR lands today" --confidence 0.7 [--resolve-by 2026-10-01] [--session crewly-dev-1]
9
+ # bash execute.sh '{"statement":"PR lands today","confidence":0.7,"resolveBy":"2026-10-01"}'
10
+ # =============================================================================
11
+ set -euo pipefail
12
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13
+ source "${SCRIPT_DIR}/../../_common/lib.sh"
14
+
15
+ print_usage() {
16
+ cat <<'EOF_USAGE'
17
+ Usage:
18
+ bash execute.sh --statement "PR lands today" --confidence 0.7 [--resolve-by 2026-10-01] [--session crewly-dev-1]
19
+ bash execute.sh '{"statement":"PR lands today","confidence":0.7}'
20
+
21
+ Options:
22
+ --statement | -p What you predict (required)
23
+ --confidence | -c Confidence 0-1 (required)
24
+ --resolve-by ISO date the prediction should be resolved by (optional)
25
+ --session | -s Session name (defaults to $CREWLY_SESSION_NAME)
26
+ --help | -h Show this help
27
+ EOF_USAGE
28
+ }
29
+
30
+ INPUT_JSON=""
31
+ SESSION_NAME=""
32
+ STATEMENT=""
33
+ CONFIDENCE=""
34
+ RESOLVE_BY=""
35
+
36
+ if [[ $# -gt 0 && ${1:0:1} == '{' ]]; then
37
+ INPUT_JSON="$1"
38
+ shift || true
39
+ fi
40
+
41
+ while [[ $# -gt 0 ]]; do
42
+ case "$1" in
43
+ --statement|-p)
44
+ [ $# -ge 2 ] || error_exit "--statement requires a value"
45
+ STATEMENT="$2"; shift 2 ;;
46
+ --confidence|-c)
47
+ [ $# -ge 2 ] || error_exit "--confidence requires a value"
48
+ CONFIDENCE="$2"; shift 2 ;;
49
+ --resolve-by)
50
+ [ $# -ge 2 ] || error_exit "--resolve-by requires a value"
51
+ RESOLVE_BY="$2"; shift 2 ;;
52
+ --session|-s)
53
+ [ $# -ge 2 ] || error_exit "--session requires a value"
54
+ SESSION_NAME="$2"; shift 2 ;;
55
+ --help|-h) print_usage; exit 0 ;;
56
+ *) error_exit "Unknown option: $1" ;;
57
+ esac
58
+ done
59
+
60
+ if [ -n "$INPUT_JSON" ]; then
61
+ INPUT=$(read_json_input "$INPUT_JSON")
62
+ [ -z "$SESSION_NAME" ] && SESSION_NAME=$(printf '%s' "$INPUT" | jq -r '.sessionName // .agentId // empty')
63
+ [ -z "$STATEMENT" ] && STATEMENT=$(printf '%s' "$INPUT" | jq -r '.statement // .prediction // empty')
64
+ [ -z "$CONFIDENCE" ] && CONFIDENCE=$(printf '%s' "$INPUT" | jq -r 'if .confidence == null then empty else (.confidence | tostring) end')
65
+ [ -z "$RESOLVE_BY" ] && RESOLVE_BY=$(printf '%s' "$INPUT" | jq -r '.resolveBy // empty')
66
+ fi
67
+
68
+ [ -z "$SESSION_NAME" ] && SESSION_NAME="${CREWLY_SESSION_NAME:-}"
69
+ require_param "sessionName (--session or CREWLY_SESSION_NAME)" "$SESSION_NAME"
70
+ require_param "statement (--statement)" "$STATEMENT"
71
+ require_param "confidence (--confidence)" "$CONFIDENCE"
72
+
73
+ # Validate locally so a typo fails fast with a readable message.
74
+ if ! printf '%s' "$CONFIDENCE" | grep -Eq '^(0(\.[0-9]+)?|1(\.0+)?)$'; then
75
+ error_exit "confidence must be a number between 0 and 1 (got: $CONFIDENCE)"
76
+ fi
77
+
78
+ if [ -n "$RESOLVE_BY" ]; then
79
+ BODY=$(jq -cn --arg s "$STATEMENT" --argjson c "$CONFIDENCE" --arg r "$RESOLVE_BY" '{statement: $s, confidence: $c, resolveBy: $r}')
80
+ else
81
+ BODY=$(jq -cn --arg s "$STATEMENT" --argjson c "$CONFIDENCE" '{statement: $s, confidence: $c}')
82
+ fi
83
+
84
+ RESPONSE=$(api_call POST "/agents/${SESSION_NAME}/self-improvement/predictions" "$BODY" 2>&1) || {
85
+ ERROR_MSG=$(printf '%s' "$RESPONSE" | jq -r '.details.error // .details // .error // "Unknown error"' 2>/dev/null || echo "$RESPONSE")
86
+ jq -n --arg reason "$ERROR_MSG" '{success: false, reason: $reason}'
87
+ exit 1
88
+ }
89
+
90
+ printf '%s' "$RESPONSE" | jq -c '{success: (.success // false), id: (.data.prediction.id // null), prediction: (.data.prediction // null)}'
@@ -0,0 +1,67 @@
1
+ #!/bin/bash
2
+ # Tests for record-prediction — run with: bash execute.test.sh
3
+ # Spins up a python HTTP stub as the backend, asserts the request path/body
4
+ # the skill sends and the JSON it prints. Exit 0 on pass.
5
+ set -u
6
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ EXEC="$HERE/execute.sh"
8
+ PASS=0; FAIL=0
9
+ check() {
10
+ local name="$1"; local got="$2"; local want="$3"
11
+ if [ "$got" = "$want" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $name"; echo " want: $want"; echo " got: $got"; fi
12
+ }
13
+
14
+ PORT=18793
15
+ STUB_LOG="$(mktemp)"; export STUB_LOG; export STUB_PORT="$PORT"
16
+ python3 -u <<'PY' >/dev/null 2>&1 &
17
+ from http.server import BaseHTTPRequestHandler, HTTPServer
18
+ import json, os
19
+ LOG = os.environ['STUB_LOG']; PORT = int(os.environ['STUB_PORT'])
20
+ class H(BaseHTTPRequestHandler):
21
+ def do_POST(self):
22
+ n = int(self.headers.get('content-length', '0')); body = self.rfile.read(n).decode() if n else ''
23
+ data = json.loads(body or '{}')
24
+ open(LOG, 'w').write(json.dumps({'path': self.path, 'body': data}))
25
+ if data.get('resolveBy') == 'soon':
26
+ self.send_response(400); self.send_header('Content-Type', 'application/json'); self.end_headers()
27
+ self.wfile.write(b'{"success":false,"error":"resolveBy must be an ISO date string"}'); return
28
+ pred = {'id': 'pred-1-abc', 'prediction': data.get('statement'), 'confidence': data.get('confidence'), 'madeAt': '2026-09-18'}
29
+ if 'resolveBy' in data: pred['resolveBy'] = data['resolveBy']
30
+ self.send_response(201); self.send_header('Content-Type', 'application/json'); self.end_headers()
31
+ self.wfile.write(json.dumps({'success': True, 'data': {'prediction': pred}}).encode())
32
+ def log_message(self, *a, **k): pass
33
+ HTTPServer(('127.0.0.1', PORT), H).serve_forever()
34
+ PY
35
+ STUB_PID=$!
36
+ disown "$STUB_PID" 2>/dev/null || true
37
+ trap 'kill "$STUB_PID" >/dev/null 2>&1; rm -f "$STUB_LOG"' EXIT
38
+ for i in $(seq 1 30); do curl -s -o /dev/null -m 0.2 "http://127.0.0.1:${PORT}/" 2>/dev/null && break; sleep 0.1; done
39
+
40
+ run() { CREWLY_API_URL="http://127.0.0.1:${PORT}" CREWLY_SESSION_NAME="crewly-dev-1" bash "$EXEC" "$@" 2>/dev/null; }
41
+ run_err() { CREWLY_API_URL="http://127.0.0.1:${PORT}" CREWLY_SESSION_NAME="" bash "$EXEC" "$@" 2>&1 >/dev/null | jq -r '.error' 2>/dev/null; }
42
+
43
+ OUT=$(run --statement "PR lands today" --confidence 0.7 --resolve-by 2026-10-01)
44
+ check "flags: output id" "$(printf '%s' "$OUT" | jq -r .id)" "pred-1-abc"
45
+ check "flags: output success" "$(printf '%s' "$OUT" | jq -r .success)" "true"
46
+ check "flags: path" "$(jq -r .path "$STUB_LOG")" "/api/agents/crewly-dev-1/self-improvement/predictions"
47
+ check "flags: body (confidence is numeric, resolveBy present)" "$(jq -c .body "$STUB_LOG")" '{"statement":"PR lands today","confidence":0.7,"resolveBy":"2026-10-01"}'
48
+
49
+ run '{"statement":"no deadline","confidence":1,"sessionName":"crewly-qa-9"}' >/dev/null
50
+ check "json: body omits resolveBy when absent" "$(jq -c .body "$STUB_LOG")" '{"statement":"no deadline","confidence":1}'
51
+ check "json: explicit session in path" "$(jq -r .path "$STUB_LOG")" "/api/agents/crewly-qa-9/self-improvement/predictions"
52
+
53
+ run '{"prediction":"legacy field name","confidence":"0.25"}' >/dev/null
54
+ check "json: accepts legacy 'prediction' key and string confidence" "$(jq -c .body "$STUB_LOG")" '{"statement":"legacy field name","confidence":0.25}'
55
+
56
+ OUT=$(CREWLY_API_URL="http://127.0.0.1:${PORT}" CREWLY_SESSION_NAME="crewly-dev-1" bash "$EXEC" --statement x --confidence 0.5 --resolve-by soon 2>/dev/null); RC=$?
57
+ check "backend 400: exit code" "$RC" "1"
58
+ check "backend 400: reason" "$(printf '%s' "$OUT" | jq -r .reason)" "resolveBy must be an ISO date string"
59
+
60
+ check "confidence > 1 rejected locally" "$(run_err --session s --statement x --confidence 1.5)" "confidence must be a number between 0 and 1 (got: 1.5)"
61
+ check "non-numeric confidence rejected locally" "$(run_err --session s --statement x --confidence abc)" "confidence must be a number between 0 and 1 (got: abc)"
62
+ check "missing statement errors" "$(run_err --session s --confidence 0.5)" "Missing required parameter: statement (--statement)"
63
+ check "missing confidence errors" "$(run_err --session s --statement x)" "Missing required parameter: confidence (--confidence)"
64
+ check "missing session errors" "$(run_err --statement x --confidence 0.5)" "Missing required parameter: sessionName (--session or CREWLY_SESSION_NAME)"
65
+
66
+ echo "=== Results: $PASS passed, $FAIL failed ==="
67
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: Resolve Prediction
3
+ description: Close a recorded prediction with what actually happened so your calibration score updates.
4
+ version: 1.0.0
5
+ category: memory
6
+ skillType: claude-skill
7
+ assignableRoles:
8
+ - developer
9
+ - qa
10
+ - tpm
11
+ - designer
12
+ - frontend-developer
13
+ - backend-developer
14
+ - fullstack-dev
15
+ - qa-engineer
16
+ - product-manager
17
+ - architect
18
+ - generalist
19
+ - sales
20
+ - support
21
+ - orchestrator
22
+ triggers:
23
+ - resolve prediction
24
+ - prediction outcome
25
+ - was I right
26
+ tags:
27
+ - memory
28
+ - calibration
29
+ - self-improvement
30
+ execution:
31
+ type: script
32
+ script:
33
+ file: execute.sh
34
+ interpreter: bash
35
+ timeoutMs: 15000
36
+ ---
37
+
38
+ # Resolve Prediction
39
+
40
+ Record the outcome of a prediction made with `record-prediction`. Pass `--accurate true|false`; if you only pass an outcome, a plain verdict such as `correct`, `wrong`, `yes`, `no` is understood — anything else needs the explicit flag. The response includes your updated calibration score.
41
+
42
+ ## Parameters
43
+
44
+ | Flag | JSON Field | Required | Description |
45
+ |------|-----------|----------|-------------|
46
+ | `--id` | `id` | Yes | Prediction id (`pred-...`) |
47
+ | `--outcome` / `-o` | `outcome` | Yes | What actually happened |
48
+ | `--accurate` / `-a` | `accurate` | No* | `true` / `false` — required unless outcome is a plain verdict |
49
+ | `--session` / `-s` | `sessionName` | No | Your session name — defaults to `$CREWLY_SESSION_NAME` |
50
+
51
+ ## Examples
52
+
53
+ ```bash
54
+ bash execute.sh --id pred-1718000000-ab12cd --outcome "merged Thursday" --accurate true
55
+ bash execute.sh --id pred-1718000000-ab12cd --outcome wrong
56
+ bash execute.sh '{"id":"pred-1718000000-ab12cd","outcome":"slipped a week","accurate":false}'
57
+ ```
58
+
59
+ ## Output
60
+
61
+ `{ "success": true, "prediction": {...}, "calibrationScore": 0.82 }`
@@ -0,0 +1,87 @@
1
+ #!/bin/bash
2
+ # =============================================================================
3
+ # resolve-prediction — Close a prediction with its actual outcome
4
+ #
5
+ # Backed by POST /api/agents/:sessionName/self-improvement/predictions/:id/resolve.
6
+ #
7
+ # Usage:
8
+ # bash execute.sh --id pred-123 --outcome "merged Thursday" --accurate true [--session crewly-dev-1]
9
+ # bash execute.sh --id pred-123 --outcome wrong
10
+ # bash execute.sh '{"id":"pred-123","outcome":"slipped","accurate":false}'
11
+ # =============================================================================
12
+ set -euo pipefail
13
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14
+ source "${SCRIPT_DIR}/../../_common/lib.sh"
15
+
16
+ print_usage() {
17
+ cat <<'EOF_USAGE'
18
+ Usage:
19
+ bash execute.sh --id pred-123 --outcome "merged Thursday" --accurate true [--session crewly-dev-1]
20
+ bash execute.sh --id pred-123 --outcome wrong
21
+ bash execute.sh '{"id":"pred-123","outcome":"slipped","accurate":false}'
22
+
23
+ Options:
24
+ --id Prediction id (required)
25
+ --outcome | -o What actually happened (required)
26
+ --accurate | -a true|false (required unless outcome is a plain verdict like "correct"/"wrong")
27
+ --session | -s Session name (defaults to $CREWLY_SESSION_NAME)
28
+ --help | -h Show this help
29
+ EOF_USAGE
30
+ }
31
+
32
+ INPUT_JSON=""
33
+ SESSION_NAME=""
34
+ PRED_ID=""
35
+ OUTCOME=""
36
+ ACCURATE=""
37
+
38
+ if [[ $# -gt 0 && ${1:0:1} == '{' ]]; then
39
+ INPUT_JSON="$1"
40
+ shift || true
41
+ fi
42
+
43
+ while [[ $# -gt 0 ]]; do
44
+ case "$1" in
45
+ --id)
46
+ [ $# -ge 2 ] || error_exit "--id requires a value"
47
+ PRED_ID="$2"; shift 2 ;;
48
+ --outcome|-o)
49
+ [ $# -ge 2 ] || error_exit "--outcome requires a value"
50
+ OUTCOME="$2"; shift 2 ;;
51
+ --accurate|-a)
52
+ [ $# -ge 2 ] || error_exit "--accurate requires a value"
53
+ ACCURATE="$2"; shift 2 ;;
54
+ --session|-s)
55
+ [ $# -ge 2 ] || error_exit "--session requires a value"
56
+ SESSION_NAME="$2"; shift 2 ;;
57
+ --help|-h) print_usage; exit 0 ;;
58
+ *) error_exit "Unknown option: $1" ;;
59
+ esac
60
+ done
61
+
62
+ if [ -n "$INPUT_JSON" ]; then
63
+ INPUT=$(read_json_input "$INPUT_JSON")
64
+ [ -z "$SESSION_NAME" ] && SESSION_NAME=$(printf '%s' "$INPUT" | jq -r '.sessionName // .agentId // empty')
65
+ [ -z "$PRED_ID" ] && PRED_ID=$(printf '%s' "$INPUT" | jq -r '.id // .predictionId // empty')
66
+ [ -z "$OUTCOME" ] && OUTCOME=$(printf '%s' "$INPUT" | jq -r '.outcome // empty')
67
+ [ -z "$ACCURATE" ] && ACCURATE=$(printf '%s' "$INPUT" | jq -r 'if .accurate == null then empty else (.accurate | tostring) end')
68
+ fi
69
+
70
+ [ -z "$SESSION_NAME" ] && SESSION_NAME="${CREWLY_SESSION_NAME:-}"
71
+ require_param "sessionName (--session or CREWLY_SESSION_NAME)" "$SESSION_NAME"
72
+ require_param "id (--id)" "$PRED_ID"
73
+ require_param "outcome (--outcome)" "$OUTCOME"
74
+
75
+ case "$ACCURATE" in
76
+ "") BODY=$(jq -cn --arg o "$OUTCOME" '{outcome: $o}') ;;
77
+ true|false) BODY=$(jq -cn --arg o "$OUTCOME" --argjson a "$ACCURATE" '{outcome: $o, accurate: $a}') ;;
78
+ *) error_exit "accurate must be true or false (got: $ACCURATE)" ;;
79
+ esac
80
+
81
+ RESPONSE=$(api_call POST "/agents/${SESSION_NAME}/self-improvement/predictions/${PRED_ID}/resolve" "$BODY" 2>&1) || {
82
+ ERROR_MSG=$(printf '%s' "$RESPONSE" | jq -r '.details.error // .details // .error // "Unknown error"' 2>/dev/null || echo "$RESPONSE")
83
+ jq -n --arg reason "$ERROR_MSG" '{success: false, reason: $reason}'
84
+ exit 1
85
+ }
86
+
87
+ printf '%s' "$RESPONSE" | jq -c '{success: (.success // false), prediction: (.data.prediction // null), calibrationScore: (.data.calibrationScore // null)}'