Skip to content

Insights

A sample app in the repository: apps/insights. Nothing in its report is generated: every number is a count of judgments, every quote is a user’s own words.

Terminal window
cd apps/insights && npm install
npm start # the report
npm run plan # what would be sent, without spending anything
npm run trace # every probability behind every judgment
npm run measure # test the vocabulary against labeled messages

Reads TYPESAFE_API_KEY from the repo-root .env.

Fifty pieces of feedback a week from five channels. A PM reads them and, per message, answers the same ten questions: is this a problem, a request, praise? Which part of the product? How bad? Are they about to leave? Did they build a workaround? Are they asking for something we already have? Then they count. The counting is easy. The reading doesn’t scale.

One expression per message, one request each:

const askAbout = (item: Feedback) =>
sense
.given(item)
.seenAs((f) => ({ message: f.text }))
.ask({
problem: describesProblem, // Noul
request: requestsChange, // Noul
workaround: describesWorkaround, // Noul
confused, // Noul
churnRisk, // Noul
praise, // Noul
reproducible, // Noul
severity, // Score over three described levels
area, // Choice over product areas
existingFeature, // Choice over shipped features
paying: (f) => f.plan !== "free", // code; costs nothing
});

Everything after run() is filter, groupBy, and arithmetic in src/main.ts. The insights are intersections the model never sees as such:

  • Where the pain is: per area, problems × (1 + mean severity).
  • Unmet needs: workaround grouped by area.
  • Discoverability gaps: requestexistingFeature decided, grouped by feature.
  • Churn concentration: churnRisk grouped by plan, then by area.
  • Docs/UX debt: confused grouped by area.
  • Engineering-ready: problemreproducible, sorted by severity.
  • Couldn’t place: area unresolved and nothing else decided.
  • Four people built their own scheduled export. Zapier, cron, a macOS Shortcut, a Friday ritual. None of them said “add scheduled exports”; they described what they do instead. That is a feature request with proof of demand, and a keyword search would never find it.
  • Four requests for things that ship today. Recurring invoices, reminders, multi-currency, the client portal. The fix is discoverability, and the report says so instead of adding them to a roadmap.
  • Team-plan churn is one problem, not four. Every team customer thinking of leaving is talking about roles and permissions.
  • “The app lost my invoice” is confusion, not a bug. Sync latency read as data loss. Engineering can’t fix that; a saving indicator can.
  • “meh”, “ok”, “👎” go under Couldn’t place. The model didn’t file them somewhere plausible. Uncertainty is kept, not hidden.

You could, once. This runs on every message, in the request path if you like, for a few hundred tokens each, and returns typed values code can count. The same ten questions, asked the same way of every message, with calibrated probabilities and an explicit “uncertain”, is what makes the counts mean something week over week. A summary is prose about the feedback. This is data.