Skip to content

chore(friction): improve report format — surface category, compact body, opt-in label#1313

Merged
zbigniewsobiecki merged 1 commit into
devfrom
chore/improve-friction-report-format
May 10, 2026
Merged

chore(friction): improve report format — surface category, compact body, opt-in label#1313
zbigniewsobiecki merged 1 commit into
devfrom
chore/improve-friction-report-format

Conversation

@zbigniewsobiecki
Copy link
Copy Markdown
Member

Summary

Pure presentation pass on friction reports — same FrictionReport input from agents, more useful PM card output. Plus an opt-in cascade-friction label (mirrors the spec-019 cascade-alert pattern) so operators can filter/cluster friction cards in the PM UI.

Live signal driving this: PRs #1305 + #1311 closed the recruit→fire loop today (5 reports filed cleanly post-deploy at 09:05Z across cascade/Trello + mongrel/Linear). The reports work, but the rendering was suboptimal.

What changes

Title

Before After
[Friction][medium] PM add-checklist failed ... [Friction · tooling · low] PM add-checklist failed ...
Slug: frictionmedium-pm-add-checklist-... Slug: friction-tooling-low-pm-add-checklist-...
Category absent from title All 3 classification facets surfaced

Body

Removed (all redundant): ## What happened (title carries summary), ## Classification (category+severity in title; whileDoing migrates into Run context), ## Timestamp header (PM provider's native createdAt already surfaces this).

New shape:

## Details
{agent's verbatim prose — most worth reading, so first}

## Run context
- **Run:** [1aaebb71-...](https://ca.sca.de.com/runs/...) — splitting · codex/gpt-5.4
- **Work item:** [Split big card into INVEST stories (\`MNG-355\`)](https://linear.app/...)
- **PR:** [#1308 feat: x](https://github.com/...)\`feature/x\` @ \`25e2e76aa3b0\`
- **Project:** \`ucho\` — zbigniewsobiecki/ucho (linear)
- **While doing:** Creating INVEST user-story work items from MNG-355

_Reported 2026-05-10T09:17:23.000Z_

Bold-keyed bullets, dense, run link first (the gold piece — links to the full agent transcript). Lines for absent fields drop entirely. Mirrors src/integrations/alerting/_shared/format.ts:formatSentryCardBody.

Optional cascade-friction label

  • New getFrictionLabelId(project) accessor reads labels['cascade-friction'] (Trello) / labels.cascadeFriction (JIRA, Linear).
  • materializeFrictionReport passes [labelId] to createWorkItem when configured, [] otherwise.
  • Back-compat: prod projects without the label configured (current cascade & ucho) keep filing unlabeled cards exactly as before.

Test plan

  • npm run lint + typecheck clean
  • All 9244 unit tests pass
  • Hand-rendered a prod-shaped sample post-build to visually verify title slug + body shape (output captured in commit message).
  • Pinned in tests:
    • format.test.ts: title is [Friction · category · severity] summary; body has only ## Details + ## Run context headings; the prior bracket-concat / removed-section forms are pinned absent (regression net for revert).
    • materialize.test.ts: label applied for Trello + JIRA; back-compat labels: [] pinned for projects without the label.
    • config-friction-slot.test.ts: getFrictionLabelId coverage + schema acceptance for the new label key.
  • Post-deploy E2E: watch the next 2-3 prod runs that fire report-friction. Expect: title slug starts with friction-<category>-<severity>-..., only ## Details and ## Run context headings on the rendered card.

Out of scope (intentional defer)

  • Tightening category/severity enums.
  • Cross-run dedup.
  • Configuring the cascade-friction label on production cascade / ucho projects (operator config, not code).

🤖 Generated with Claude Code

…dy, opt-in label

PRs #1305 + #1311 closed the recruit→fire loop. Looking at the 5 reports
filed live in prod 2026-05-10 (Trello cascade + Linear mongrel):

- Title slugs read `frictionlow-...` because `[Friction][severity]` put
  brackets adjacent with no separator. Category — the most useful triage
  signal — wasn't in the title at all.
- Body had 5 sections including `## What happened` (just repeats the
  summary already in the title), `## Classification` (now-redundant
  category/severity + the useful-but-buried whileDoing), and
  `## Timestamp` (the PM provider's native createdAt already shows this).
- No PM-side label, so operators couldn't filter friction cards even
  though the alert flow already established the cascade-alert opt-in
  pattern via spec 019.

Agents are already writing structured prose in `details` voluntarily
(what they tried, error, workaround, impact). The win is in rendering,
not in tightening the gadget input.

Changes:

- src/friction/format.ts:
  - Title: `[Friction · ${category} · ${severity}] ${summary}` —
    one bracket pair, dot separators, all three classification facets
    surfaced. Slugifies as `friction-tooling-low-...`.
  - Body has only two sections: `## Details` (agent prose verbatim,
    first because it's the most worth reading) and `## Run context`
    (bold-keyed bullets — Run / Work item / PR / Project / While doing).
    Italic `_Reported {iso}_` footer. Lines for absent fields drop
    entirely; no `_not provided_` placeholders for conditional context.
  - Compact bullets mirror src/integrations/alerting/_shared/format.ts.

- src/pm/config.ts: add `getFrictionLabelId(project)` mirroring the
  `getAlertLabelId` opt-in pattern from spec 019. Reads
  `labels['cascade-friction']` (Trello) / `labels.cascadeFriction`
  (JIRA, Linear). Returns undefined when unconfigured — current prod
  cascade & ucho behavior is preserved.

- src/integrations/pm/{jira,linear}/config-schema.ts: extend Zod
  schemas with the optional `cascadeFriction` label key.

- src/friction/materialize.ts: pass `[labelId]` to createWorkItem when
  configured, `[]` otherwise. Back-compat — projects without the label
  configured continue to file unlabeled cards exactly as before.

Tests:

- tests/unit/friction/format.test.ts: re-pin title + body invariants
  (only `## Details` + `## Run context` headings; no `## What happened`
  / `## Classification` / `## Timestamp`), Run-context bullet shape
  (run link, work item with monospaced id, PR with branch + 12-char SHA,
  project key/repo/pmType, whileDoing). Pin absence of prior
  bracket-concat title form as a regression net.
- tests/unit/friction/materialize.test.ts: add label-applied paths for
  Trello + JIRA + a label-absent regression net pinning `labels: []`.
- tests/unit/pm/config-friction-slot.test.ts: cover getFrictionLabelId
  across providers + Zod schema acceptance for `labels.cascadeFriction`.

Hand-rendered against a prod-shaped fixture confirms the new title slug
(`friction-tooling-low-pm-add-checklist-...`) and dense body shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zbigniewsobiecki zbigniewsobiecki merged commit 2178bce into dev May 10, 2026
7 checks passed
@codecov
Copy link
Copy Markdown

codecov Bot commented May 10, 2026

Codecov Report

❌ Patch coverage is 92.15686% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/friction/format.ts 87.50% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant