@zhixuan92/multi-model-agent-core 4.0.3 → 4.0.5

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 (294) hide show
  1. package/README.md +10 -12
  2. package/dist/events/cloud-events.d.ts +1 -3
  3. package/dist/events/cloud-events.d.ts.map +1 -1
  4. package/dist/events/event-builder.d.ts +1 -1
  5. package/dist/events/event-builder.d.ts.map +1 -1
  6. package/dist/events/observability-events.d.ts +3 -111
  7. package/dist/events/observability-events.d.ts.map +1 -1
  8. package/dist/events/observability-events.js +0 -58
  9. package/dist/events/observability-events.js.map +1 -1
  10. package/dist/events/telemetry-types.d.ts +3 -3
  11. package/dist/events/telemetry-types.js +1 -1
  12. package/dist/events/telemetry-types.js.map +1 -1
  13. package/dist/index.d.ts +2 -7
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +1 -7
  16. package/dist/index.js.map +1 -1
  17. package/dist/intake/brief-compiler-slots/debug.d.ts +0 -26
  18. package/dist/intake/brief-compiler-slots/debug.d.ts.map +1 -1
  19. package/dist/intake/brief-compiler-slots/debug.js +5 -44
  20. package/dist/intake/brief-compiler-slots/debug.js.map +1 -1
  21. package/dist/intake/brief-compiler-slots/delegate.d.ts +0 -24
  22. package/dist/intake/brief-compiler-slots/delegate.d.ts.map +1 -1
  23. package/dist/intake/brief-compiler-slots/delegate.js +2 -45
  24. package/dist/intake/brief-compiler-slots/delegate.js.map +1 -1
  25. package/dist/intake/brief-compiler-slots/research.d.ts +18 -0
  26. package/dist/intake/brief-compiler-slots/research.d.ts.map +1 -0
  27. package/dist/intake/brief-compiler-slots/research.js +43 -0
  28. package/dist/intake/brief-compiler-slots/research.js.map +1 -0
  29. package/dist/intake/brief-compiler-slots/review.d.ts +0 -23
  30. package/dist/intake/brief-compiler-slots/review.d.ts.map +1 -1
  31. package/dist/intake/brief-compiler-slots/review.js +0 -62
  32. package/dist/intake/brief-compiler-slots/review.js.map +1 -1
  33. package/dist/lifecycle/diff-tracker.d.ts +72 -0
  34. package/dist/lifecycle/diff-tracker.d.ts.map +1 -0
  35. package/dist/lifecycle/diff-tracker.js +316 -0
  36. package/dist/lifecycle/diff-tracker.js.map +1 -0
  37. package/dist/lifecycle/handlers/prepare-execution-context-handler.d.ts +1 -1
  38. package/dist/lifecycle/handlers/prepare-execution-context-handler.d.ts.map +1 -1
  39. package/dist/lifecycle/handlers/prepare-execution-context-handler.js +23 -1
  40. package/dist/lifecycle/handlers/prepare-execution-context-handler.js.map +1 -1
  41. package/dist/lifecycle/handlers/quality-chain-handlers.d.ts.map +1 -1
  42. package/dist/lifecycle/handlers/quality-chain-handlers.js +57 -6
  43. package/dist/lifecycle/handlers/quality-chain-handlers.js.map +1 -1
  44. package/dist/lifecycle/handlers/review-diff-handler.d.ts.map +1 -1
  45. package/dist/lifecycle/handlers/review-diff-handler.js +38 -12
  46. package/dist/lifecycle/handlers/review-diff-handler.js.map +1 -1
  47. package/dist/lifecycle/handlers/spec-chain-handlers.d.ts.map +1 -1
  48. package/dist/lifecycle/handlers/spec-chain-handlers.js +38 -10
  49. package/dist/lifecycle/handlers/spec-chain-handlers.js.map +1 -1
  50. package/dist/lifecycle/handlers/terminal-handlers.d.ts.map +1 -1
  51. package/dist/lifecycle/handlers/terminal-handlers.js +17 -2
  52. package/dist/lifecycle/handlers/terminal-handlers.js.map +1 -1
  53. package/dist/lifecycle/merge-stage-stats.d.ts +27 -0
  54. package/dist/lifecycle/merge-stage-stats.d.ts.map +1 -1
  55. package/dist/lifecycle/merge-stage-stats.js +56 -0
  56. package/dist/lifecycle/merge-stage-stats.js.map +1 -1
  57. package/dist/lifecycle/stage-plan-types.d.ts +15 -0
  58. package/dist/lifecycle/stage-plan-types.d.ts.map +1 -1
  59. package/dist/lifecycle/stage-progression.d.ts.map +1 -1
  60. package/dist/lifecycle/stage-progression.js +1 -0
  61. package/dist/lifecycle/stage-progression.js.map +1 -1
  62. package/dist/lifecycle/task-runner.js +1 -1
  63. package/dist/lifecycle/task-runner.js.map +1 -1
  64. package/dist/providers/provider-factory.d.ts.map +1 -1
  65. package/dist/providers/provider-factory.js +6 -0
  66. package/dist/providers/provider-factory.js.map +1 -1
  67. package/dist/reporting/headline-templates/audit.d.ts.map +1 -1
  68. package/dist/reporting/headline-templates/audit.js +17 -8
  69. package/dist/reporting/headline-templates/audit.js.map +1 -1
  70. package/dist/reporting/headline-templates/debug.d.ts +22 -3
  71. package/dist/reporting/headline-templates/debug.d.ts.map +1 -1
  72. package/dist/reporting/headline-templates/debug.js +38 -8
  73. package/dist/reporting/headline-templates/debug.js.map +1 -1
  74. package/dist/reporting/headline-templates/delegate.d.ts.map +1 -1
  75. package/dist/reporting/headline-templates/delegate.js +14 -3
  76. package/dist/reporting/headline-templates/delegate.js.map +1 -1
  77. package/dist/reporting/headline-templates/execute-plan.d.ts.map +1 -1
  78. package/dist/reporting/headline-templates/execute-plan.js +17 -8
  79. package/dist/reporting/headline-templates/execute-plan.js.map +1 -1
  80. package/dist/reporting/headline-templates/research.d.ts +3 -0
  81. package/dist/reporting/headline-templates/research.d.ts.map +1 -0
  82. package/dist/reporting/headline-templates/research.js +23 -0
  83. package/dist/reporting/headline-templates/research.js.map +1 -0
  84. package/dist/reporting/headline-templates/review.d.ts.map +1 -1
  85. package/dist/reporting/headline-templates/review.js +23 -6
  86. package/dist/reporting/headline-templates/review.js.map +1 -1
  87. package/dist/reporting/headline-templates/verify.d.ts.map +1 -1
  88. package/dist/reporting/headline-templates/verify.js +23 -6
  89. package/dist/reporting/headline-templates/verify.js.map +1 -1
  90. package/dist/reporting/headline-text.d.ts +5 -0
  91. package/dist/reporting/headline-text.d.ts.map +1 -1
  92. package/dist/reporting/headline-text.js +36 -5
  93. package/dist/reporting/headline-text.js.map +1 -1
  94. package/dist/reporting/report-parser-slots/research-report.d.ts +30 -0
  95. package/dist/reporting/report-parser-slots/research-report.d.ts.map +1 -0
  96. package/dist/reporting/report-parser-slots/research-report.js +94 -0
  97. package/dist/reporting/report-parser-slots/research-report.js.map +1 -0
  98. package/dist/reporting/report-parser-slots/verify-report.d.ts +17 -0
  99. package/dist/reporting/report-parser-slots/verify-report.d.ts.map +1 -1
  100. package/dist/reporting/report-parser-slots/verify-report.js +45 -3
  101. package/dist/reporting/report-parser-slots/verify-report.js.map +1 -1
  102. package/dist/reporting/severity.d.ts +22 -0
  103. package/dist/reporting/severity.d.ts.map +1 -1
  104. package/dist/reporting/severity.js +36 -0
  105. package/dist/reporting/severity.js.map +1 -1
  106. package/dist/review/annotator-output-parser.d.ts.map +1 -1
  107. package/dist/review/annotator-output-parser.js +94 -14
  108. package/dist/review/annotator-output-parser.js.map +1 -1
  109. package/dist/review/annotator-prompt-builder.d.ts +20 -0
  110. package/dist/review/annotator-prompt-builder.d.ts.map +1 -1
  111. package/dist/review/annotator-prompt-builder.js +54 -3
  112. package/dist/review/annotator-prompt-builder.js.map +1 -1
  113. package/dist/review/reviewer-engine.d.ts +15 -1
  114. package/dist/review/reviewer-engine.d.ts.map +1 -1
  115. package/dist/review/reviewer-engine.js.map +1 -1
  116. package/dist/review/reviewer-output-parser.d.ts.map +1 -1
  117. package/dist/review/reviewer-output-parser.js +171 -16
  118. package/dist/review/reviewer-output-parser.js.map +1 -1
  119. package/dist/review/reviewer-prompt-builder.d.ts +5 -13
  120. package/dist/review/reviewer-prompt-builder.d.ts.map +1 -1
  121. package/dist/review/reviewer-prompt-builder.js.map +1 -1
  122. package/dist/review/templates/annotator-audit.d.ts.map +1 -1
  123. package/dist/review/templates/annotator-audit.js +13 -0
  124. package/dist/review/templates/annotator-audit.js.map +1 -1
  125. package/dist/review/templates/annotator-debug.d.ts.map +1 -1
  126. package/dist/review/templates/annotator-debug.js +11 -1
  127. package/dist/review/templates/annotator-debug.js.map +1 -1
  128. package/dist/review/templates/annotator-investigate.d.ts.map +1 -1
  129. package/dist/review/templates/annotator-investigate.js +10 -1
  130. package/dist/review/templates/annotator-investigate.js.map +1 -1
  131. package/dist/review/templates/annotator-review.d.ts.map +1 -1
  132. package/dist/review/templates/annotator-review.js +10 -0
  133. package/dist/review/templates/annotator-review.js.map +1 -1
  134. package/dist/review/templates/annotator-shared.d.ts +7 -1
  135. package/dist/review/templates/annotator-shared.d.ts.map +1 -1
  136. package/dist/review/templates/annotator-shared.js +18 -29
  137. package/dist/review/templates/annotator-shared.js.map +1 -1
  138. package/dist/review/templates/annotator-verify.d.ts.map +1 -1
  139. package/dist/review/templates/annotator-verify.js +11 -1
  140. package/dist/review/templates/annotator-verify.js.map +1 -1
  141. package/dist/review/templates/diff-review.d.ts +8 -0
  142. package/dist/review/templates/diff-review.d.ts.map +1 -1
  143. package/dist/review/templates/diff-review.js +34 -2
  144. package/dist/review/templates/diff-review.js.map +1 -1
  145. package/dist/review/templates/finding-criteria.d.ts +15 -0
  146. package/dist/review/templates/finding-criteria.d.ts.map +1 -0
  147. package/dist/review/templates/finding-criteria.js +39 -0
  148. package/dist/review/templates/finding-criteria.js.map +1 -0
  149. package/dist/review/templates/quality-review-artifact.d.ts +13 -0
  150. package/dist/review/templates/quality-review-artifact.d.ts.map +1 -1
  151. package/dist/review/templates/quality-review-artifact.js +41 -3
  152. package/dist/review/templates/quality-review-artifact.js.map +1 -1
  153. package/dist/review/templates/quality-review-audit.d.ts.map +1 -1
  154. package/dist/review/templates/quality-review-audit.js +3 -2
  155. package/dist/review/templates/quality-review-audit.js.map +1 -1
  156. package/dist/review/templates/quality-review-debug.d.ts.map +1 -1
  157. package/dist/review/templates/quality-review-debug.js +3 -2
  158. package/dist/review/templates/quality-review-debug.js.map +1 -1
  159. package/dist/review/templates/quality-review-investigate.d.ts.map +1 -1
  160. package/dist/review/templates/quality-review-investigate.js +3 -2
  161. package/dist/review/templates/quality-review-investigate.js.map +1 -1
  162. package/dist/review/templates/quality-review-review.d.ts.map +1 -1
  163. package/dist/review/templates/quality-review-review.js +3 -2
  164. package/dist/review/templates/quality-review-review.js.map +1 -1
  165. package/dist/review/templates/quality-review-verify.d.ts.map +1 -1
  166. package/dist/review/templates/quality-review-verify.js +3 -2
  167. package/dist/review/templates/quality-review-verify.js.map +1 -1
  168. package/dist/review/templates/shared.d.ts +22 -5
  169. package/dist/review/templates/shared.d.ts.map +1 -1
  170. package/dist/review/templates/spec-review.d.ts +15 -0
  171. package/dist/review/templates/spec-review.d.ts.map +1 -1
  172. package/dist/review/templates/spec-review.js +43 -3
  173. package/dist/review/templates/spec-review.js.map +1 -1
  174. package/dist/stores/file-backed-context-block-store.d.ts +5 -1
  175. package/dist/stores/file-backed-context-block-store.d.ts.map +1 -1
  176. package/dist/stores/file-backed-context-block-store.js +16 -19
  177. package/dist/stores/file-backed-context-block-store.js.map +1 -1
  178. package/dist/stores/project-context-registry.d.ts +5 -3
  179. package/dist/stores/project-context-registry.d.ts.map +1 -1
  180. package/dist/stores/project-context-registry.js.map +1 -1
  181. package/dist/tool-surface/openapi-generator.d.ts.map +1 -1
  182. package/dist/tool-surface/openapi-generator.js +4 -4
  183. package/dist/tool-surface/openapi-generator.js.map +1 -1
  184. package/dist/tool-surface/register-all-tools.js +3 -3
  185. package/dist/tool-surface/register-all-tools.js.map +1 -1
  186. package/dist/tools/audit/implementer-criteria.d.ts +17 -0
  187. package/dist/tools/audit/implementer-criteria.d.ts.map +1 -0
  188. package/dist/tools/audit/implementer-criteria.js +36 -0
  189. package/dist/tools/audit/implementer-criteria.js.map +1 -0
  190. package/dist/tools/audit/tool-config.d.ts.map +1 -1
  191. package/dist/tools/audit/tool-config.js +24 -6
  192. package/dist/tools/audit/tool-config.js.map +1 -1
  193. package/dist/tools/debug/implementer-criteria.d.ts +12 -0
  194. package/dist/tools/debug/implementer-criteria.d.ts.map +1 -0
  195. package/dist/tools/debug/implementer-criteria.js +29 -0
  196. package/dist/tools/debug/implementer-criteria.js.map +1 -0
  197. package/dist/tools/debug/tool-config.d.ts.map +1 -1
  198. package/dist/tools/debug/tool-config.js +18 -4
  199. package/dist/tools/debug/tool-config.js.map +1 -1
  200. package/dist/tools/execute-plan/tool-config.d.ts.map +1 -1
  201. package/dist/tools/execute-plan/tool-config.js +5 -1
  202. package/dist/tools/execute-plan/tool-config.js.map +1 -1
  203. package/dist/tools/index.d.ts +0 -1
  204. package/dist/tools/index.d.ts.map +1 -1
  205. package/dist/tools/index.js +0 -1
  206. package/dist/tools/index.js.map +1 -1
  207. package/dist/tools/investigate/implementer-criteria.d.ts +17 -0
  208. package/dist/tools/investigate/implementer-criteria.d.ts.map +1 -0
  209. package/dist/tools/investigate/implementer-criteria.js +33 -0
  210. package/dist/tools/investigate/implementer-criteria.js.map +1 -0
  211. package/dist/tools/investigate/tool-config.d.ts +13 -1
  212. package/dist/tools/investigate/tool-config.d.ts.map +1 -1
  213. package/dist/tools/investigate/tool-config.js +34 -4
  214. package/dist/tools/investigate/tool-config.js.map +1 -1
  215. package/dist/tools/research/implementer-criteria.d.ts +15 -0
  216. package/dist/tools/research/implementer-criteria.d.ts.map +1 -0
  217. package/dist/tools/research/implementer-criteria.js +37 -0
  218. package/dist/tools/research/implementer-criteria.js.map +1 -0
  219. package/dist/tools/{explore → research}/schema.d.ts +2 -3
  220. package/dist/tools/research/schema.d.ts.map +1 -0
  221. package/dist/tools/{explore → research}/schema.js +10 -16
  222. package/dist/tools/research/schema.js.map +1 -0
  223. package/dist/tools/research/tool-config.d.ts +20 -0
  224. package/dist/tools/research/tool-config.d.ts.map +1 -0
  225. package/dist/tools/research/tool-config.js +51 -0
  226. package/dist/tools/research/tool-config.js.map +1 -0
  227. package/dist/tools/retry/tool-config.d.ts.map +1 -1
  228. package/dist/tools/retry/tool-config.js +27 -4
  229. package/dist/tools/retry/tool-config.js.map +1 -1
  230. package/dist/tools/review/implementer-criteria.d.ts +11 -0
  231. package/dist/tools/review/implementer-criteria.d.ts.map +1 -0
  232. package/dist/tools/review/implementer-criteria.js +27 -0
  233. package/dist/tools/review/implementer-criteria.js.map +1 -0
  234. package/dist/tools/review/tool-config.d.ts.map +1 -1
  235. package/dist/tools/review/tool-config.js +43 -4
  236. package/dist/tools/review/tool-config.js.map +1 -1
  237. package/dist/tools/verify/implementer-criteria.d.ts +12 -0
  238. package/dist/tools/verify/implementer-criteria.d.ts.map +1 -0
  239. package/dist/tools/verify/implementer-criteria.js +29 -0
  240. package/dist/tools/verify/implementer-criteria.js.map +1 -0
  241. package/dist/tools/verify/tool-config.d.ts.map +1 -1
  242. package/dist/tools/verify/tool-config.js +18 -4
  243. package/dist/tools/verify/tool-config.js.map +1 -1
  244. package/dist/types/enums.d.ts +1 -11
  245. package/dist/types/enums.d.ts.map +1 -1
  246. package/dist/types/enums.js +2 -4
  247. package/dist/types/enums.js.map +1 -1
  248. package/package.json +12 -40
  249. package/dist/intake/brief-compiler-slots/audit.d.ts +0 -23
  250. package/dist/intake/brief-compiler-slots/audit.d.ts.map +0 -1
  251. package/dist/intake/brief-compiler-slots/audit.js +0 -61
  252. package/dist/intake/brief-compiler-slots/audit.js.map +0 -1
  253. package/dist/intake/brief-compiler-slots/explore.d.ts +0 -43
  254. package/dist/intake/brief-compiler-slots/explore.d.ts.map +0 -1
  255. package/dist/intake/brief-compiler-slots/explore.js +0 -116
  256. package/dist/intake/brief-compiler-slots/explore.js.map +0 -1
  257. package/dist/intake/brief-compiler-slots/investigate.d.ts +0 -26
  258. package/dist/intake/brief-compiler-slots/investigate.d.ts.map +0 -1
  259. package/dist/intake/brief-compiler-slots/investigate.js +0 -42
  260. package/dist/intake/brief-compiler-slots/investigate.js.map +0 -1
  261. package/dist/intake/brief-compiler-slots/verify.d.ts +0 -21
  262. package/dist/intake/brief-compiler-slots/verify.d.ts.map +0 -1
  263. package/dist/intake/brief-compiler-slots/verify.js +0 -62
  264. package/dist/intake/brief-compiler-slots/verify.js.map +0 -1
  265. package/dist/reporting/compose-explore-headline.d.ts +0 -14
  266. package/dist/reporting/compose-explore-headline.d.ts.map +0 -1
  267. package/dist/reporting/compose-explore-headline.js +0 -14
  268. package/dist/reporting/compose-explore-headline.js.map +0 -1
  269. package/dist/reporting/derive-explore-status.d.ts +0 -18
  270. package/dist/reporting/derive-explore-status.d.ts.map +0 -1
  271. package/dist/reporting/derive-explore-status.js +0 -15
  272. package/dist/reporting/derive-explore-status.js.map +0 -1
  273. package/dist/reporting/headline-templates/explore.d.ts +0 -3
  274. package/dist/reporting/headline-templates/explore.d.ts.map +0 -1
  275. package/dist/reporting/headline-templates/explore.js +0 -13
  276. package/dist/reporting/headline-templates/explore.js.map +0 -1
  277. package/dist/reporting/parse-explore-report.d.ts +0 -38
  278. package/dist/reporting/parse-explore-report.d.ts.map +0 -1
  279. package/dist/reporting/parse-explore-report.js +0 -185
  280. package/dist/reporting/parse-explore-report.js.map +0 -1
  281. package/dist/reporting/report-parser-slots/explore-report.d.ts +0 -17
  282. package/dist/reporting/report-parser-slots/explore-report.d.ts.map +0 -1
  283. package/dist/reporting/report-parser-slots/explore-report.js +0 -9
  284. package/dist/reporting/report-parser-slots/explore-report.js.map +0 -1
  285. package/dist/research/explore-orchestrator.d.ts +0 -14
  286. package/dist/research/explore-orchestrator.d.ts.map +0 -1
  287. package/dist/research/explore-orchestrator.js +0 -362
  288. package/dist/research/explore-orchestrator.js.map +0 -1
  289. package/dist/tools/explore/schema.d.ts.map +0 -1
  290. package/dist/tools/explore/schema.js.map +0 -1
  291. package/dist/tools/explore/tool-config.d.ts +0 -7
  292. package/dist/tools/explore/tool-config.d.ts.map +0 -1
  293. package/dist/tools/explore/tool-config.js +0 -36
  294. package/dist/tools/explore/tool-config.js.map +0 -1
@@ -1,21 +1,30 @@
1
1
  import { isNotApplicable } from '../not-applicable.js';
2
- import { countHighOrCritical } from '../severity.js';
2
+ import { countHighOrCritical, parseNarrativeFindings } from '../severity.js';
3
3
  export const auditHeadlineTemplate = {
4
4
  compose({ report, status, runResult, task }) {
5
5
  const r = report;
6
6
  const reportInapplicable = !r || isNotApplicable(r);
7
- // Source priority for findings (4.0.3+ Gap 2 fix):
7
+ // Source priority for findings (4.0.3+):
8
8
  // 1. Structured report's `findings` (rare — only when the worker
9
9
  // emitted proper JSON matching the audit reportSchema).
10
- // 2. runResult.annotatedFindings (canonical narrative-path source,
10
+ // 2. runResult.annotatedFindings (canonical narrative-path source
11
11
  // populated by the quality-chain handler when verdict='annotated').
12
- // Pre-fix the composer only read (1) — when the worker emitted
13
- // narrative `## Finding N:` blocks, the structuredReport fallback
14
- // had no `findings` field, so the headline reported "0 findings"
15
- // even when the annotator returned dozens.
12
+ // 3. NEW: parseNarrativeFindings(runResult.output) — recovers
13
+ // findings directly from the implementer's `## Finding N:`
14
+ // output when the annotator errored (parse failure, exhaustion).
15
+ // Without this third fallback, audits where the annotator
16
+ // failed report `0 findings (0 high)` even though the
17
+ // implementer's narrative carried valid findings.
16
18
  const reportFindings = !reportInapplicable && Array.isArray(r?.findings) ? r.findings : [];
17
19
  const annotated = runResult?.annotatedFindings ?? [];
18
- const findings = reportFindings.length > 0 ? reportFindings : annotated;
20
+ let findings = reportFindings.length > 0
21
+ ? reportFindings
22
+ : annotated;
23
+ if (findings.length === 0 && typeof runResult?.output === 'string') {
24
+ const narrative = parseNarrativeFindings(runResult.output);
25
+ if (narrative.length > 0)
26
+ findings = narrative;
27
+ }
19
28
  if (findings.length === 0 && reportInapplicable) {
20
29
  return `[${status}] audit completed`;
21
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/reporting/headline-templates/audit.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,CAAC,MAAM,qBAAqB,GAAqB;IACrD,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE;QACzC,MAAM,CAAC,GAAG,MAAiD,CAAC;QAC5D,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC;QAEpD,mDAAmD;QACnD,mEAAmE;QACnE,6DAA6D;QAC7D,qEAAqE;QACrE,yEAAyE;QACzE,+DAA+D;QAC/D,kEAAkE;QAClE,iEAAiE;QACjE,2CAA2C;QAC3C,MAAM,cAAc,GAAG,CAAC,kBAAkB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5F,MAAM,SAAS,GAAG,SAAS,EAAE,iBAAiB,IAAI,EAAE,CAAC;QACrD,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC;QAExE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,kBAAkB,EAAE,CAAC;YAChD,OAAO,IAAI,MAAM,mBAAmB,CAAC;QACvC,CAAC;QAED,MAAM,IAAI,GAAG,mBAAmB,CAAC,QAAyC,CAAC,CAAC;QAE5E,mEAAmE;QACnE,gEAAgE;QAChE,kDAAkD;QAClD,MAAM,IAAI,GACR,CAAC,CAAC,kBAAkB,IAAI,OAAO,CAAC,EAAE,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAE,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;eAC/E,IAA6C,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;eAC9D,EAAE,CAAC;QAER,OAAO,IAAI,MAAM,WAAW,IAAI,KAAK,QAAQ,CAAC,MAAM,cAAc,IAAI,QAAQ,CAAC;IACjF,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/reporting/headline-templates/audit.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAE7E,MAAM,CAAC,MAAM,qBAAqB,GAAqB;IACrD,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE;QACzC,MAAM,CAAC,GAAG,MAAiD,CAAC;QAC5D,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC;QAEpD,yCAAyC;QACzC,mEAAmE;QACnE,6DAA6D;QAC7D,oEAAoE;QACpE,yEAAyE;QACzE,gEAAgE;QAChE,gEAAgE;QAChE,sEAAsE;QACtE,+DAA+D;QAC/D,2DAA2D;QAC3D,uDAAuD;QACvD,MAAM,cAAc,GAAG,CAAC,kBAAkB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5F,MAAM,SAAS,GAAG,SAAS,EAAE,iBAAiB,IAAI,EAAE,CAAC;QACrD,IAAI,QAAQ,GACV,cAAc,CAAC,MAAM,GAAG,CAAC;YACvB,CAAC,CAAE,cAAgD;YACnD,CAAC,CAAE,SAA2C,CAAC;QACnD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,SAAS,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;YACnE,MAAM,SAAS,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YAC3D,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;gBAAE,QAAQ,GAAG,SAAS,CAAC;QACjD,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,kBAAkB,EAAE,CAAC;YAChD,OAAO,IAAI,MAAM,mBAAmB,CAAC;QACvC,CAAC;QAED,MAAM,IAAI,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAE3C,mEAAmE;QACnE,gEAAgE;QAChE,kDAAkD;QAClD,MAAM,IAAI,GACR,CAAC,CAAC,kBAAkB,IAAI,OAAO,CAAC,EAAE,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAE,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;eAC/E,IAA6C,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;eAC9D,EAAE,CAAC;QAER,OAAO,IAAI,MAAM,WAAW,IAAI,KAAK,QAAQ,CAAC,MAAM,cAAc,IAAI,QAAQ,CAAC;IACjF,CAAC;CACF,CAAC"}
@@ -1,8 +1,27 @@
1
1
  import type { HeadlineTemplate } from '../headline-composer.js';
2
2
  /**
3
- * Compose a terminal headline for debug. Matches the composeTerminalHeadline
4
- * format that the legacy executor produced: "debug: 1/1 tasks complete".
5
- * Debug always dispatches exactly 1 task.
3
+ * Compose a terminal headline for debug.
4
+ *
5
+ * Tool sweep #4 rewrite: bring debug into the same shape as audit and
6
+ * review/verify so operator-facing logs stay consistent across tools:
7
+ *
8
+ * [ok] debug <path>: 3 findings (0 high)
9
+ * [error] debug: 1 findings (1 high)
10
+ * [ok] debug completed
11
+ *
12
+ * Previously emitted "debug: 1/1 tasks complete" with no status prefix
13
+ * and no findings count — operator could not tell ok from error and
14
+ * had no signal about how many real findings landed.
15
+ *
16
+ * Source priority for findings (parallel to audit):
17
+ * 1. runResult.annotatedFindings (canonical — annotator's structured
18
+ * output when verdict='annotated').
19
+ * 2. parseNarrativeFindings(runResult.output) — recovers `## Finding N:`
20
+ * blocks from the implementer's narrative when the annotator errored.
21
+ *
22
+ * Note: debug's reportSchema.parse is intentionally a thrower (the tool
23
+ * doesn't emit a structured report), so `report` is always notApplicable
24
+ * here — there's no `report.findings` source to read.
6
25
  */
7
26
  export declare const debugHeadlineTemplate: HeadlineTemplate;
8
27
  //# sourceMappingURL=debug.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../src/reporting/headline-templates/debug.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,gBAQnC,CAAC"}
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../src/reporting/headline-templates/debug.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,qBAAqB,EAAE,gBAsBnC,CAAC"}
@@ -1,15 +1,45 @@
1
+ import { countHighOrCritical, parseNarrativeFindings } from '../severity.js';
1
2
  /**
2
- * Compose a terminal headline for debug. Matches the composeTerminalHeadline
3
- * format that the legacy executor produced: "debug: 1/1 tasks complete".
4
- * Debug always dispatches exactly 1 task.
3
+ * Compose a terminal headline for debug.
4
+ *
5
+ * Tool sweep #4 rewrite: bring debug into the same shape as audit and
6
+ * review/verify so operator-facing logs stay consistent across tools:
7
+ *
8
+ * [ok] debug <path>: 3 findings (0 high)
9
+ * [error] debug: 1 findings (1 high)
10
+ * [ok] debug completed
11
+ *
12
+ * Previously emitted "debug: 1/1 tasks complete" with no status prefix
13
+ * and no findings count — operator could not tell ok from error and
14
+ * had no signal about how many real findings landed.
15
+ *
16
+ * Source priority for findings (parallel to audit):
17
+ * 1. runResult.annotatedFindings (canonical — annotator's structured
18
+ * output when verdict='annotated').
19
+ * 2. parseNarrativeFindings(runResult.output) — recovers `## Finding N:`
20
+ * blocks from the implementer's narrative when the annotator errored.
21
+ *
22
+ * Note: debug's reportSchema.parse is intentionally a thrower (the tool
23
+ * doesn't emit a structured report), so `report` is always notApplicable
24
+ * here — there's no `report.findings` source to read.
5
25
  */
6
26
  export const debugHeadlineTemplate = {
7
- compose({ report }) {
8
- const r = report;
9
- if (r && typeof r.rootCause === 'string' && r.rootCause.length > 0) {
10
- return `debug: root cause ${r.rootCause}`;
27
+ compose({ status, runResult, task }) {
28
+ const annotated = runResult?.annotatedFindings ?? [];
29
+ let findings = annotated;
30
+ if (findings.length === 0 && typeof runResult?.output === 'string') {
31
+ const narrative = parseNarrativeFindings(runResult.output);
32
+ if (narrative.length > 0)
33
+ findings = narrative;
11
34
  }
12
- return 'debug: 1/1 tasks complete';
35
+ const path = task?.filePaths?.[0] || '';
36
+ if (findings.length === 0 && !path) {
37
+ return `[${status}] debug completed`;
38
+ }
39
+ const high = countHighOrCritical(findings);
40
+ return path
41
+ ? `[${status}] debug ${path}: ${findings.length} findings (${high} high)`
42
+ : `[${status}] debug: ${findings.length} findings (${high} high)`;
13
43
  },
14
44
  };
15
45
  //# sourceMappingURL=debug.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"debug.js","sourceRoot":"","sources":["../../../src/reporting/headline-templates/debug.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAqB;IACrD,OAAO,CAAC,EAAE,MAAM,EAAE;QAChB,MAAM,CAAC,GAAG,MAA6C,CAAC;QACxD,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnE,OAAO,uBAAuB,CAAC,CAAC,SAAS,EAAE,CAAC;QAC9C,CAAC;QACD,OAAO,2BAA2B,CAAC;IACrC,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"debug.js","sourceRoot":"","sources":["../../../src/reporting/headline-templates/debug.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAqB;IACrD,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE;QACjC,MAAM,SAAS,GAAG,SAAS,EAAE,iBAAiB,IAAI,EAAE,CAAC;QACrD,IAAI,QAAQ,GACV,SAA0C,CAAC;QAC7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,SAAS,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;YACnE,MAAM,SAAS,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YAC3D,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;gBAAE,QAAQ,GAAG,SAAS,CAAC;QACjD,CAAC;QAED,MAAM,IAAI,GACP,IAA6C,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEvE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACnC,OAAO,IAAI,MAAM,mBAAmB,CAAC;QACvC,CAAC;QAED,MAAM,IAAI,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC3C,OAAO,IAAI;YACT,CAAC,CAAC,IAAI,MAAM,WAAW,IAAI,KAAK,QAAQ,CAAC,MAAM,cAAc,IAAI,QAAQ;YACzE,CAAC,CAAC,IAAI,MAAM,YAAY,QAAQ,CAAC,MAAM,cAAc,IAAI,QAAQ,CAAC;IACtE,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"delegate.d.ts","sourceRoot":"","sources":["../../../src/reporting/headline-templates/delegate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAKhE,eAAO,MAAM,wBAAwB,EAAE,gBA+BtC,CAAC"}
1
+ {"version":3,"file":"delegate.d.ts","sourceRoot":"","sources":["../../../src/reporting/headline-templates/delegate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAKhE,eAAO,MAAM,wBAAwB,EAAE,gBA0CtC,CAAC"}
@@ -16,16 +16,27 @@ export const delegateHeadlineTemplate = {
16
16
  const runFiles = Array.isArray(runResult?.filesWritten) ? runResult.filesWritten : [];
17
17
  const fileCount = reportFiles.length > 0 ? reportFiles.length : runFiles.length;
18
18
  if (reportInapplicable && fileCount === 0) {
19
- return `[${status}] no structured report available`;
19
+ return `[${status}] delegate: no structured report available`;
20
20
  }
21
21
  // Gap 12 fix (4.0.3+): trim worker's narrative `summary` to first
22
22
  // sentence (or 80-char truncate). Pre-fix, the entire summary —
23
23
  // sometimes multi-sentence prose ending mid-thought — was inlined
24
24
  // into the headline.
25
- const rawSummary = !reportInapplicable && typeof r?.summary === 'string' ? r.summary : '';
25
+ //
26
+ // Tool sweep #6 follow-up: when the structured report carries no
27
+ // summary, fall back to the worker's `output` text (also trimmed to
28
+ // first sentence) so the headline is informative even on no-op /
29
+ // 0-file outcomes. Pre-fix, those collapsed to `[incomplete] (0
30
+ // files)` with NO clue why.
31
+ const rawSummary = (!reportInapplicable && typeof r?.summary === 'string' && r.summary.length > 0)
32
+ ? r.summary
33
+ : (typeof runResult?.output === 'string' ? runResult.output : '');
26
34
  const summary = firstSentenceOrTruncate(rawSummary);
27
35
  const summaryClause = summary.length > 0 ? ` ${summary}` : '';
28
- return `[${status}]${summaryClause} (${fileCount} file${fileCount === 1 ? '' : 's'})`;
36
+ // Tool sweep #6 follow-up: prefix with `delegate:` for parity with
37
+ // audit / review / verify / debug / investigate headlines so the
38
+ // operator can tell the route at a glance.
39
+ return `[${status}] delegate:${summaryClause} (${fileCount} file${fileCount === 1 ? '' : 's'})`;
29
40
  },
30
41
  };
31
42
  //# sourceMappingURL=delegate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"delegate.js","sourceRoot":"","sources":["../../../src/reporting/headline-templates/delegate.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,MAAM,CAAC,MAAM,wBAAwB,GAAqB;IACxD,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE;QACnC,MAAM,CAAC,GAAG,MAA8D,CAAC;QACzE,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC;QAEpD,qDAAqD;QACrD,kEAAkE;QAClE,2DAA2D;QAC3D,8DAA8D;QAC9D,6DAA6D;QAC7D,kEAAkE;QAClE,yDAAyD;QACzD,0BAA0B;QAC1B,MAAM,WAAW,GAAG,CAAC,kBAAkB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QACjG,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,SAAU,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QACvF,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAEhF,IAAI,kBAAkB,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;YAC1C,OAAO,IAAI,MAAM,kCAAkC,CAAC;QACtD,CAAC;QAED,kEAAkE;QAClE,gEAAgE;QAChE,kEAAkE;QAClE,qBAAqB;QACrB,MAAM,UAAU,GAAG,CAAC,kBAAkB,IAAI,OAAO,CAAC,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3F,MAAM,OAAO,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC;QAEpD,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,OAAO,IAAI,MAAM,IAAI,aAAa,KAAK,SAAS,QAAQ,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IACxF,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"delegate.js","sourceRoot":"","sources":["../../../src/reporting/headline-templates/delegate.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,MAAM,CAAC,MAAM,wBAAwB,GAAqB;IACxD,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE;QACnC,MAAM,CAAC,GAAG,MAA8D,CAAC;QACzE,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC;QAEpD,qDAAqD;QACrD,kEAAkE;QAClE,2DAA2D;QAC3D,8DAA8D;QAC9D,6DAA6D;QAC7D,kEAAkE;QAClE,yDAAyD;QACzD,0BAA0B;QAC1B,MAAM,WAAW,GAAG,CAAC,kBAAkB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QACjG,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,SAAU,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QACvF,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAEhF,IAAI,kBAAkB,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;YAC1C,OAAO,IAAI,MAAM,4CAA4C,CAAC;QAChE,CAAC;QAED,kEAAkE;QAClE,gEAAgE;QAChE,kEAAkE;QAClE,qBAAqB;QACrB,EAAE;QACF,iEAAiE;QACjE,oEAAoE;QACpE,iEAAiE;QACjE,gEAAgE;QAChE,4BAA4B;QAC5B,MAAM,UAAU,GAAG,CAAC,CAAC,kBAAkB,IAAI,OAAO,CAAC,EAAE,OAAO,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;YAChG,CAAC,CAAC,CAAC,CAAC,OAAO;YACX,CAAC,CAAC,CAAC,OAAO,SAAS,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC;QAEpD,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,mEAAmE;QACnE,iEAAiE;QACjE,2CAA2C;QAC3C,OAAO,IAAI,MAAM,cAAc,aAAa,KAAK,SAAS,QAAQ,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IAClG,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"execute-plan.d.ts","sourceRoot":"","sources":["../../../src/reporting/headline-templates/execute-plan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAahE,eAAO,MAAM,2BAA2B,EAAE,gBAgBzC,CAAC"}
1
+ {"version":3,"file":"execute-plan.d.ts","sourceRoot":"","sources":["../../../src/reporting/headline-templates/execute-plan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAahE,eAAO,MAAM,2BAA2B,EAAE,gBAyBzC,CAAC"}
@@ -1,17 +1,26 @@
1
1
  import { firstSentenceOrTruncate } from '../headline-text.js';
2
2
  export const executePlanHeadlineTemplate = {
3
- compose({ report, status }) {
3
+ compose({ report, status, runResult }) {
4
4
  const r = report;
5
+ // Tool sweep #7 (execute-plan): use the dash-cased route name
6
+ // `execute-plan` to match the HTTP path + envelope shapes (the
7
+ // pre-fix `execute_plan` underscore was the only tool diverging
8
+ // from kebab-case in operator-facing output) and ALWAYS include
9
+ // the [<status>] prefix for parity with audit/review/verify/debug/
10
+ // delegate.
5
11
  if (r?.taskOutcomes && Array.isArray(r.taskOutcomes) && r.taskOutcomes.length > 0) {
6
12
  const completed = r.taskOutcomes.filter((t) => t.status === 'completed' || t.status === 'success').length;
7
- return `execute_plan: ${completed}/${r.taskOutcomes.length} tasks complete`;
13
+ return `[${status}] execute-plan: ${completed}/${r.taskOutcomes.length} tasks complete`;
8
14
  }
9
- if (r?.summary && typeof r.summary === 'string') {
10
- // Gap 12 fix (4.0.3+): trim worker's narrative summary so the
11
- // headline doesn't dump multi-sentence prose ending mid-thought.
12
- return `[${status}] execute_plan: ${firstSentenceOrTruncate(r.summary)}`;
13
- }
14
- return `[${status}] execute_plan`;
15
+ // Tool sweep #7: fall back to runResult.output when report has no
16
+ // summary. Mirrors the delegate fix operator gets a meaningful
17
+ // reason on no-op outcomes instead of a bare `[<status>] execute-plan`.
18
+ const fallbackSrc = (r?.summary && typeof r.summary === 'string' && r.summary.length > 0)
19
+ ? r.summary
20
+ : (typeof runResult?.output === 'string' ? runResult.output : '');
21
+ const summary = firstSentenceOrTruncate(fallbackSrc);
22
+ const summaryClause = summary.length > 0 ? ` ${summary}` : '';
23
+ return `[${status}] execute-plan:${summaryClause}`;
15
24
  },
16
25
  };
17
26
  //# sourceMappingURL=execute-plan.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"execute-plan.js","sourceRoot":"","sources":["../../../src/reporting/headline-templates/execute-plan.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAY9D,MAAM,CAAC,MAAM,2BAA2B,GAAqB;IAC3D,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE;QACxB,MAAM,CAAC,GAAG,MAA2C,CAAC;QACtD,IAAI,CAAC,EAAE,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClF,MAAM,SAAS,GAAG,CAAC,CAAC,YAAY,CAAC,MAAM,CACrC,CAAC,CAAc,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CACvE,CAAC,MAAM,CAAC;YACT,OAAO,iBAAiB,SAAS,IAAI,CAAC,CAAC,YAAY,CAAC,MAAM,iBAAiB,CAAC;QAC9E,CAAC;QACD,IAAI,CAAC,EAAE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChD,8DAA8D;YAC9D,iEAAiE;YACjE,OAAO,IAAI,MAAM,mBAAmB,uBAAuB,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3E,CAAC;QACD,OAAO,IAAI,MAAM,gBAAgB,CAAC;IACpC,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"execute-plan.js","sourceRoot":"","sources":["../../../src/reporting/headline-templates/execute-plan.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAY9D,MAAM,CAAC,MAAM,2BAA2B,GAAqB;IAC3D,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE;QACnC,MAAM,CAAC,GAAG,MAA2C,CAAC;QACtD,8DAA8D;QAC9D,+DAA+D;QAC/D,gEAAgE;QAChE,gEAAgE;QAChE,mEAAmE;QACnE,YAAY;QACZ,IAAI,CAAC,EAAE,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClF,MAAM,SAAS,GAAG,CAAC,CAAC,YAAY,CAAC,MAAM,CACrC,CAAC,CAAc,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CACvE,CAAC,MAAM,CAAC;YACT,OAAO,IAAI,MAAM,mBAAmB,SAAS,IAAI,CAAC,CAAC,YAAY,CAAC,MAAM,iBAAiB,CAAC;QAC1F,CAAC;QACD,kEAAkE;QAClE,iEAAiE;QACjE,wEAAwE;QACxE,MAAM,WAAW,GAAG,CAAC,CAAC,EAAE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;YACvF,CAAC,CAAC,CAAC,CAAC,OAAO;YACX,CAAC,CAAC,CAAC,OAAO,SAAS,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,OAAO,IAAI,MAAM,kBAAkB,aAAa,EAAE,CAAC;IACrD,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { HeadlineTemplate } from '../headline-composer.js';
2
+ export declare const researchHeadlineTemplate: HeadlineTemplate;
3
+ //# sourceMappingURL=research.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"research.d.ts","sourceRoot":"","sources":["../../../src/reporting/headline-templates/research.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAShE,eAAO,MAAM,wBAAwB,EAAE,gBAiBtC,CAAC"}
@@ -0,0 +1,23 @@
1
+ const REASON_TEXT = {
2
+ cost_cap: 'cost cap reached',
3
+ timeout: 'timed out',
4
+ turn_cap: 'turn cap reached',
5
+ };
6
+ export const researchHeadlineTemplate = {
7
+ compose({ report, status, runResult }) {
8
+ const r = report;
9
+ const findings = Array.isArray(r?.findings) ? r.findings : [];
10
+ const sources = Array.isArray(r?.sourcesUsed) ? r.sourcesUsed : [];
11
+ if (status === 'incomplete') {
12
+ const reasonKey = runResult?.incompleteReason ?? '';
13
+ const reason = REASON_TEXT[reasonKey] ?? reasonKey ?? 'incomplete';
14
+ return `[incomplete] research: ${reason}`;
15
+ }
16
+ if (status === 'error') {
17
+ const msg = runResult?.error ?? 'runner crash';
18
+ return `[error] research: ${msg}`;
19
+ }
20
+ return `[ok] research: ${sources.length} sources, ${findings.length} findings`;
21
+ },
22
+ };
23
+ //# sourceMappingURL=research.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"research.js","sourceRoot":"","sources":["../../../src/reporting/headline-templates/research.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,GAA2B;IAC1C,QAAQ,EAAE,kBAAkB;IAC5B,OAAO,EAAE,WAAW;IACpB,QAAQ,EAAE,kBAAkB;CAC7B,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAqB;IACxD,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE;QACnC,MAAM,CAAC,GAAG,MAAoD,CAAC;QAC/D,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;QAEpE,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;YAC5B,MAAM,SAAS,GAAI,SAAuD,EAAE,gBAAgB,IAAI,EAAE,CAAC;YACnG,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,YAAY,CAAC;YACnE,OAAO,0BAA0B,MAAM,EAAE,CAAC;QAC5C,CAAC;QACD,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YACvB,MAAM,GAAG,GAAI,SAA4C,EAAE,KAAK,IAAI,cAAc,CAAC;YACnF,OAAO,qBAAqB,GAAG,EAAE,CAAC;QACpC,CAAC;QACD,OAAO,kBAAkB,OAAO,CAAC,MAAM,aAAa,QAAQ,CAAC,MAAM,WAAW,CAAC;IACjF,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../../src/reporting/headline-templates/review.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAKhE,eAAO,MAAM,sBAAsB,EAAE,gBAuBpC,CAAC"}
1
+ {"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../../src/reporting/headline-templates/review.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAKhE,eAAO,MAAM,sBAAsB,EAAE,gBAwCpC,CAAC"}
@@ -1,21 +1,38 @@
1
1
  import { isNotApplicable } from '../not-applicable.js';
2
- import { countHighOrCritical } from '../severity.js';
2
+ import { countHighOrCritical, parseNarrativeFindings } from '../severity.js';
3
3
  export const reviewHeadlineTemplate = {
4
4
  compose({ report, status, taskBrief, runResult, task }) {
5
5
  const r = report;
6
6
  const reportInapplicable = !r || isNotApplicable(r);
7
- // 4.0.3+ Gap 2 fix: prefer report.findings (structured), fall back
8
- // to runResult.annotatedFindings (narrative-path canonical source).
7
+ // Source priority (4.0.3+, parallel to audit):
8
+ // 1. report.findings (structured)
9
+ // 2. runResult.annotatedFindings (annotator success path)
10
+ // 3. parseNarrativeFindings(runResult.output) (annotator error
11
+ // fallback — recover from implementer's `## Finding N:` blocks)
9
12
  const reportFindings = !reportInapplicable && Array.isArray(r?.findings) ? r.findings : [];
10
13
  const annotated = runResult?.annotatedFindings ?? [];
11
- const findings = reportFindings.length > 0 ? reportFindings : annotated;
12
- if (findings.length === 0) {
13
- return `[${status}] review: ${taskBrief}`;
14
+ let findings = reportFindings.length > 0
15
+ ? reportFindings
16
+ : annotated;
17
+ if (findings.length === 0 && typeof runResult?.output === 'string') {
18
+ const narrative = parseNarrativeFindings(runResult.output);
19
+ if (narrative.length > 0)
20
+ findings = narrative;
14
21
  }
15
22
  const blocking = countHighOrCritical(findings);
16
23
  const path = (!reportInapplicable && typeof r?.filePath === 'string' ? r.filePath : '')
17
24
  || task?.filePaths?.[0]
18
25
  || '';
26
+ // Mirror audit's gap-A fix: only collapse to "review completed"
27
+ // when we have no path AND no findings. With a path, always emit
28
+ // the structured form so a clean review still names the file:
29
+ // [ok] review packages/foo.ts: 0 findings (0 blocking)
30
+ // Previously this branch fell back to `${taskBrief}` which the
31
+ // brief compiler reduces to the route name, producing the
32
+ // operator-useless headline "[ok] review: review".
33
+ if (findings.length === 0 && !path) {
34
+ return `[${status}] review completed`;
35
+ }
19
36
  return `[${status}] review ${path}: ${findings.length} findings (${blocking} blocking)`;
20
37
  },
21
38
  };
@@ -1 +1 @@
1
- {"version":3,"file":"review.js","sourceRoot":"","sources":["../../../src/reporting/headline-templates/review.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,CAAC,MAAM,sBAAsB,GAAqB;IACtD,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE;QACpD,MAAM,CAAC,GAAG,MAAkD,CAAC;QAC7D,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC;QAEpD,mEAAmE;QACnE,oEAAoE;QACpE,MAAM,cAAc,GAAG,CAAC,kBAAkB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5F,MAAM,SAAS,GAAG,SAAS,EAAE,iBAAiB,IAAI,EAAE,CAAC;QACrD,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC;QAExE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,IAAI,MAAM,aAAa,SAAS,EAAE,CAAC;QAC5C,CAAC;QAED,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAyC,CAAC,CAAC;QAChF,MAAM,IAAI,GACR,CAAC,CAAC,kBAAkB,IAAI,OAAO,CAAC,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;eACvE,IAA6C,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;eAC9D,EAAE,CAAC;QAER,OAAO,IAAI,MAAM,YAAY,IAAI,KAAK,QAAQ,CAAC,MAAM,cAAc,QAAQ,YAAY,CAAC;IAC1F,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"review.js","sourceRoot":"","sources":["../../../src/reporting/headline-templates/review.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAE7E,MAAM,CAAC,MAAM,sBAAsB,GAAqB;IACtD,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE;QACpD,MAAM,CAAC,GAAG,MAAkD,CAAC;QAC7D,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC;QAEpD,+CAA+C;QAC/C,oCAAoC;QACpC,4DAA4D;QAC5D,iEAAiE;QACjE,qEAAqE;QACrE,MAAM,cAAc,GAAG,CAAC,kBAAkB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5F,MAAM,SAAS,GAAG,SAAS,EAAE,iBAAiB,IAAI,EAAE,CAAC;QACrD,IAAI,QAAQ,GACV,cAAc,CAAC,MAAM,GAAG,CAAC;YACvB,CAAC,CAAE,cAAgD;YACnD,CAAC,CAAE,SAA2C,CAAC;QACnD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,SAAS,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;YACnE,MAAM,SAAS,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YAC3D,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;gBAAE,QAAQ,GAAG,SAAS,CAAC;QACjD,CAAC;QAED,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC/C,MAAM,IAAI,GACR,CAAC,CAAC,kBAAkB,IAAI,OAAO,CAAC,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;eACvE,IAA6C,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;eAC9D,EAAE,CAAC;QAER,gEAAgE;QAChE,iEAAiE;QACjE,8DAA8D;QAC9D,yDAAyD;QACzD,+DAA+D;QAC/D,0DAA0D;QAC1D,mDAAmD;QACnD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACnC,OAAO,IAAI,MAAM,oBAAoB,CAAC;QACxC,CAAC;QAED,OAAO,IAAI,MAAM,YAAY,IAAI,KAAK,QAAQ,CAAC,MAAM,cAAc,QAAQ,YAAY,CAAC;IAC1F,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../src/reporting/headline-templates/verify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAIhE,eAAO,MAAM,sBAAsB,EAAE,gBAQpC,CAAC"}
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../src/reporting/headline-templates/verify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAIhE,eAAO,MAAM,sBAAsB,EAAE,gBA8BpC,CAAC"}
@@ -1,12 +1,29 @@
1
+ import { parseVerifyResults } from '../report-parser-slots/verify-report.js';
1
2
  import { isNotApplicable } from '../not-applicable.js';
2
3
  export const verifyHeadlineTemplate = {
3
- compose({ report, status }) {
4
- if (!report || isNotApplicable(report))
5
- return `[${status}] verify: no structured report available`;
4
+ compose({ report, status, runResult, task }) {
6
5
  const r = report;
7
- const items = Array.isArray(r.results) ? r.results : [];
8
- const passed = items.filter((x) => x?.pass).length;
9
- return `[${status}] verify: ${passed}/${items.length} pass`;
6
+ const reportInapplicable = !r || isNotApplicable(r);
7
+ // Source priority (parallel to audit + review):
8
+ // 1. report.results (structured path; the primary parser now handles
9
+ // both JSON and narrative).
10
+ // 2. parseVerifyResults(runResult.output) (defensive fallback when the
11
+ // structured parser ran a non-verify schema and stripped the
12
+ // narrative — same Gap-A pattern surfaced on review #2).
13
+ let results = !reportInapplicable && Array.isArray(r?.results) ? r.results : [];
14
+ if (results.length === 0 && typeof runResult?.output === 'string') {
15
+ const narrative = parseVerifyResults(runResult.output);
16
+ if (narrative.length > 0)
17
+ results = narrative;
18
+ }
19
+ const path = task?.filePaths?.[0] || '';
20
+ if (results.length === 0 && !path) {
21
+ return `[${status}] verify completed`;
22
+ }
23
+ const passed = results.filter((x) => x?.pass).length;
24
+ return path
25
+ ? `[${status}] verify ${path}: ${passed}/${results.length} pass`
26
+ : `[${status}] verify: ${passed}/${results.length} pass`;
10
27
  },
11
28
  };
12
29
  //# sourceMappingURL=verify.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../src/reporting/headline-templates/verify.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,CAAC,MAAM,sBAAsB,GAAqB;IACtD,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE;QACxB,IAAI,CAAC,MAAM,IAAI,eAAe,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,MAAM,0CAA0C,CAAC;QACpG,MAAM,CAAC,GAAG,MAAsB,CAAC;QACjC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC;QACnD,OAAO,IAAI,MAAM,aAAa,MAAM,IAAI,KAAK,CAAC,MAAM,OAAO,CAAC;IAC9D,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../src/reporting/headline-templates/verify.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAChG,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,CAAC,MAAM,sBAAsB,GAAqB;IACtD,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE;QACzC,MAAM,CAAC,GAAG,MAAkD,CAAC;QAC7D,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC;QAEpD,gDAAgD;QAChD,uEAAuE;QACvE,iCAAiC;QACjC,yEAAyE;QACzE,kEAAkE;QAClE,8DAA8D;QAC9D,IAAI,OAAO,GACT,CAAC,kBAAkB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,SAAS,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;YAClE,MAAM,SAAS,GAAG,kBAAkB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACvD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,GAAG,SAAS,CAAC;QAChD,CAAC;QAED,MAAM,IAAI,GACP,IAA6C,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEvE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAClC,OAAO,IAAI,MAAM,oBAAoB,CAAC;QACxC,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC;QACrD,OAAO,IAAI;YACT,CAAC,CAAC,IAAI,MAAM,YAAY,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,MAAM,OAAO;YAChE,CAAC,CAAC,IAAI,MAAM,aAAa,MAAM,IAAI,OAAO,CAAC,MAAM,OAAO,CAAC;IAC7D,CAAC;CACF,CAAC"}
@@ -21,6 +21,11 @@
21
21
  * relevant signal. Truncating mid-sentence (the prior bug) loses
22
22
  * that signal AND looks broken.
23
23
  *
24
+ * Sentence-end heuristic: a `.!?` followed by whitespace OR end-of-
25
+ * string. The match is non-greedy and ranges over `max` characters,
26
+ * so internal punctuation (version numbers like `v4.0.3`, decimals
27
+ * like `1.5`, filenames like `auth.ts`) does NOT block the scan.
28
+ *
24
29
  * @param s raw text (may be empty / whitespace-only)
25
30
  * @param max hard truncation cap when no sentence break is found.
26
31
  * 80 keeps headlines well under the typical 120-char
@@ -1 +1 @@
1
- {"version":3,"file":"headline-text.d.ts","sourceRoot":"","sources":["../../src/reporting/headline-text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,SAAK,GAAG,MAAM,CAOnE"}
1
+ {"version":3,"file":"headline-text.d.ts","sourceRoot":"","sources":["../../src/reporting/headline-text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,SAAK,GAAG,MAAM,CAkCnE"}
@@ -11,7 +11,6 @@
11
11
  * `firstSentenceOrTruncate` is the single helper composers use to
12
12
  * sanitize narrative text for headline display.
13
13
  */
14
- const SENTENCE_END = /^([^.!?\n]{1,80}[.!?])(\s|$)/;
15
14
  /**
16
15
  * Return the first sentence of `s`, or a hard-truncated form with
17
16
  * trailing ellipsis when no sentence boundary exists in the first
@@ -22,6 +21,11 @@ const SENTENCE_END = /^([^.!?\n]{1,80}[.!?])(\s|$)/;
22
21
  * relevant signal. Truncating mid-sentence (the prior bug) loses
23
22
  * that signal AND looks broken.
24
23
  *
24
+ * Sentence-end heuristic: a `.!?` followed by whitespace OR end-of-
25
+ * string. The match is non-greedy and ranges over `max` characters,
26
+ * so internal punctuation (version numbers like `v4.0.3`, decimals
27
+ * like `1.5`, filenames like `auth.ts`) does NOT block the scan.
28
+ *
25
29
  * @param s raw text (may be empty / whitespace-only)
26
30
  * @param max hard truncation cap when no sentence break is found.
27
31
  * 80 keeps headlines well under the typical 120-char
@@ -34,9 +38,36 @@ export function firstSentenceOrTruncate(s, max = 80) {
34
38
  const trimmed = s.trim();
35
39
  if (trimmed.length === 0)
36
40
  return '';
37
- const m = trimmed.match(SENTENCE_END);
38
- if (m)
39
- return m[1];
40
- return trimmed.length > max ? trimmed.slice(0, max - 1) + '…' : trimmed;
41
+ // F2 fix (audit, low): defend against invalid `max` values. Headlines
42
+ // are single-line operator-facing strings; a buggy caller passing
43
+ // `max=0`, negative, `NaN`, or `Infinity` shouldn't make the regex
44
+ // throw or overrun. Coerce to a sane bound: integer in [1, 2000].
45
+ const safeMax = Number.isFinite(max) && max >= 1
46
+ ? Math.min(Math.floor(max), 2000)
47
+ : 80;
48
+ // N2 fix (audit-2, low): collapse whitespace BEFORE sentence detection.
49
+ // Doing it after meant a sentence wrapping across a newline before
50
+ // its terminator (e.g., "Fixed auth\nissue. More") never matched the
51
+ // boundary regex and fell through to a generic truncate.
52
+ const oneLine = collapseNewlines(trimmed);
53
+ // N1 fix (audit-2, low): cap the captured sentence at exactly `safeMax`
54
+ // chars including the terminating punctuation. The leading run is
55
+ // therefore at most `safeMax - 1` chars. Skip sentence detection
56
+ // entirely when there's no room for even "X." (safeMax < 2).
57
+ // Lazy quantifier `{1,N}?` lets internal `.!?` characters pass
58
+ // through (version numbers, decimals, filenames) until we hit one
59
+ // followed by whitespace or end-of-string — the real sentence boundary.
60
+ if (safeMax >= 2) {
61
+ const sentenceEnd = new RegExp(`^(.{1,${safeMax - 1}}?[.!?])(\\s|$)`);
62
+ const m = oneLine.match(sentenceEnd);
63
+ if (m)
64
+ return m[1];
65
+ }
66
+ return oneLine.length > safeMax ? oneLine.slice(0, safeMax - 1) + '…' : oneLine;
67
+ }
68
+ /** Replace any whitespace run (including newlines, tabs, and CRs) with
69
+ * a single space so the returned headline stays on one line. */
70
+ function collapseNewlines(s) {
71
+ return s.replace(/\s+/g, ' ').trim();
41
72
  }
42
73
  //# sourceMappingURL=headline-text.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"headline-text.js","sourceRoot":"","sources":["../../src/reporting/headline-text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,YAAY,GAAG,8BAA8B,CAAC;AAEpD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,uBAAuB,CAAC,CAAS,EAAE,GAAG,GAAG,EAAE;IACzD,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IAC3C,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACnB,OAAO,OAAO,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;AAC1E,CAAC"}
1
+ {"version":3,"file":"headline-text.js","sourceRoot":"","sources":["../../src/reporting/headline-text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,uBAAuB,CAAC,CAAS,EAAE,GAAG,GAAG,EAAE;IACzD,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IAC3C,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEpC,sEAAsE;IACtE,kEAAkE;IAClE,mEAAmE;IACnE,kEAAkE;IAClE,MAAM,OAAO,GACX,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAC9B,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;QACjC,CAAC,CAAC,EAAE,CAAC;IAET,wEAAwE;IACxE,mEAAmE;IACnE,qEAAqE;IACrE,yDAAyD;IACzD,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAE1C,wEAAwE;IACxE,kEAAkE;IAClE,iEAAiE;IACjE,6DAA6D;IAC7D,+DAA+D;IAC/D,kEAAkE;IAClE,wEAAwE;IACxE,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACjB,MAAM,WAAW,GAAG,IAAI,MAAM,CAAC,SAAS,OAAO,GAAG,CAAC,iBAAiB,CAAC,CAAC;QACtE,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACrC,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;AAClF,CAAC;AAED;iEACiE;AACjE,SAAS,gBAAgB,CAAC,CAAS;IACjC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACvC,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { ReportSchema } from '../structured-report-parser.js';
2
+ import { z } from 'zod';
3
+ declare const researchReportZod: z.ZodObject<{
4
+ findings: z.ZodArray<z.ZodObject<{
5
+ index: z.ZodNumber;
6
+ body: z.ZodString;
7
+ citations: z.ZodArray<z.ZodObject<{
8
+ kind: z.ZodEnum<{
9
+ url: "url";
10
+ file_line: "file_line";
11
+ source: "source";
12
+ }>;
13
+ label: z.ZodOptional<z.ZodString>;
14
+ target: z.ZodOptional<z.ZodString>;
15
+ }, z.core.$strip>>;
16
+ }, z.core.$strip>>;
17
+ sourcesUsed: z.ZodArray<z.ZodObject<{
18
+ source: z.ZodString;
19
+ attempted: z.ZodBoolean;
20
+ used: z.ZodBoolean;
21
+ note: z.ZodOptional<z.ZodString>;
22
+ }, z.core.$strip>>;
23
+ }, z.core.$strip>;
24
+ export type ResearchReport = z.infer<typeof researchReportZod>;
25
+ /** ReportSchema that parses worker narrative text (numbered findings +
26
+ * `## Sources used` table) into a structured ResearchReport. */
27
+ export declare const researchReportSchema: ReportSchema<ResearchReport>;
28
+ export declare function parseResearchReport(output: string): ResearchReport;
29
+ export {};
30
+ //# sourceMappingURL=research-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"research-report.d.ts","sourceRoot":"","sources":["../../../src/reporting/report-parser-slots/research-report.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;iBAgBrB,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE/D;iEACiE;AACjE,eAAO,MAAM,oBAAoB,EAAE,YAAY,CAAC,cAAc,CAI7D,CAAC;AAuDF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAclE"}
@@ -0,0 +1,94 @@
1
+ import { z } from 'zod';
2
+ const researchReportZod = z.object({
3
+ findings: z.array(z.object({
4
+ index: z.number().int().nonnegative(),
5
+ body: z.string(),
6
+ citations: z.array(z.object({
7
+ kind: z.enum(['url', 'file_line', 'source']),
8
+ label: z.string().optional(),
9
+ target: z.string().optional(),
10
+ })),
11
+ })),
12
+ sourcesUsed: z.array(z.object({
13
+ source: z.string(),
14
+ attempted: z.boolean(),
15
+ used: z.boolean(),
16
+ note: z.string().optional(),
17
+ })),
18
+ });
19
+ /** ReportSchema that parses worker narrative text (numbered findings +
20
+ * `## Sources used` table) into a structured ResearchReport. */
21
+ export const researchReportSchema = {
22
+ parse(text) {
23
+ return parseResearchReport(text);
24
+ },
25
+ };
26
+ const NUMBERED_FINDING_RE = /^\s*(\d+)\.\s+([\s\S]*?)(?=^\s*\d+\.\s+|\n##\s|\n#\s|$)/gmu;
27
+ const URL_RE = /https?:\/\/[^\s)]+/g;
28
+ const FILE_LINE_RE = /([A-Za-z0-9_./-]+):(\d+(?:-\d+)?)/g;
29
+ function parseSourcesUsed(text) {
30
+ const m = text.match(/##\s+Sources used\s*([\s\S]*?)(?:\n##\s|$)/i);
31
+ if (!m)
32
+ return [];
33
+ const lines = m[1].split('\n').map(l => l.trim()).filter(Boolean);
34
+ const rows = [];
35
+ for (const line of lines) {
36
+ if (!line.startsWith('|') || /^\|\s*-/.test(line) || /^\|\s*source\s*\|/i.test(line))
37
+ continue;
38
+ const cells = line.split('|').slice(1, -1).map(c => c.trim());
39
+ if (cells.length < 3)
40
+ continue;
41
+ const [source, attemptedRaw, usedRaw, note] = cells;
42
+ rows.push({
43
+ source,
44
+ attempted: /^yes$/i.test(attemptedRaw),
45
+ used: /^yes$/i.test(usedRaw),
46
+ ...(note ? { note } : {}),
47
+ });
48
+ }
49
+ return rows;
50
+ }
51
+ function extractCitations(body, sources) {
52
+ const citations = [];
53
+ for (const m of body.matchAll(URL_RE)) {
54
+ citations.push({ kind: 'url', label: extractDomain(m[0]), target: m[0] });
55
+ }
56
+ for (const m of body.matchAll(FILE_LINE_RE)) {
57
+ if (URL_RE.test(m[0]))
58
+ continue; // skip if it's part of a URL
59
+ citations.push({ kind: 'file_line', label: m[1], target: `${m[1]}:${m[2]}` });
60
+ }
61
+ // Pass 2: source-name match against the Sources Used table.
62
+ const lower = body.toLowerCase();
63
+ for (const row of sources) {
64
+ if (lower.includes(row.source.toLowerCase())) {
65
+ citations.push({ kind: 'source', label: row.source });
66
+ }
67
+ }
68
+ return citations;
69
+ }
70
+ function extractDomain(url) {
71
+ try {
72
+ return new URL(url).hostname;
73
+ }
74
+ catch {
75
+ return url;
76
+ }
77
+ }
78
+ export function parseResearchReport(output) {
79
+ const sourcesUsed = parseSourcesUsed(output);
80
+ const findings = [];
81
+ for (const m of output.matchAll(NUMBERED_FINDING_RE)) {
82
+ const idx = Number(m[1]);
83
+ const body = m[2].trim();
84
+ if (!body)
85
+ continue;
86
+ findings.push({
87
+ index: idx,
88
+ body,
89
+ citations: extractCitations(body, sourcesUsed),
90
+ });
91
+ }
92
+ return { findings, sourcesUsed };
93
+ }
94
+ //# sourceMappingURL=research-report.js.map