Ship the right features out of raw user feedback
Paddi is a PM agent that digests messy user feedback into clear specs for both human & coding agent.
Paddi turns raw feedback into build-ready specs,
with each decision backed by your codebase and documents
Capture every signal, from everywhere
Connect where your feedback lives, or add it through built-in inputs.
Paddi groups related feedback into structured requests.
SlackFor agent / developer
Straight into where coding agents and developers already work

Pull from the CLI to fetch any spec straight from the command line, no context switch, no waiting on a handoff.
Run Paddi as a skill and coding agents fetch the specs they need on their own, ready to execute.
For teams
Ask Paddi anything right on the spec

Current state
The API's calculateHealthScore currently calculates the raw value, 0–100 normalized value, weight, and weighted contribution for six signals: usage frequency, seat utilization, open tickets, NPS score, contract value, and login recency. apps/web/src/app/customers/[id]/page.tsx displays these fields in the Customer Detail Score breakdown table, but lists the values only in the existing signal order and does not indicate which factors are lowering or raising the total score. CSMs must therefore interpret the normalized values and contributions themselves, making it difficult to identify customer risks quickly.
packages/types/src/health-score.ts already includes the calculation results needed to build an explanation, and the API customer health-score response returns signals directly. This improvement should reuse those results rather than change the health score formula. The existing score-tier thresholds remain Healthy ≥ 75, At Risk ≥ 50, and Critical < 50.
Goal
Provide a prominent, standalone Risk drivers summary on Customer Detail so that CSMs can immediately understand the primary downward and upward factors behind a customer's score while still being able to review the signal values, weights, and contributions supporting the explanation.
Success criteria:
- Clearly label every displayed driver as either a downward contributor or an upward contributor.
- Prioritize items by the magnitude of their weighted contribution; do not introduce undecided thresholds, baselines, or external data models.
- Use the same API-calculated results as the existing Score breakdown so the summary and total score cannot diverge.
- Let CSMs identify the most important upward and downward factors without manually comparing six rows of numbers. This feature provides explanation only; it does not create tasks, timeline events, customer contacts, or other workflow actions.
Proposal
- 1.Add a standalone
Cardto the main customer-detail content area inapps/web/src/app/customers/[id]/page.tsx. Place it near the existing Health score trend and Score breakdown so it is the primary interpretation area after the score is viewed. The title may be Risk drivers, with a subtitle explaining that the content is based on the current Score breakdown calculations. - 2.Create presentation-only groups from the
signalsarray in the health-score response:- Downward contributors: signals where
normalizedValue < 50. Sort them byweightedContributionfrom lowest to highest; a lower contribution represents a greater downward effect on the total score. - Upward contributors: signals where
normalizedValue >= 50. Sort them byweightedContributionfrom highest to lowest; a higher contribution represents stronger support for the total score.
- Downward contributors: signals where
- 3.This grouping rule uses only the existing normalized values and contributions. It must not modify the calculator, weights, or score/tier calculations. To avoid incorrectly labeling a signal at exactly 50 as a risk, include 50 in the upward group and use neutral wording in the UI; do not claim that it is a risk.
- 4.Display both upward and downward contributors in the summary, with no more than two items per group to preserve scanability. If a group has no items, show an explicit empty state such as
No significant downward contributorsorNo significant upward contributorsrather than leaving it blank. - 5.Each driver row/card must include: a human-readable signal label, direction (
Pulling score down/Supporting score), raw value, normalized value, weight, and weighted contribution. Use consistent and accessible warning/danger visual treatment for downward items and success/positive treatment for upward items. Direction must not be communicated by color alone; it must include text or another readable marker. - 6.Add concise explanatory copy stating that the ordering is based on the current weighted contribution and that this section explains the score rather than recommending follow-up actions. Do not add threshold-based claims such as "below target," causal inferences, risk probabilities, or automatic recommendations.
- 7.Keep the complete existing Score breakdown table so CSMs can still inspect all six signals and their details. The summary is a prioritized overview, not a replacement for the table. A pure function or shared presenter may be extracted for grouping and sorting, with unit tests, to keep product logic out of JSX.
- 8.Adjust the shared contract only if the API response cannot support the UI.
SignalContributionis currently sufficient, so do not add persistence fields or an API route by default. Centralize any new labels or descriptions and reuse the existingSIGNAL_LABELSso naming remains consistent between the summary and breakdown.
Risks / trade-offs
- Using normalized value 50 as the positive/negative boundary is an explainable product rule that requires no new data, but it is not a business-risk threshold. The UI must avoid describing every signal below 50 as definitive customer churn risk.
- Sorting only by weighted contribution reflects each signal's impact on the current total score, but does not represent recent trends, causal relationships, or the best action for a CSM. These are explicitly out of scope.
- Limiting each group to two items reduces information load but may hide other signals. The complete table must remain available for inspection.
- Null or missing synchronization data must continue to be presented according to the calculator's existing output; the frontend must not guess or fabricate raw values. If a contribution is 0, use neutral or appropriate empty/low-impact wording and do not exaggerate risk.
- Any difference between the grouping and the existing Score breakdown numbers would damage trust. Use the same response, consistent number formatting, and tests to guarantee consistency.
Acceptance criteria
- When any Customer Detail is opened, a standalone Risk drivers summary is visible near Score breakdown without navigating to the customer list or another page.
- The summary provides both downward and upward contributor sections; each section displays no more than two items and shows an explicit empty state when it has no items.
- Downward items are determined by
normalizedValue < 50and sorted byweightedContributionfrom lowest to highest; upward items are determined bynormalizedValue >= 50and sorted byweightedContributionfrom highest to lowest. - Each summary item displays the signal label, direction text, raw value, normalized value, weight, and weighted contribution, with values exactly matching the existing Score breakdown.
- Positive and negative directions have text or semantic markers and do not rely on color alone; they remain distinguishable in dark mode and for keyboard and screen-reader users.
- The summary does not change health score, tier, weights, normalization, API calculations, or database snapshot behavior.
- The existing complete Score breakdown table remains and still contains all six signals and its original fields.
- The summary does not provide actions to create tasks, create timeline events, contact customers, or trigger other workflows; it is limited to explaining the current score.
- Automated tests cover grouping, sorting, the two-item limit, empty groups, and the boundary value
normalizedValue = 50; existing health-score calculator tests and web typecheck/build pass.
Developers ask how a decision maps to the code and which edge cases to watch.
Designers ask why a change was scoped this way and which feedback drove it.
Anyone asks and gets the reasoning behind every call, without pinging you.
Security built into every step
Never retained
Paddi reads your codebase to ground its analysis, then releases it. Your source is never stored.
Never used for model training
None of your data is ever used to train a model.
Encrypted in transit and at rest
Everything moving through and stored in Paddi is encrypted.
Working toward SOC 2 Type II and ISO 27001
We're building to those standards from day one and pursuing formal certification as Paddi grows.
Join the first teams building with Paddi
We're onboarding a small group of teams now. Get in early and start shipping the right features.
