fix: record workflow tool parts in audit metadata

Merged
SI
2d ago
+186-0

Workflow audit records currently report zero tool parts because the main workflow never supplies the count to the existing audit writer. Count top-level static/dynamic tool UI parts in the accumulated assistant message and forward that optional metadata through handleChatCredits.

This is a bounded successor to #649. The count includes pending/failed parts and preexisting parts in a resumed message; it is not successful executions, incremental resume work, or nested subagent usage. Credit calculations, amounts, account/model attribution, charge conditions and workflow boundaries remain unchanged. No migration or historical backfill.

Validation:

  • Six regression tests failed before wiring; 213 focused tests across 36 files now pass.
  • Full lint and diff checks pass.
  • Whole-project local typecheck retains the same 211 baseline diagnostics by path/code/message; one existing test diagnostic moved two lines.
  • Independent Spec and Standards review clear at 9364e765d5b38b51fed75dd2801c396cdccc5616 (tree 19add370db831f2cf80528180c73358cee21b7dc, base 5c0e585d0e12277abc57160129f35b02c9e7cacf).
  • Tests mock external workflow/credit/provider leaves. No live workflow, database write, credit deduction, customer job or credential inspection performed. CI and preview compilation tracked separately.

Summary by cubic

Fixes workflow audit records reporting zero tool calls because the main workflow never supplied the count to the existing audit writer. Counts tool UI parts in the accumulated assistant message and passes the optional count through handleChatCredits into audit metadata, without changing credit calculations, amounts, charge conditions, or workflow boundaries.

Tool call counting

  • Counts top-level static and dynamic tool UI parts, including pending and failed parts, and preexisting parts in resumed messages.
  • Excludes successful-execution counts, incremental resume work, and nested subagent output.
  • Omitted when the count is undefined, preserving the writer's existing zero default.