11.5.18 The activity `all` page reports ONE total where the stream has two — `totalComments` / `totalChanges`
GET /api/v1/work-items/{key}/activity returns the RANKED page envelope — { items, nextCursor, totalCount }. The all view merges two streams, and the CLI's footer reports them separately:
packages/cli/src/render.ts:1025 shownOfTotal(shownComments, p.totalComments, 'comment'),
packages/cli/src/render.ts:1026 shownOfTotal(shownChanges, p.totalChanges, 'change'),
packages/cli/src/render.ts:1038 [p.totalComments - shownComments, 'comment'],
packages/cli/src/render.ts:1039 [p.totalChanges - shownChanges, 'change'],
ActivityAllPage therefore declares totalComments and totalChanges, which the MCP tool supplies and v1 does not. One totalCount cannot be split into them.
Why the client cannot derive them
They are whole-STREAM totals, not page counts. render.ts prints "3 of 47 comments, 2 of 18 changes" and, when a next page exists, "…and 44 more comments, 16 more changes" — both computed as total − shown. Counting the page's own items would make the footer say "3 of 3", which is not merely different, it is wrong on every page but the last. And render.ts is byte-identical-locked by 11.5.4, so the footer cannot be reworded to fit a single total.
What has to be decided, briefly
The ranked envelope promises ONE totalCount (ADR Amendment 3 Q2), and that is the right shape for the comments and history views, where the stream IS one kind. Only all has two. So the question is whether the two counts ride as fields on the all response beside totalCount, or whether totalCount on all is better understood as their sum with the split published alongside.
Recommended: publish totalComments and totalChanges as additional fields on the activity response, leaving totalCount exactly as it is and equal to their sum on the all view. That is additive under §8, keeps the envelope's promise unbroken for the two single-kind views, and matches what the underlying read already computes — ActivityAllPageDto carries both numbers today, which is where the MCP tool gets them.
Scope BOUNDARY
The server side only. It does NOT port getWorkItemActivity or touch a CLI file — that returns to 11.5.4, which this unblocks.
Acceptance criteria
- The
allview's response carries the comment and change totals separately, and a test asserts each against a known fixture stream containing both kinds. totalCountis unchanged in meaning on all three views, and onallit equals the sum — asserted, not assumed.- The
commentsandhistoryviews are unchanged on the wire. - The ADR records the decision, including why the ranked envelope was not reshaped.
contractVersion.tsmoves with a changelog line; the generated CLI artifacts are regenerated and committed; both freshness guards pass.- The drift guard drives the operation (it already does) and still passes.
- The per-file coverage floor (≥90%) holds on every modified file.
Context refs
lib/api/v1/workLoop/operations.ts:409—body: { kind: 'rankedPage', item: activityEntrySchema }.lib/api/v1/workLoop/schema.ts:803— the entry union;activityChangeSchemaabove it.lib/api/v1/openapi/envelopes.ts— the ranked envelope and its one-total promise.lib/dto/activity.ts—ActivityAllPageDto, which already carries both numbers.packages/cli/src/render.ts:1000–1045— the footer that needs them, unchangeable.packages/cli/src/mcpClient.ts—ActivityAllPage.- Story: 11.5.