@renseiai/agentfactory 0.8.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 (246) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +125 -0
  3. package/dist/src/config/index.d.ts +3 -0
  4. package/dist/src/config/index.d.ts.map +1 -0
  5. package/dist/src/config/index.js +1 -0
  6. package/dist/src/config/repository-config.d.ts +44 -0
  7. package/dist/src/config/repository-config.d.ts.map +1 -0
  8. package/dist/src/config/repository-config.js +88 -0
  9. package/dist/src/config/repository-config.test.d.ts +2 -0
  10. package/dist/src/config/repository-config.test.d.ts.map +1 -0
  11. package/dist/src/config/repository-config.test.js +249 -0
  12. package/dist/src/deployment/deployment-checker.d.ts +110 -0
  13. package/dist/src/deployment/deployment-checker.d.ts.map +1 -0
  14. package/dist/src/deployment/deployment-checker.js +242 -0
  15. package/dist/src/deployment/index.d.ts +3 -0
  16. package/dist/src/deployment/index.d.ts.map +1 -0
  17. package/dist/src/deployment/index.js +2 -0
  18. package/dist/src/frontend/index.d.ts +2 -0
  19. package/dist/src/frontend/index.d.ts.map +1 -0
  20. package/dist/src/frontend/index.js +1 -0
  21. package/dist/src/frontend/types.d.ts +106 -0
  22. package/dist/src/frontend/types.d.ts.map +1 -0
  23. package/dist/src/frontend/types.js +11 -0
  24. package/dist/src/governor/decision-engine.d.ts +52 -0
  25. package/dist/src/governor/decision-engine.d.ts.map +1 -0
  26. package/dist/src/governor/decision-engine.js +220 -0
  27. package/dist/src/governor/decision-engine.test.d.ts +2 -0
  28. package/dist/src/governor/decision-engine.test.d.ts.map +1 -0
  29. package/dist/src/governor/decision-engine.test.js +629 -0
  30. package/dist/src/governor/event-bus.d.ts +43 -0
  31. package/dist/src/governor/event-bus.d.ts.map +1 -0
  32. package/dist/src/governor/event-bus.js +8 -0
  33. package/dist/src/governor/event-deduplicator.d.ts +43 -0
  34. package/dist/src/governor/event-deduplicator.d.ts.map +1 -0
  35. package/dist/src/governor/event-deduplicator.js +53 -0
  36. package/dist/src/governor/event-driven-governor.d.ts +131 -0
  37. package/dist/src/governor/event-driven-governor.d.ts.map +1 -0
  38. package/dist/src/governor/event-driven-governor.js +379 -0
  39. package/dist/src/governor/event-driven-governor.test.d.ts +2 -0
  40. package/dist/src/governor/event-driven-governor.test.d.ts.map +1 -0
  41. package/dist/src/governor/event-driven-governor.test.js +673 -0
  42. package/dist/src/governor/event-types.d.ts +78 -0
  43. package/dist/src/governor/event-types.d.ts.map +1 -0
  44. package/dist/src/governor/event-types.js +32 -0
  45. package/dist/src/governor/governor-types.d.ts +82 -0
  46. package/dist/src/governor/governor-types.d.ts.map +1 -0
  47. package/dist/src/governor/governor-types.js +21 -0
  48. package/dist/src/governor/governor.d.ts +100 -0
  49. package/dist/src/governor/governor.d.ts.map +1 -0
  50. package/dist/src/governor/governor.js +262 -0
  51. package/dist/src/governor/governor.test.d.ts +2 -0
  52. package/dist/src/governor/governor.test.d.ts.map +1 -0
  53. package/dist/src/governor/governor.test.js +514 -0
  54. package/dist/src/governor/human-touchpoints.d.ts +131 -0
  55. package/dist/src/governor/human-touchpoints.d.ts.map +1 -0
  56. package/dist/src/governor/human-touchpoints.js +251 -0
  57. package/dist/src/governor/human-touchpoints.test.d.ts +2 -0
  58. package/dist/src/governor/human-touchpoints.test.d.ts.map +1 -0
  59. package/dist/src/governor/human-touchpoints.test.js +366 -0
  60. package/dist/src/governor/in-memory-event-bus.d.ts +29 -0
  61. package/dist/src/governor/in-memory-event-bus.d.ts.map +1 -0
  62. package/dist/src/governor/in-memory-event-bus.js +79 -0
  63. package/dist/src/governor/index.d.ts +14 -0
  64. package/dist/src/governor/index.d.ts.map +1 -0
  65. package/dist/src/governor/index.js +13 -0
  66. package/dist/src/governor/override-parser.d.ts +60 -0
  67. package/dist/src/governor/override-parser.d.ts.map +1 -0
  68. package/dist/src/governor/override-parser.js +98 -0
  69. package/dist/src/governor/override-parser.test.d.ts +2 -0
  70. package/dist/src/governor/override-parser.test.d.ts.map +1 -0
  71. package/dist/src/governor/override-parser.test.js +312 -0
  72. package/dist/src/governor/platform-adapter.d.ts +69 -0
  73. package/dist/src/governor/platform-adapter.d.ts.map +1 -0
  74. package/dist/src/governor/platform-adapter.js +11 -0
  75. package/dist/src/governor/processing-state.d.ts +66 -0
  76. package/dist/src/governor/processing-state.d.ts.map +1 -0
  77. package/dist/src/governor/processing-state.js +43 -0
  78. package/dist/src/governor/processing-state.test.d.ts +2 -0
  79. package/dist/src/governor/processing-state.test.d.ts.map +1 -0
  80. package/dist/src/governor/processing-state.test.js +96 -0
  81. package/dist/src/governor/top-of-funnel.d.ts +118 -0
  82. package/dist/src/governor/top-of-funnel.d.ts.map +1 -0
  83. package/dist/src/governor/top-of-funnel.js +168 -0
  84. package/dist/src/governor/top-of-funnel.test.d.ts +2 -0
  85. package/dist/src/governor/top-of-funnel.test.d.ts.map +1 -0
  86. package/dist/src/governor/top-of-funnel.test.js +331 -0
  87. package/dist/src/index.d.ts +11 -0
  88. package/dist/src/index.d.ts.map +1 -0
  89. package/dist/src/index.js +10 -0
  90. package/dist/src/linear-cli.d.ts +38 -0
  91. package/dist/src/linear-cli.d.ts.map +1 -0
  92. package/dist/src/linear-cli.js +674 -0
  93. package/dist/src/logger.d.ts +117 -0
  94. package/dist/src/logger.d.ts.map +1 -0
  95. package/dist/src/logger.js +430 -0
  96. package/dist/src/manifest/generate.d.ts +20 -0
  97. package/dist/src/manifest/generate.d.ts.map +1 -0
  98. package/dist/src/manifest/generate.js +65 -0
  99. package/dist/src/manifest/index.d.ts +4 -0
  100. package/dist/src/manifest/index.d.ts.map +1 -0
  101. package/dist/src/manifest/index.js +2 -0
  102. package/dist/src/manifest/route-manifest.d.ts +34 -0
  103. package/dist/src/manifest/route-manifest.d.ts.map +1 -0
  104. package/dist/src/manifest/route-manifest.js +148 -0
  105. package/dist/src/orchestrator/activity-emitter.d.ts +119 -0
  106. package/dist/src/orchestrator/activity-emitter.d.ts.map +1 -0
  107. package/dist/src/orchestrator/activity-emitter.js +306 -0
  108. package/dist/src/orchestrator/api-activity-emitter.d.ts +167 -0
  109. package/dist/src/orchestrator/api-activity-emitter.d.ts.map +1 -0
  110. package/dist/src/orchestrator/api-activity-emitter.js +417 -0
  111. package/dist/src/orchestrator/heartbeat-writer.d.ts +57 -0
  112. package/dist/src/orchestrator/heartbeat-writer.d.ts.map +1 -0
  113. package/dist/src/orchestrator/heartbeat-writer.js +137 -0
  114. package/dist/src/orchestrator/index.d.ts +20 -0
  115. package/dist/src/orchestrator/index.d.ts.map +1 -0
  116. package/dist/src/orchestrator/index.js +22 -0
  117. package/dist/src/orchestrator/log-analyzer.d.ts +160 -0
  118. package/dist/src/orchestrator/log-analyzer.d.ts.map +1 -0
  119. package/dist/src/orchestrator/log-analyzer.js +572 -0
  120. package/dist/src/orchestrator/log-config.d.ts +39 -0
  121. package/dist/src/orchestrator/log-config.d.ts.map +1 -0
  122. package/dist/src/orchestrator/log-config.js +45 -0
  123. package/dist/src/orchestrator/orchestrator.d.ts +316 -0
  124. package/dist/src/orchestrator/orchestrator.d.ts.map +1 -0
  125. package/dist/src/orchestrator/orchestrator.js +3290 -0
  126. package/dist/src/orchestrator/parse-work-result.d.ts +16 -0
  127. package/dist/src/orchestrator/parse-work-result.d.ts.map +1 -0
  128. package/dist/src/orchestrator/parse-work-result.js +135 -0
  129. package/dist/src/orchestrator/parse-work-result.test.d.ts +2 -0
  130. package/dist/src/orchestrator/parse-work-result.test.d.ts.map +1 -0
  131. package/dist/src/orchestrator/parse-work-result.test.js +234 -0
  132. package/dist/src/orchestrator/progress-logger.d.ts +72 -0
  133. package/dist/src/orchestrator/progress-logger.d.ts.map +1 -0
  134. package/dist/src/orchestrator/progress-logger.js +135 -0
  135. package/dist/src/orchestrator/session-logger.d.ts +159 -0
  136. package/dist/src/orchestrator/session-logger.d.ts.map +1 -0
  137. package/dist/src/orchestrator/session-logger.js +275 -0
  138. package/dist/src/orchestrator/state-recovery.d.ts +96 -0
  139. package/dist/src/orchestrator/state-recovery.d.ts.map +1 -0
  140. package/dist/src/orchestrator/state-recovery.js +302 -0
  141. package/dist/src/orchestrator/state-types.d.ts +165 -0
  142. package/dist/src/orchestrator/state-types.d.ts.map +1 -0
  143. package/dist/src/orchestrator/state-types.js +7 -0
  144. package/dist/src/orchestrator/stream-parser.d.ts +151 -0
  145. package/dist/src/orchestrator/stream-parser.d.ts.map +1 -0
  146. package/dist/src/orchestrator/stream-parser.js +137 -0
  147. package/dist/src/orchestrator/types.d.ts +232 -0
  148. package/dist/src/orchestrator/types.d.ts.map +1 -0
  149. package/dist/src/orchestrator/types.js +4 -0
  150. package/dist/src/orchestrator/validate-git-remote.test.d.ts +2 -0
  151. package/dist/src/orchestrator/validate-git-remote.test.d.ts.map +1 -0
  152. package/dist/src/orchestrator/validate-git-remote.test.js +61 -0
  153. package/dist/src/providers/a2a-auth.d.ts +81 -0
  154. package/dist/src/providers/a2a-auth.d.ts.map +1 -0
  155. package/dist/src/providers/a2a-auth.js +188 -0
  156. package/dist/src/providers/a2a-auth.test.d.ts +2 -0
  157. package/dist/src/providers/a2a-auth.test.d.ts.map +1 -0
  158. package/dist/src/providers/a2a-auth.test.js +232 -0
  159. package/dist/src/providers/a2a-provider.d.ts +254 -0
  160. package/dist/src/providers/a2a-provider.d.ts.map +1 -0
  161. package/dist/src/providers/a2a-provider.integration.test.d.ts +9 -0
  162. package/dist/src/providers/a2a-provider.integration.test.d.ts.map +1 -0
  163. package/dist/src/providers/a2a-provider.integration.test.js +665 -0
  164. package/dist/src/providers/a2a-provider.js +811 -0
  165. package/dist/src/providers/a2a-provider.test.d.ts +2 -0
  166. package/dist/src/providers/a2a-provider.test.d.ts.map +1 -0
  167. package/dist/src/providers/a2a-provider.test.js +681 -0
  168. package/dist/src/providers/amp-provider.d.ts +20 -0
  169. package/dist/src/providers/amp-provider.d.ts.map +1 -0
  170. package/dist/src/providers/amp-provider.js +24 -0
  171. package/dist/src/providers/claude-provider.d.ts +18 -0
  172. package/dist/src/providers/claude-provider.d.ts.map +1 -0
  173. package/dist/src/providers/claude-provider.js +437 -0
  174. package/dist/src/providers/codex-provider.d.ts +133 -0
  175. package/dist/src/providers/codex-provider.d.ts.map +1 -0
  176. package/dist/src/providers/codex-provider.js +381 -0
  177. package/dist/src/providers/codex-provider.test.d.ts +2 -0
  178. package/dist/src/providers/codex-provider.test.d.ts.map +1 -0
  179. package/dist/src/providers/codex-provider.test.js +387 -0
  180. package/dist/src/providers/index.d.ts +44 -0
  181. package/dist/src/providers/index.d.ts.map +1 -0
  182. package/dist/src/providers/index.js +85 -0
  183. package/dist/src/providers/spring-ai-provider.d.ts +90 -0
  184. package/dist/src/providers/spring-ai-provider.d.ts.map +1 -0
  185. package/dist/src/providers/spring-ai-provider.integration.test.d.ts +13 -0
  186. package/dist/src/providers/spring-ai-provider.integration.test.d.ts.map +1 -0
  187. package/dist/src/providers/spring-ai-provider.integration.test.js +351 -0
  188. package/dist/src/providers/spring-ai-provider.js +317 -0
  189. package/dist/src/providers/spring-ai-provider.test.d.ts +2 -0
  190. package/dist/src/providers/spring-ai-provider.test.d.ts.map +1 -0
  191. package/dist/src/providers/spring-ai-provider.test.js +200 -0
  192. package/dist/src/providers/types.d.ts +165 -0
  193. package/dist/src/providers/types.d.ts.map +1 -0
  194. package/dist/src/providers/types.js +13 -0
  195. package/dist/src/templates/adapters.d.ts +51 -0
  196. package/dist/src/templates/adapters.d.ts.map +1 -0
  197. package/dist/src/templates/adapters.js +104 -0
  198. package/dist/src/templates/adapters.test.d.ts +2 -0
  199. package/dist/src/templates/adapters.test.d.ts.map +1 -0
  200. package/dist/src/templates/adapters.test.js +165 -0
  201. package/dist/src/templates/agent-definition.d.ts +85 -0
  202. package/dist/src/templates/agent-definition.d.ts.map +1 -0
  203. package/dist/src/templates/agent-definition.js +97 -0
  204. package/dist/src/templates/agent-definition.test.d.ts +2 -0
  205. package/dist/src/templates/agent-definition.test.d.ts.map +1 -0
  206. package/dist/src/templates/agent-definition.test.js +209 -0
  207. package/dist/src/templates/index.d.ts +14 -0
  208. package/dist/src/templates/index.d.ts.map +1 -0
  209. package/dist/src/templates/index.js +11 -0
  210. package/dist/src/templates/loader.d.ts +41 -0
  211. package/dist/src/templates/loader.d.ts.map +1 -0
  212. package/dist/src/templates/loader.js +114 -0
  213. package/dist/src/templates/registry.d.ts +80 -0
  214. package/dist/src/templates/registry.d.ts.map +1 -0
  215. package/dist/src/templates/registry.js +177 -0
  216. package/dist/src/templates/registry.test.d.ts +2 -0
  217. package/dist/src/templates/registry.test.d.ts.map +1 -0
  218. package/dist/src/templates/registry.test.js +198 -0
  219. package/dist/src/templates/renderer.d.ts +29 -0
  220. package/dist/src/templates/renderer.d.ts.map +1 -0
  221. package/dist/src/templates/renderer.js +35 -0
  222. package/dist/src/templates/strategy-templates.test.d.ts +2 -0
  223. package/dist/src/templates/strategy-templates.test.d.ts.map +1 -0
  224. package/dist/src/templates/strategy-templates.test.js +619 -0
  225. package/dist/src/templates/types.d.ts +233 -0
  226. package/dist/src/templates/types.d.ts.map +1 -0
  227. package/dist/src/templates/types.js +127 -0
  228. package/dist/src/templates/types.test.d.ts +2 -0
  229. package/dist/src/templates/types.test.d.ts.map +1 -0
  230. package/dist/src/templates/types.test.js +232 -0
  231. package/dist/src/tools/index.d.ts +6 -0
  232. package/dist/src/tools/index.d.ts.map +1 -0
  233. package/dist/src/tools/index.js +3 -0
  234. package/dist/src/tools/linear-runner.d.ts +34 -0
  235. package/dist/src/tools/linear-runner.d.ts.map +1 -0
  236. package/dist/src/tools/linear-runner.js +700 -0
  237. package/dist/src/tools/plugins/linear.d.ts +9 -0
  238. package/dist/src/tools/plugins/linear.d.ts.map +1 -0
  239. package/dist/src/tools/plugins/linear.js +138 -0
  240. package/dist/src/tools/registry.d.ts +9 -0
  241. package/dist/src/tools/registry.d.ts.map +1 -0
  242. package/dist/src/tools/registry.js +18 -0
  243. package/dist/src/tools/types.d.ts +18 -0
  244. package/dist/src/tools/types.d.ts.map +1 -0
  245. package/dist/src/tools/types.js +1 -0
  246. package/package.json +78 -0
@@ -0,0 +1,16 @@
1
+ import type { AgentWorkType } from '@renseiai/agentfactory-linear';
2
+ import type { AgentWorkResult } from './types.js';
3
+ /**
4
+ * Parse the agent's result message to determine whether the work passed or failed.
5
+ *
6
+ * Detection priority:
7
+ * 1. Structured marker: `<!-- WORK_RESULT:passed/failed -->`
8
+ * 2. Heuristic heading/pattern matching scoped to the work type
9
+ * 3. Returns 'unknown' if nothing matches (safe default: no transition)
10
+ *
11
+ * @param resultMessage - The agent's final output message
12
+ * @param workType - The type of work performed (qa, acceptance, etc.)
13
+ * @returns 'passed', 'failed', or 'unknown'
14
+ */
15
+ export declare function parseWorkResult(resultMessage: string | undefined, workType: AgentWorkType): AgentWorkResult;
16
+ //# sourceMappingURL=parse-work-result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-work-result.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/parse-work-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AA+FjD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,QAAQ,EAAE,aAAa,GACtB,eAAe,CAyCjB"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Structured marker pattern embedded in agent output.
3
+ * Agents are instructed to include this marker in their final output.
4
+ *
5
+ * Format: <!-- WORK_RESULT:passed --> or <!-- WORK_RESULT:failed -->
6
+ */
7
+ const STRUCTURED_MARKER_RE = /<!--\s*WORK_RESULT:(passed|failed)\s*-->/i;
8
+ /**
9
+ * Heuristic patterns for detecting QA pass/fail when structured marker is absent.
10
+ * Patterns are checked case-insensitively against the result message.
11
+ */
12
+ const QA_PASS_PATTERNS = [
13
+ // Heading patterns
14
+ /##\s*QA\s+Passed/i,
15
+ /##\s*QA\s+Complete[^]*?\bPASS/i,
16
+ // Explicit label patterns (with optional "QA" prefix, word-bounded to avoid WORK_RESULT)
17
+ /\b(?:QA\s+)?Result:\s*\*{0,2}Pass(?:ed)?\*{0,2}/i,
18
+ /\b(?:QA\s+)?Status:\s*\*{0,2}Pass(?:ed)?\*{0,2}/i,
19
+ /\b(?:QA\s+)?Verdict:\s*\*{0,2}Pass(?:ed)?\*{0,2}/i,
20
+ /\b(?:QA\s+)?(?:Result|Status|Verdict):\s*✅/i,
21
+ /Overall\s+(?:QA\s+)?Result:\s*PASS/i,
22
+ /Roll-?Up\s+Verdict:\s*PASS/i,
23
+ // Bold standalone PASS (agents commonly output **PASS** or **PASS.**)
24
+ /\*\*PASS\.?\*\*/,
25
+ ];
26
+ const QA_FAIL_PATTERNS = [
27
+ // Heading patterns
28
+ /##\s*QA\s+Failed/i,
29
+ /##\s*QA\s+Complete[^]*?\bFAIL/i,
30
+ // Explicit label patterns (with optional "QA" prefix, word-bounded to avoid WORK_RESULT)
31
+ /\b(?:QA\s+)?Result:\s*\*{0,2}Fail(?:ed)?\*{0,2}/i,
32
+ /\b(?:QA\s+)?Status:\s*\*{0,2}Fail(?:ed)?\*{0,2}/i,
33
+ /\b(?:QA\s+)?Verdict:\s*\*{0,2}Fail(?:ed)?\*{0,2}/i,
34
+ /\b(?:QA\s+)?(?:Result|Status|Verdict):\s*❌/i,
35
+ /Overall\s+(?:QA\s+)?Result:\s*FAIL/i,
36
+ /Roll-?Up\s+Verdict:\s*FAIL/i,
37
+ /Parent\s+QA\s+verdict:\s*FAIL/i,
38
+ // Bold standalone FAIL
39
+ /\*\*FAIL\.?\*\*/,
40
+ // QA coordination report with issues found (agents output "Status: N Issues Found")
41
+ /\bStatus:\s*\d+\s+Issues?\s+Found\b/i,
42
+ // "Must Fix Before Merge" — agents use this heading for blocking findings
43
+ /\bMust\s+Fix\s+Before\s+Merge\b/i,
44
+ // "N Critical Issues (Block Merge)" — coordination QA summary format
45
+ /\d+\s+Critical\s+Issues?\s*\(Block\s+Merge\)/i,
46
+ ];
47
+ const ACCEPTANCE_PASS_PATTERNS = [
48
+ /##\s*Acceptance\s+Complete/i,
49
+ /Acceptance\s+Result:\s*Pass/i,
50
+ /PR\s+has\s+been\s+merged\s+successfully/i,
51
+ ];
52
+ const ACCEPTANCE_FAIL_PATTERNS = [
53
+ /##\s*Acceptance\s+(?:Processing\s+)?Failed/i,
54
+ /Acceptance\s+(?:Processing\s+)?Blocked/i,
55
+ /Acceptance\s+Result:\s*Fail/i,
56
+ /Cannot\s+merge\s+PR/i,
57
+ // Coordination-style patterns (agents output reports with "Must Fix" / "Critical Issues")
58
+ /\bMust\s+Fix\s+Before\s+Merge\b/i,
59
+ /\d+\s+Critical\s+Issues?\s*\(Block\s+Merge\)/i,
60
+ ];
61
+ /**
62
+ * Heuristic patterns for detecting coordination pass/fail.
63
+ * These apply to the 'coordination' work type (development coordination).
64
+ */
65
+ const COORDINATION_PASS_PATTERNS = [
66
+ // "all 8/8 sub-issues completed" or "all sub-issues completed"
67
+ /\ball\s+(?:\d+\/\d+\s+)?sub-issues?\s+(?:completed|finished)/i,
68
+ // "8/8 sub-issues completed/finished" (without leading "all")
69
+ /\b(\d+)\/\1\b.*\bsub-issues?\s+(?:completed|finished)/i,
70
+ // Explicit result labels
71
+ /\bCoordination\s+(?:Result|Status|Verdict):\s*\*{0,2}Pass(?:ed)?\*{0,2}/i,
72
+ /\bCoordination\s+Complete/i,
73
+ // "Parent issue marked Finished" — coordinator confirms parent status update
74
+ /\bParent\s+issue\s+marked\s+Finished/i,
75
+ ];
76
+ const COORDINATION_FAIL_PATTERNS = [
77
+ // "Must Fix Before Merge" — agents use this heading for blocking issues
78
+ /\bMust\s+Fix\s+Before\s+Merge\b/i,
79
+ // "N Critical Issues (Block Merge)"
80
+ /\d+\s+Critical\s+Issues?\s*\(Block\s+Merge\)/i,
81
+ // "sub-issues need work/attention/fixes"
82
+ /\bsub-issues?\s+(?:need|require)[s]?\s+(?:work|attention|fixes?)\b/i,
83
+ // Explicit result labels
84
+ /\bCoordination\s+(?:Result|Status|Verdict):\s*\*{0,2}Fail(?:ed)?\*{0,2}/i,
85
+ /\bCoordination\s+Failed/i,
86
+ ];
87
+ /**
88
+ * Parse the agent's result message to determine whether the work passed or failed.
89
+ *
90
+ * Detection priority:
91
+ * 1. Structured marker: `<!-- WORK_RESULT:passed/failed -->`
92
+ * 2. Heuristic heading/pattern matching scoped to the work type
93
+ * 3. Returns 'unknown' if nothing matches (safe default: no transition)
94
+ *
95
+ * @param resultMessage - The agent's final output message
96
+ * @param workType - The type of work performed (qa, acceptance, etc.)
97
+ * @returns 'passed', 'failed', or 'unknown'
98
+ */
99
+ export function parseWorkResult(resultMessage, workType) {
100
+ if (!resultMessage) {
101
+ return 'unknown';
102
+ }
103
+ // 1. Check for structured marker (highest priority, work-type agnostic)
104
+ const markerMatch = resultMessage.match(STRUCTURED_MARKER_RE);
105
+ if (markerMatch) {
106
+ return markerMatch[1].toLowerCase();
107
+ }
108
+ // 2. Fall back to heuristic patterns scoped by work type
109
+ if (workType === 'qa' || workType === 'qa-coordination') {
110
+ if (QA_FAIL_PATTERNS.some((p) => p.test(resultMessage))) {
111
+ return 'failed';
112
+ }
113
+ if (QA_PASS_PATTERNS.some((p) => p.test(resultMessage))) {
114
+ return 'passed';
115
+ }
116
+ }
117
+ if (workType === 'acceptance' || workType === 'acceptance-coordination') {
118
+ if (ACCEPTANCE_FAIL_PATTERNS.some((p) => p.test(resultMessage))) {
119
+ return 'failed';
120
+ }
121
+ if (ACCEPTANCE_PASS_PATTERNS.some((p) => p.test(resultMessage))) {
122
+ return 'passed';
123
+ }
124
+ }
125
+ if (workType === 'coordination') {
126
+ if (COORDINATION_FAIL_PATTERNS.some((p) => p.test(resultMessage))) {
127
+ return 'failed';
128
+ }
129
+ if (COORDINATION_PASS_PATTERNS.some((p) => p.test(resultMessage))) {
130
+ return 'passed';
131
+ }
132
+ }
133
+ // 3. Unknown — safe default
134
+ return 'unknown';
135
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parse-work-result.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-work-result.test.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/parse-work-result.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,234 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { parseWorkResult } from './parse-work-result.js';
3
+ describe('parseWorkResult', () => {
4
+ // Structured marker tests
5
+ describe('structured markers', () => {
6
+ it('detects <!-- WORK_RESULT:passed --> marker', () => {
7
+ expect(parseWorkResult('Some text <!-- WORK_RESULT:passed --> more text', 'qa')).toBe('passed');
8
+ });
9
+ it('detects <!-- WORK_RESULT:failed --> marker', () => {
10
+ expect(parseWorkResult('<!-- WORK_RESULT:failed -->', 'qa')).toBe('failed');
11
+ });
12
+ it('is case-insensitive for marker value', () => {
13
+ expect(parseWorkResult('<!-- WORK_RESULT:PASSED -->', 'qa')).toBe('passed');
14
+ expect(parseWorkResult('<!-- WORK_RESULT:Failed -->', 'acceptance')).toBe('failed');
15
+ });
16
+ it('handles extra whitespace in marker', () => {
17
+ expect(parseWorkResult('<!-- WORK_RESULT:passed -->', 'qa')).toBe('passed');
18
+ });
19
+ it('finds marker anywhere in the message', () => {
20
+ const msg = 'Here is my QA report\n\nEverything looks good\n\n<!-- WORK_RESULT:passed -->\n\nEnd of report';
21
+ expect(parseWorkResult(msg, 'qa')).toBe('passed');
22
+ });
23
+ it('works for any work type (not just qa/acceptance)', () => {
24
+ expect(parseWorkResult('<!-- WORK_RESULT:passed -->', 'development')).toBe('passed');
25
+ expect(parseWorkResult('<!-- WORK_RESULT:failed -->', 'coordination')).toBe('failed');
26
+ });
27
+ });
28
+ // QA heuristic pattern tests
29
+ describe('QA heuristic patterns', () => {
30
+ it('detects "## QA Passed" heading', () => {
31
+ expect(parseWorkResult('## QA Passed\nAll tests pass.', 'qa')).toBe('passed');
32
+ });
33
+ it('detects "QA Result: Pass"', () => {
34
+ expect(parseWorkResult('QA Result: Pass', 'qa')).toBe('passed');
35
+ });
36
+ it('detects "QA Status: Passed"', () => {
37
+ expect(parseWorkResult('QA Status: Passed', 'qa')).toBe('passed');
38
+ });
39
+ it('detects "## QA Failed" heading', () => {
40
+ expect(parseWorkResult('## QA Failed\nTests are broken.', 'qa')).toBe('failed');
41
+ });
42
+ it('detects "QA Result: Fail"', () => {
43
+ expect(parseWorkResult('QA Result: Fail', 'qa')).toBe('failed');
44
+ });
45
+ it('does not match QA patterns for non-qa work types', () => {
46
+ expect(parseWorkResult('## QA Passed', 'development')).toBe('unknown');
47
+ expect(parseWorkResult('QA Result: Pass', 'acceptance')).toBe('unknown');
48
+ });
49
+ it('matches QA patterns for qa-coordination work type', () => {
50
+ expect(parseWorkResult('## QA Passed\nAll sub-issues pass.', 'qa-coordination')).toBe('passed');
51
+ expect(parseWorkResult('## QA Failed\nSUP-712 needs work.', 'qa-coordination')).toBe('failed');
52
+ expect(parseWorkResult('QA Result: Pass', 'qa-coordination')).toBe('passed');
53
+ expect(parseWorkResult('QA Result: Fail', 'qa-coordination')).toBe('failed');
54
+ });
55
+ it('checks fail patterns before pass patterns', () => {
56
+ // Both present - fail takes precedence since it's checked first
57
+ expect(parseWorkResult('## QA Failed\n## QA Passed', 'qa')).toBe('failed');
58
+ });
59
+ it('detects "Overall Result: FAIL" (coordination style)', () => {
60
+ expect(parseWorkResult('**Overall Result: FAIL** — 4 of 6 phases failed', 'qa-coordination')).toBe('failed');
61
+ });
62
+ it('detects "Overall QA Result: FAIL" (coordination style)', () => {
63
+ expect(parseWorkResult('**Overall QA Result: FAIL (0/6 sub-issues pass)**', 'qa-coordination')).toBe('failed');
64
+ });
65
+ it('detects "Roll-Up Verdict: FAIL"', () => {
66
+ expect(parseWorkResult('### Roll-Up Verdict: FAIL (0/6 sub-issues pass)', 'qa-coordination')).toBe('failed');
67
+ });
68
+ it('detects "Parent QA verdict: FAIL"', () => {
69
+ expect(parseWorkResult('**Parent QA verdict: FAIL — requires fixes**', 'qa-coordination')).toBe('failed');
70
+ });
71
+ it('detects "Overall Result: PASS" (coordination style)', () => {
72
+ expect(parseWorkResult('**Overall Result: PASS** — all phases passed', 'qa-coordination')).toBe('passed');
73
+ });
74
+ it('detects "Roll-Up Verdict: PASS"', () => {
75
+ expect(parseWorkResult('### Roll-Up Verdict: PASS (6/6 sub-issues pass)', 'qa-coordination')).toBe('passed');
76
+ });
77
+ // Real agent output patterns (SUP-867 regression)
78
+ it('detects bold **PASS**', () => {
79
+ expect(parseWorkResult('Branch unchanged — `4383c3e`. **PASS.** No new findings.', 'qa')).toBe('passed');
80
+ });
81
+ it('detects bold **PASS** without period', () => {
82
+ expect(parseWorkResult('All tests pass. **PASS**', 'qa')).toBe('passed');
83
+ });
84
+ it('detects "Verdict: PASS" without QA prefix', () => {
85
+ expect(parseWorkResult('**Verdict: PASS** — all criteria met', 'qa')).toBe('passed');
86
+ });
87
+ it('detects "Verdict: **PASS**" with bold', () => {
88
+ expect(parseWorkResult('Verdict: **PASS**', 'qa')).toBe('passed');
89
+ });
90
+ it('detects "Status: **PASS**" without QA prefix', () => {
91
+ expect(parseWorkResult('### Status: **PASS** — same as prior two passes', 'qa')).toBe('passed');
92
+ });
93
+ it('detects "Result: Pass" without QA prefix', () => {
94
+ expect(parseWorkResult('Result: Pass — no issues found', 'qa')).toBe('passed');
95
+ });
96
+ it('detects bold **FAIL**', () => {
97
+ expect(parseWorkResult('Build failed. **FAIL.**', 'qa')).toBe('failed');
98
+ });
99
+ it('detects "Verdict: FAIL" without QA prefix', () => {
100
+ expect(parseWorkResult('Verdict: FAIL — build errors detected', 'qa')).toBe('failed');
101
+ });
102
+ it('detects "Status: **FAIL**" without QA prefix', () => {
103
+ expect(parseWorkResult('Status: **FAIL**', 'qa')).toBe('failed');
104
+ });
105
+ it('does not false-positive on "tests pass" (no bold)', () => {
106
+ expect(parseWorkResult('All tests pass and everything looks good.', 'qa')).toBe('unknown');
107
+ });
108
+ });
109
+ // Acceptance heuristic pattern tests
110
+ describe('acceptance heuristic patterns', () => {
111
+ it('detects "## Acceptance Complete"', () => {
112
+ expect(parseWorkResult('## Acceptance Complete', 'acceptance')).toBe('passed');
113
+ });
114
+ it('detects "Acceptance Result: Pass"', () => {
115
+ expect(parseWorkResult('Acceptance Result: Pass', 'acceptance')).toBe('passed');
116
+ });
117
+ it('detects "PR has been merged successfully"', () => {
118
+ expect(parseWorkResult('PR has been merged successfully', 'acceptance')).toBe('passed');
119
+ });
120
+ it('detects "## Acceptance Failed"', () => {
121
+ expect(parseWorkResult('## Acceptance Failed', 'acceptance')).toBe('failed');
122
+ });
123
+ it('detects "Acceptance Processing Blocked"', () => {
124
+ expect(parseWorkResult('Acceptance Processing Blocked', 'acceptance')).toBe('failed');
125
+ });
126
+ it('detects "Cannot merge PR"', () => {
127
+ expect(parseWorkResult('Cannot merge PR', 'acceptance')).toBe('failed');
128
+ });
129
+ it('does not match acceptance patterns for non-acceptance work types', () => {
130
+ expect(parseWorkResult('## Acceptance Complete', 'qa')).toBe('unknown');
131
+ expect(parseWorkResult('PR has been merged successfully', 'development')).toBe('unknown');
132
+ });
133
+ it('matches acceptance patterns for acceptance-coordination work type', () => {
134
+ expect(parseWorkResult('## Acceptance Complete', 'acceptance-coordination')).toBe('passed');
135
+ expect(parseWorkResult('PR has been merged successfully', 'acceptance-coordination')).toBe('passed');
136
+ expect(parseWorkResult('## Acceptance Failed', 'acceptance-coordination')).toBe('failed');
137
+ expect(parseWorkResult('Cannot merge PR', 'acceptance-coordination')).toBe('failed');
138
+ });
139
+ });
140
+ // Coordination heuristic pattern tests
141
+ describe('coordination heuristic patterns', () => {
142
+ it('detects "all 8/8 sub-issues completed"', () => {
143
+ expect(parseWorkResult('all 8/8 sub-issues completed and marked Finished in Linear.', 'coordination')).toBe('passed');
144
+ });
145
+ it('detects "all sub-issues completed" without count', () => {
146
+ expect(parseWorkResult('All sub-issues completed successfully.', 'coordination')).toBe('passed');
147
+ });
148
+ it('detects "all sub-issues finished"', () => {
149
+ expect(parseWorkResult('All 3/3 sub-issues finished.', 'coordination')).toBe('passed');
150
+ });
151
+ it('detects "Coordination Complete"', () => {
152
+ expect(parseWorkResult('## Coordination Complete\nAll work done.', 'coordination')).toBe('passed');
153
+ });
154
+ it('detects "Must Fix Before Merge" as fail', () => {
155
+ expect(parseWorkResult('### CRITICAL — Must Fix Before Merge\n1. provision-trial.ts uses removed fields', 'coordination')).toBe('failed');
156
+ });
157
+ it('detects "N Critical Issues (Block Merge)" as fail', () => {
158
+ expect(parseWorkResult('### 3 Critical Issues (Block Merge)\n1. Bad migration', 'coordination')).toBe('failed');
159
+ });
160
+ it('detects "sub-issues need work" as fail', () => {
161
+ expect(parseWorkResult('2 sub-issues need work before this can proceed.', 'coordination')).toBe('failed');
162
+ });
163
+ it('detects "Parent issue marked Finished"', () => {
164
+ expect(parseWorkResult('Execution: Wave 1...Wave 2...Wave 3. Parent issue marked Finished in Linear.', 'coordination')).toBe('passed');
165
+ });
166
+ it('does not match coordination patterns for non-coordination work types', () => {
167
+ expect(parseWorkResult('All sub-issues completed.', 'development')).toBe('unknown');
168
+ expect(parseWorkResult('All sub-issues completed.', 'qa')).toBe('unknown');
169
+ });
170
+ it('checks fail patterns before pass patterns', () => {
171
+ expect(parseWorkResult('All 8/8 sub-issues completed.\n### Must Fix Before Merge\n1. Bad code', 'coordination')).toBe('failed');
172
+ });
173
+ });
174
+ // QA coordination with real agent output formats
175
+ describe('QA coordination real-world patterns', () => {
176
+ it('detects "Status: N Issues Found" as fail', () => {
177
+ expect(parseWorkResult('### Status: 3 Issues Found (1 Critical, 2 Minor)', 'qa-coordination')).toBe('failed');
178
+ });
179
+ it('detects "Must Fix Before Merge" in QA context as fail', () => {
180
+ expect(parseWorkResult('## QA Report\n### CRITICAL — Must Fix Before Merge\n1. Bad migration', 'qa')).toBe('failed');
181
+ });
182
+ it('detects "N Critical Issues (Block Merge)" in QA context as fail', () => {
183
+ expect(parseWorkResult('### 3 Critical Issues (Block Merge)\n1. Bad code', 'qa-coordination')).toBe('failed');
184
+ });
185
+ });
186
+ // Acceptance coordination with real agent output formats
187
+ describe('acceptance coordination real-world patterns', () => {
188
+ it('detects "Must Fix Before Merge" in acceptance context as fail', () => {
189
+ expect(parseWorkResult('## Acceptance Coordination Report\n### CRITICAL — Must Fix Before Merge', 'acceptance-coordination')).toBe('failed');
190
+ });
191
+ it('detects "N Critical Issues (Block Merge)" in acceptance context as fail', () => {
192
+ expect(parseWorkResult('### 3 Critical Issues (Block Merge)\n1. provision-trial.ts uses removed fields', 'acceptance-coordination')).toBe('failed');
193
+ });
194
+ });
195
+ // Unknown result tests
196
+ describe('unknown results', () => {
197
+ it('returns unknown for undefined message', () => {
198
+ expect(parseWorkResult(undefined, 'qa')).toBe('unknown');
199
+ });
200
+ it('returns unknown for empty string', () => {
201
+ expect(parseWorkResult('', 'qa')).toBe('unknown');
202
+ });
203
+ it('returns unknown for message without any markers or patterns', () => {
204
+ expect(parseWorkResult('Work completed successfully. All looks good.', 'qa')).toBe('unknown');
205
+ });
206
+ it('returns unknown for generic success messages without structured marker', () => {
207
+ expect(parseWorkResult('Everything passed! Great work.', 'qa')).toBe('unknown');
208
+ });
209
+ it('returns unknown for message with only whitespace', () => {
210
+ expect(parseWorkResult(' \n\n \t ', 'qa')).toBe('unknown');
211
+ });
212
+ });
213
+ // Priority / edge cases
214
+ describe('edge cases', () => {
215
+ it('prefers structured marker over heuristic patterns', () => {
216
+ const msg = '## QA Failed\n\nActually wait, it passed.\n\n<!-- WORK_RESULT:passed -->';
217
+ expect(parseWorkResult(msg, 'qa')).toBe('passed');
218
+ });
219
+ it('handles messages with multiple structured markers (takes first)', () => {
220
+ const msg = '<!-- WORK_RESULT:passed -->\nOops\n<!-- WORK_RESULT:failed -->';
221
+ expect(parseWorkResult(msg, 'qa')).toBe('passed');
222
+ });
223
+ it('handles very long messages', () => {
224
+ const long = 'x'.repeat(100000) +
225
+ '<!-- WORK_RESULT:passed -->' +
226
+ 'y'.repeat(100000);
227
+ expect(parseWorkResult(long, 'qa')).toBe('passed');
228
+ });
229
+ it('does not match partial markers', () => {
230
+ expect(parseWorkResult('WORK_RESULT:passed', 'qa')).toBe('unknown');
231
+ expect(parseWorkResult('<!-- WORK_RESULT:maybe -->', 'qa')).toBe('unknown');
232
+ });
233
+ });
234
+ });
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Progress Logger
3
+ *
4
+ * Append-only log for debugging agent activity.
5
+ * Format: timestamp|event_type|details
6
+ */
7
+ import type { ProgressLoggerConfig, ProgressEventType } from './state-types.js';
8
+ /**
9
+ * ProgressLogger appends events to a log file for debugging
10
+ */
11
+ export declare class ProgressLogger {
12
+ private readonly config;
13
+ private readonly logPath;
14
+ private stopped;
15
+ constructor(config: ProgressLoggerConfig);
16
+ /**
17
+ * Initialize the logger (create directory if needed)
18
+ */
19
+ init(): void;
20
+ /**
21
+ * Stop the logger
22
+ */
23
+ stop(): void;
24
+ /**
25
+ * Log an event
26
+ */
27
+ log(eventType: ProgressEventType, details: string | object): void;
28
+ /**
29
+ * Log agent start
30
+ */
31
+ logStart(details: {
32
+ issueId: string;
33
+ workType: string;
34
+ prompt: string;
35
+ }): void;
36
+ /**
37
+ * Log phase change
38
+ */
39
+ logPhase(phase: string): void;
40
+ /**
41
+ * Log tool call
42
+ */
43
+ logTool(toolName: string, input?: object): void;
44
+ /**
45
+ * Log error
46
+ */
47
+ logError(message: string, error?: Error | unknown): void;
48
+ /**
49
+ * Log recovery attempt
50
+ */
51
+ logRecovery(attempt: number, reason?: string): void;
52
+ /**
53
+ * Log completion
54
+ */
55
+ logComplete(details?: {
56
+ prUrl?: string;
57
+ message?: string;
58
+ }): void;
59
+ /**
60
+ * Log stop
61
+ */
62
+ logStop(reason: 'user_request' | 'timeout' | 'error'): void;
63
+ /**
64
+ * Rotate log file if it exceeds max size
65
+ */
66
+ private maybeRotate;
67
+ }
68
+ /**
69
+ * Create a progress logger for an agent
70
+ */
71
+ export declare function createProgressLogger(config: ProgressLoggerConfig): ProgressLogger;
72
+ //# sourceMappingURL=progress-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-logger.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/progress-logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAK/E;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,OAAO,CAAQ;gBAEX,MAAM,EAAE,oBAAoB;IAQxC;;OAEG;IACH,IAAI,IAAI,IAAI;IAOZ;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,GAAG,CAAC,SAAS,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAkBjE;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAI9E;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAI/C;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,IAAI;IAOxD;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAInD;;OAEG;IACH,WAAW,CAAC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAIjE;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,GAAG,OAAO,GAAG,IAAI;IAI3D;;OAEG;IACH,OAAO,CAAC,WAAW;CAkBpB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,cAAc,CAIjF"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Progress Logger
3
+ *
4
+ * Append-only log for debugging agent activity.
5
+ * Format: timestamp|event_type|details
6
+ */
7
+ import { appendFileSync, existsSync, mkdirSync, statSync, renameSync } from 'fs';
8
+ import { resolve, dirname } from 'path';
9
+ // Default max log size: 1MB
10
+ const DEFAULT_MAX_SIZE_BYTES = 1024 * 1024;
11
+ /**
12
+ * ProgressLogger appends events to a log file for debugging
13
+ */
14
+ export class ProgressLogger {
15
+ config;
16
+ logPath;
17
+ stopped = false;
18
+ constructor(config) {
19
+ this.config = {
20
+ ...config,
21
+ maxSizeBytes: config.maxSizeBytes ?? DEFAULT_MAX_SIZE_BYTES,
22
+ };
23
+ this.logPath = resolve(this.config.agentDir, 'progress.log');
24
+ }
25
+ /**
26
+ * Initialize the logger (create directory if needed)
27
+ */
28
+ init() {
29
+ const dir = dirname(this.logPath);
30
+ if (!existsSync(dir)) {
31
+ mkdirSync(dir, { recursive: true });
32
+ }
33
+ }
34
+ /**
35
+ * Stop the logger
36
+ */
37
+ stop() {
38
+ this.stopped = true;
39
+ }
40
+ /**
41
+ * Log an event
42
+ */
43
+ log(eventType, details) {
44
+ if (this.stopped)
45
+ return;
46
+ const timestamp = Date.now();
47
+ const detailsStr = typeof details === 'object' ? JSON.stringify(details) : details;
48
+ const line = `${timestamp}|${eventType}|${detailsStr}\n`;
49
+ try {
50
+ // Check if rotation is needed
51
+ this.maybeRotate();
52
+ // Append to log
53
+ appendFileSync(this.logPath, line);
54
+ }
55
+ catch (error) {
56
+ // Silently ignore errors - progress logging is best-effort
57
+ }
58
+ }
59
+ /**
60
+ * Log agent start
61
+ */
62
+ logStart(details) {
63
+ this.log('start', details);
64
+ }
65
+ /**
66
+ * Log phase change
67
+ */
68
+ logPhase(phase) {
69
+ this.log('phase', { phase });
70
+ }
71
+ /**
72
+ * Log tool call
73
+ */
74
+ logTool(toolName, input) {
75
+ this.log('tool', { toolName, input: input ? JSON.stringify(input).substring(0, 200) : undefined });
76
+ }
77
+ /**
78
+ * Log error
79
+ */
80
+ logError(message, error) {
81
+ this.log('error', {
82
+ message,
83
+ error: error instanceof Error ? error.message : String(error),
84
+ });
85
+ }
86
+ /**
87
+ * Log recovery attempt
88
+ */
89
+ logRecovery(attempt, reason) {
90
+ this.log('recovery', { attempt, reason });
91
+ }
92
+ /**
93
+ * Log completion
94
+ */
95
+ logComplete(details) {
96
+ this.log('complete', details ?? {});
97
+ }
98
+ /**
99
+ * Log stop
100
+ */
101
+ logStop(reason) {
102
+ this.log('stop', { reason });
103
+ }
104
+ /**
105
+ * Rotate log file if it exceeds max size
106
+ */
107
+ maybeRotate() {
108
+ try {
109
+ if (!existsSync(this.logPath))
110
+ return;
111
+ const stats = statSync(this.logPath);
112
+ if (stats.size >= this.config.maxSizeBytes) {
113
+ // Rotate: rename current to .old
114
+ const oldPath = `${this.logPath}.old`;
115
+ try {
116
+ renameSync(this.logPath, oldPath);
117
+ }
118
+ catch {
119
+ // Ignore rotation errors
120
+ }
121
+ }
122
+ }
123
+ catch {
124
+ // Ignore stat errors
125
+ }
126
+ }
127
+ }
128
+ /**
129
+ * Create a progress logger for an agent
130
+ */
131
+ export function createProgressLogger(config) {
132
+ const logger = new ProgressLogger(config);
133
+ logger.init();
134
+ return logger;
135
+ }