# fix\(server\): preserve tool lifecycle identity · PR \#7151 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/7151)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: ui-refresh/tool-activity

Target branch: main

Head commit: 102ece2dee9ba6c17c412337f53da5ed7ec5f1a9

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/7151)

[Commits](https://git.cafe/pingdotgg/t3code/pull/7151/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/7151/diffs?format=markdown)

## Description

---

## What changed

- Carries provider item IDs into top-level `toolCallId` lifecycle identity for started, updated, and completed tool events.
- Preserves start status and provider command data so later completion events can be folded into the correct activity.
- Normalizes direct, Claude, and OpenCode command shapes during activity projection.

## Screenshots

Not applicable. This is a server-only lifecycle projection change; its visible web consumer is demonstrated in #7152.

## Why

This is the sensitive server layer that was hard to approve inside the original UI PR. It is intentionally above every independent UI layer. The stack can merge through #7150 without taking this change.

## Review notes

- Started-event provider data is newly retained in persisted activity payloads.
- No contracts change is required.
- Mobile still ignores `tool.started`; the new web behavior is implemented in #7152.

## Validation

- Activity payload projection tests
- Provider runtime ingestion tests
- Affected-package typechecks
- Changed-file lint and formatting checks

## Stack order

1. #7153 workspace and navigation
2. #7147 Usage
3. #7148 Pull Requests
4. #7149 terminal
5. #7150 composer
6. #7151 tool lifecycle projection, this PR
7. #7152 tool activity UI

Built with GPT-5.6-sol in the Codex harness.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes orchestration activity identity and persisted tool.started payloads; deduplication keys shift for in-flight sessions at deploy time, though behavior is covered by projection and ingestion tests.
> 
> **Overview**
> **Propagates provider item IDs into persisted tool activities** so started, updated, and completed lifecycle rows share a stable top-level `toolCallId`. `toolLifecycleIdentity` now prefers that field when deduplicating to the newest row per call.
> 
> **Enriches `tool.started` payloads** to include provider `status` and `data` (aligned with update/complete), so clients can fold in-flight tool state into the same activity.
> 
> **Normalizes command strings during activity projection** via `projectCommandValue`, pulling commands from direct `data.command`, Claude-style `data.input.command`, or OpenCode-style `data.state.input.command` before slimming provider blobs.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 102ece2dee9ba6c17c412337f53da5ed7ec5f1a9. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- Macroscope's pull request summary starts here -->
<!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. -->
<!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. -->
> [!NOTE]
> ### Fix `toolLifecycleIdentity` to prefer top-level `toolCallId`
> - `toolLifecycleIdentity` in [ActivityPayloadProjection.ts](https://github.com/pingdotgg/t3code/pull/7151/files#diff-debcaf6e868575f9d95bb6918b9983c3a8929d664039039b54e9e1c7ea3b4130) now checks `payload.toolCallId` before falling back to nested `data.toolCallId`; `projectActivityPayload` uses a new `projectCommandValue` helper to normalize command fields from Claude and OpenCode payload shapes. Tool activity payloads from `runtimeEventToActivities` in [ProviderRuntimeIngestion.ts](https://github.com/pingdotgg/t3code/pull/7151/files#diff-22a6c9818b956463b848a73a5b3e787b44a144bd003b1cc25fa2b1b3110cdea7) now include `toolCallId`, `status`, and `data` when present.
> - Composer UI is redesigned across many components in `apps/web/src/components/chat/` to use attached "drawer" styling with glass surfaces, shoulder tabs, and a new `Button` size `"micro"`. New `ComposerTasksBadge` and `ComposerTasksDrawer` show per-turn task progress; `ComposerStashBadge` and `ComposerStashMenu` gain inline placement and outside-click dismissal.
> - `addPlanStepDurations` in [session-logic.ts](https://github.com/pingdotgg/t3code/pull/7151/files#diff-9f1f9f19555f14c3c47d4ce52e1b7dcec7e968e54f400820085376797a7223d6) computes `durationMs` on completed plan steps by scanning `plan.update` transitions; `deriveActivePlanState` and `deriveTurnPlans` now return plans with per-step durations.
> - `resolveProviderSkillSourceKind` in [providerSkills.ts](https://github.com/pingdotgg/t3code/pull/7151/files#diff-476dddad7957a4fde40db8096524533f59b357b62c8d01c6d9f05f2c0b12c63c) replaces `formatProviderSkillInstallSource`, returning a normalized union (`'app'|'repo'|'project'|'personal'|'system'|'other'`); callers in web and mobile use it for skill icons.
> - Risk: `toolLifecycleIdentity` resolution change may alter which activity row is retained for a given tool call in snapshots — verify dedup logic in [ActivityPayloadProjection.ts](https://github.com/pingdotgg/t3code/pull/7151/files#diff-debcaf6e868575f9d95bb6918b9983c3a8929d664039039b54e9e1c7ea3b4130) handles top-level `toolCallId` collisions. Composer CSS in [index.css](https://github.com/pingdotgg/t3code/pull/7151/files#diff-70ad657a634ce55957729ff8d1c93f697cc7e3ca2a5cb5fe6b00c90d7d515fcd) introduces new glass-surface rules and removes `background: transparent` from `code`, which may affect existing code element rendering.
>
> <!-- Macroscope's review summary starts here -->
>
> <sup><a href="https://app.macroscope.com">Macroscope</a> summarized 9df356b.</sup>
> <!-- Macroscope's review summary ends here -->
>
<!-- Macroscope's pull request summary ends here -->
