Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

Parse the board tool result instead of asserting it

merged#2899CedarCopilot

CedarCopilot wants to merge 1 commit into staging from fix/board-result-parse-not-cast

What Libra verified

  • A tool call an agent makes for a user finishes with a result

    Libra ran this behavior against the change and confirmed the check detects when it breaks.

    Technical evidence
    • the agent's board creation call finishes with its created-board result instead of stopping when the run identifier is not a string
  • String run IDs remain attached to created board documents

    Libra ran this behavior against the change and confirmed the check detects when it breaks.

    Technical evidence
    • a board created with a string runId is attached to the thread with that exact runId
    • a board created with a non-string runId is attached without a runId

    Changed code: boardTool.ts.

Live on prod, 0 of 4 surfaces working, 2 days leftTimeline and evidence
  1. Opened
    Sep 23, 2026, 1:05 AM
  2. Sep 23, 2026, 1:20 AM
  3. Merged
    Sep 23, 2026, 2:01 AM
  4. Live on prod
    Sep 23, 2026, 2:01 AM
  5. Observed 0 hours, 4 surfaces, 0 requests
    Sep 23, 2026, 2:01 AM
  6. Watching

    Live on prod, 0 of 4 surfaces working, 2 days left

    Sep 23, 2026, 2:01 AM
  7. Pipelines steady after this deploy
    Sep 23, 2026, 2:01 AM

Behaviors Libra is checking

Board tool result payloads are schema-checked before rendering, so malformed or changed results render no board badge instead of crashing the transcript, while valid successful create_board results still show the clickable board badge.Not checked
prod
The board tool only uses a request-context runId when it is a string, treating missing or incorrectly typed values as undefined instead of passing invalid data downstream.Not checked
prod

Libra found 4 production surfaces on prod but could not judge any of them yet. 4 surfaces had no requests at all. Libra checks hourly for 3 days after each deploy.

Follow-up to #2896, which merged while this last fix was still in review.

Greptile flagged two as casts that PR added, both against CLAUDE.md's NEVER cast rule and both at exactly the boundary the rule exists for.

  • message.result as BoardCreateResult in the board result badge. A tool result off the wire is genuinely untyped , the assertion was the compiler agreeing with a guess the server is free to invalidate, which is the shape of the PipelineWidget crash CLAUDE.md cites. Parsed with zod instead, and .catch({}) rather than a throw: a badge that cannot read its own result should render nothing, not take the transcript down through the error boundary.
  • requestContext.get('runId') as string | undefined in boardTool, narrowed with a typeof check. The older casts on that same object are left alone , they predate this work.

No behaviour change: every access was already optional-chained, so a malformed payload rendered a disabled badge before and still does. The difference is that it is now checked at runtime rather than asserted away.

Test plan

  • turbo run types (both packages) โœ…
  • oxlint@1.78.0 --deny-warnings โœ…
  • vitest run src/mastra/tools/document/ , 219 passed โœ…
  • jest tests/modules/cedar-os , 38 passed โœ…

๐Ÿค– Generated with Claude Code

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with no actionable correctness, security, or repository-rule issues identified.

Summary

This PR replaces two unsafe type assertions at untyped runtime boundaries.

  • Validates board tool results with Zod and safely suppresses malformed-result badges.
  • Narrows the request-context run ID with a runtime string check.
  • Preserves the existing board-result and thread-attachment behavior.

Reviews (1) ยท Last reviewed commit: "fix(greptile): parse the board tool resu..."

Show production surfaces and changed-file mapping

Production surfaces

SurfaceRequestsErrorsp95UsersVerdict
/api/trpc/boards.listCards0 โ†’ 00 โ†’ 0 (0%)not measured0No traffic
No requests recorded since this deploy.
POST /api/trpc/boards.listCards0 โ†’ 00 โ†’ 0 (0%)not measured0No traffic
No requests recorded since this deploy.
execute_tool board0 โ†’ 00 โ†’ 0 (0%)not measured0No traffic
No requests recorded since this deploy.
trpc.boards.listCards0 โ†’ 00 โ†’ 0 (0%)not measured0No traffic
No requests recorded since this deploy.

Changed files โ†’ surfaces

  • apps/server/src/mastra/tools/document/boardTool.ts/api/trpc/boards.listCardsPOST /api/trpc/boards.listCardsexecute_tool boardtrpc.boards.listCards
  • apps/mail/modules/cedar-os/src/components/renderers/messageRenderers.tsxno production surface mapped