MSO Cloud · Documentation

Morning Brief

Source: docs/guides/morning-brief.md Updated 2026-09-21
On this page

The Morning Brief is a short daily digest that tells the people running an organization what needs attention today, and which signal rules produced that conclusion. It is not a report. A report answers a question you already had; the brief exists to tell you the question you did not know to ask, and to stay quiet when there is nothing to say.

Every line in a brief traces to a rule that fired on a named signal, over a named window. Nothing in it is a summary an assistant wrote from a dashboard.

Where it lives and who sees it#

The brief is at /briefing, in the product. It is in-app only: there is no emailed or messaged copy of the brief document itself. Individual alerts inside it can be routed to email or Zalo, and the design rule for those is that a message is a pointer to the brief, never a duplicate of its content.

Reaching the page needs two things at once:

  1. The reader's role carries the briefing menu grant. Every built-in role carries it by default; an org admin can remove it per role at /admin/orgs/<slug>/roles. Reading the brief does not need manage_ai — that capability is the right to configure the AI layer, and the brief is a document written for the org's operating readers.
  2. The organization runs at least one briefable data plane: commerce, marketing, market estimates or social.

The brief is not part of the decision-intelligence feature bundle, and turning that bundle on or off does not affect it. That bundle covers the action queue, the playbook library and the weekly memo.

That last gate is why a Content Intelligence organization has no brief. Its delivered corpus is a document a client signed off, not an operational surface with a state that can change overnight; a daily alarm over it would be noise.

An org admin can also re-run the brief by hand from that page. A manual re-run always produces the daily brief.

Cadence#

Run When Time zone
Daily 07:00, every day Vietnam time
Weekly 07:00, every Monday Vietnam time
Monthly 07:00, on the 1st Vietnam time

All three run on the Vietnam calendar day, not on UTC. That matters here more than it sounds: a job that runs at 07:00 local time is still on the previous UTC day, and a brief dated by the UTC day would be dated yesterday every single morning.

The cadence spine anchors each window to the latest day that actually carries data, not to today's date. When a connector is behind, the brief says the data runs to a particular day rather than reporting that the business stopped selling.

One current limitation, stated plainly: the weekly and monthly runs read the same recent window as the daily run and reframe it as a weekly or monthly brief. They do not yet compute a seven-day or a month-long comparison of their own.

Personas#

A brief is written for a role, not for a person. Three personas exist, and which ones an organization generates is decided by the data planes it actually runs, not by a label someone typed:

Organization runs Personas generated What the headline leads with
Commerce (marketplace orders) Owner and Ops Owner: yesterday's GMV, its change, and contribution margin. Ops: how many signals need handling on the morning shift, then the same commerce figures
Marketing, without commerce Marketing Ad spend against its own recent baseline, leads bought, cost per lead, and pacing against plan
Neither yet Owner and Ops, without the commerce clause The signal count alone

The distinction is not cosmetic. A marketing agency reading an eCom brief was told every morning that it had no marketplace order data - technically true, useless, and it trained the reader to skip the page. The marketing headline never mentions a marketplace, and it abstains part by part: if spend is known but cost per lead is not, it prints the spend and says nothing about cost per lead. It never prints a zero for a number it does not have.

A market-context line is written for the owner persona only. Ops and marketing readers get the operational lines.

A brief carries a summary and up to four bullets, deduplicated by title, ranked by severity. Fewer is allowed. The cap and the floor both exist because of the same failure: a brief padded to a fixed length repeats itself, and a reader who sees filler twice stops reading the real lines.

What the marketing pack watches#

Each briefable plane ships a default rule pack. The marketing pack has eleven rules. All of them read day-grain, first-party signals from the organization's own ad accounts, and all of them are addressed to the organization rather than to the platform.

Rule What it detects How it decides Severity
Cost per lead spike Lead cost jumped At least 1.3x its own trailing 7-day mean Warn
Delivery cost inflation Impressions got more expensive At least 1.3x the trailing 7-day mean Warn
Result rate drop Fewer results per impression At most 0.7x the trailing 7-day mean Warn
Click-through collapse People stopped clicking At most 0.7x the trailing 7-day mean Warn
Pacing overspend Spending ahead of plan More than 20% over the pro-rated plan Warn
Frequency fatigue The same people keep seeing it Average frequency at or above 3.0 Info
Landing-page drop-off Clicks are not arriving on the page 60% or more of link clicks never became a page view Warn
Spend with zero results Money bought nothing Result rate at or below zero, only when spend clears 1,000,000 VND Critical
Result signal outage The results feed went silent Two consecutive periods with no value, only when spend clears 1,000,000 VND Warn
Lead cost uptrend Lead cost rising day after day Three consecutive increases, only when spend clears 1,000,000 VND Info
End-of-flight shortfall The month will not land on plan More than 30% behind plan, only once the month is 60% elapsed Warn

Two design choices are worth understanding, because they explain why the pack looks the way it does.

Cost rules compare against the account's own history, not against a fixed price. A fixed VND ceiling on cost per thousand impressions is a client-specific number: a Tet push and an always-on funnel do not buy at the same price. A ratio against the account's own trailing mean travels between clients; a fixed number does not.

Rules that could fire on noise carry a spend gate. The three most alarming rules - zero results, signal outage, cost uptrend - only evaluate once the entity has spent a material amount. Below that, there is not enough money on the table to distinguish a problem from a rounding error.

There is deliberately no rule on marketing efficiency ratio or return on ad spend. Those figures are computed and shown on the marketing surfaces, but they are not written into the signal store, so a rule on them could never fire. A rule that can never fire is worse than no rule: it looks like coverage.

How a rule decides#

Six detection operators reduce a series to something a single comparison can judge. This is one vocabulary, shared by the brief and by the playbook catalogue.

Operator What it does Fails safe when
threshold Takes the latest value and compares it against a bound The latest value is missing
anomaly Compares the latest value to the mean of the N periods before it, as a ratio There are no usable baseline points, or the baseline is not positive
derived Judges the change from the previous period, as an absolute delta or a percentage change The previous value is zero, so no honest percentage exists
streak Counts consecutive moves in one direction, backwards from the latest A missing value breaks the streak
pacing Compares actual against target as a ratio, with a bar that can be how far through the month you are The target is not positive, or the calendar bar cannot be resolved
absence The one thing a comparison cannot express: the signal stopped arriving The series never had data, or is shorter than the required run - because "we lost it" is a claim about a change

Any rule can also carry gates: preconditions that must hold before the detection is judged at all. A gate can require another signal to clear a bar (spend must be material), or a calendar position (the month must be at least 60% elapsed).

The rule that makes all of this trustworthy is one sentence: an unknown gate is not an open gate. A missing series, a null latest value or an unparsable period makes a gate false, so the rule does not fire. Nothing is assumed in order to produce a line.

Tuning it#

Rule packs are configured at /settings/alerts, which needs the manage_org_settings capability - org admin by default. The page lists, per data plane the organization runs, the rules in that plane's default pack.

What you can change today, per person:

  • Mute a rule, so it stops reaching you.
  • Snooze it for 24 hours or 7 days.
  • Choose its channels: in-app, email, Zalo. In-app is the default for every rule until you say otherwise - no rule reaches you by email or Zalo on its own, including one a pack just installed. The stored channel policy is a ceiling on top of that default; a person's choice can narrow it, never widen it past what the ceiling allows.

What you cannot change yet, and this is deliberate rather than an oversight: there is no org-wide threshold control on this page. Editing a threshold needs its own storage and its own record of why the number is what it is, and shipping a control without that would let a number drift with nobody able to say who moved it or why. Playbook thresholds are editable, in the playbook rule editor, where a reason for the number is a required field - see Marketing Playbooks. The two surfaces are not the same thing and are deliberately not merged.

Muting is about notification, not about evaluation. A muted rule is still evaluated and still recorded as having fired; you simply are not told. That keeps the history honest while the noise is turned down.

Why a brief sometimes says it does not know#

Abstention is not one banner. It happens at four different layers, and each says something different.

A rule with no signal does not fire. If a rule names a signal the organization does not compute, the rule is skipped. It does not error, and it does not guess.

A rule below its evidence floor answers "not enough data", not "fine". A playbook rule declares a minimum spend and a minimum number of days in the window. Below either, the finding is recorded with the status unknown and the reason - not enough spend, not enough days, or a missing signal. The rule editor's own help text says it outright: below this line the system returns chưa đủ dữ liệu, and that is not the same as a clean bill of health.

Three-valued logic runs all the way through. A condition is true, false, or unknown. In an AND, one failure fails; otherwise one unknown makes the whole thing unknown. Unknown never becomes a match.

A quiet day says so, once. When nothing at all fired, the brief prints exactly one bullet saying so, with a link to the surface where you could look anyway - the marketing performance page for the marketing persona, the action queue for owner and ops. It is one line, not a page of reassurance.

And there is one thing the brief deliberately does not report: it does not tell you at 07:00 that some entities were unmeasurable. That state is real, and it is shown on the audit card in the product. It is not news every morning, and a brief that reports "0 alerts" plus a paragraph of caveats every day is a brief people stop opening.

If one plane's collector fails, the brief continues without that plane rather than failing entirely.

Who a signal is addressed to#

Every rule declares an audience, and that audience is a hard boundary, not a default someone can configure around.

  • Organization signals - everything in the marketing, social and market packs, plus the commerce rules like imminent stockout, GMV anomaly, return-rate spike and margin collapse - go to the organization's own members.
  • Platform signals - webhook lag, a failed sync run, a critical reconciliation break, budget burn - go to super admins only. A tenant can neither diagnose nor fix the plumbing we run, so telling them is alarming without being actionable.

That boundary is enforced in three independent places: the org-facing evaluator skips platform rules outright, the recipient resolver returns super admins for a platform rule regardless of any preference, and the org-admin settings page never lists a platform rule to begin with.

By organization type#

Organization type Brief today
Marketplace / eCom The most complete pack: GMV, margin, inventory, creator performance and returns, on a daily cadence, with owner and ops personas
Marketing The eleven-rule marketing pack above, with the marketing persona and a media-first headline
Market intelligence The market pack exists - category contraction, top-shop share shift, competitor revenue breakout - and reads third-party estimates, which are never treated as first-party facts
Social A social pack exists - share-of-voice drop, buzz anomaly, trend surge - and its signals form hypotheses, never scored outcomes
Content intelligence No brief, by design. The delivered corpus is a document, not an operational surface

Sources#

  • docs/adr/0035-morning-brief-per-org-type.md - the brief's per-org-type design
  • apps/web/src/app/(dashboard)/briefing/page.tsx - the surface and its four gates
  • apps/worker/src/schedules.ts - the three cadences and their time zone
  • packages/agent/src/index.ts - personas, headline composition, the quiet-day bullet
  • packages/metrics/src/briefing-cadence.ts - anchoring a window to the latest day with data
  • packages/alerts/src/packs/marketing.ts - the eleven marketing rules
  • packages/alerts/src/signal-conditions.ts - the six detection operators and gates
  • packages/alerts/src/signal-rules.ts, packages/alerts/src/index.ts - evaluation, audience and delivery
  • apps/web/src/server/routers/alerts.ts, apps/web/src/app/(dashboard)/settings/alerts/ - the tuning surface
  • packages/metrics/src/marketing-audit.ts - evidence floors and the unknown verdict