---
name: weekly-pipeline-report
description: Produce the Monday-morning weekly pipeline brief for a sales VP from a HubSpot pipeline snapshot and last week's snapshot. Outputs a one-page markdown report with headline metrics, top deals moving the number, top risks, the single biggest pattern, and a recommended ask. Segment-aware. Stamps every metric with movement direction.
---
# Weekly pipeline report
## When to invoke
Invoke every Monday morning, before the sales VP's pipeline review, to produce the weekly brief that goes into Slack `#pipeline-review` or the Monday leadership thread. Input is a current HubSpot pipeline snapshot, last week's snapshot from the same extractor, and a segment-definitions file. Output is a single markdown report sized to fit on one screen — the VP reads it in under three minutes and walks into the review with a point of view.
Do NOT invoke this skill for:
- **Board materials.** The brief is operational. It uses last-week deltas and one-week-stale assumptions about what is real. Board reporting needs reconciled, audited numbers — pull those from the finance system, not from this skill.
- **Customer-facing reports.** The brief names deals, owners, and risks in language that is fine for an internal Slack channel and unsafe to share externally.
- **The actual forecast number.** This skill summarizes pipeline composition and movement. It is not a forecast model. Anyone citing the headline number as "the forecast" is misusing it. The forecast comes from the forecast call, owned by the sales VP and RevOps lead.
## Inputs
Required:
- `pipeline_snapshot` — path to the current HubSpot pipeline export (CSV or JSON), one row per open deal, with columns: `deal_id`, `deal_name`, `owner_id`, `stage`, `amount`, `close_date`, `last_modified`, `segment` (or a column the segment map can join on).
- `previous_snapshot` — path to last Monday's snapshot, same shape. Used for week-over-week deltas. If absent, the skill emits a "no comparison available" header instead of guessing direction.
- `segments` — path to `references/segment-mapping.md` (or a YAML/CSV of the same shape). Defines the segment slices the report uses.
Optional:
- `report_format` — path to `references/report-format-template.md`. If absent, the skill uses the embedded default in the Output format section below.
- `hedge_blocklist` — path to `references/hedge-words-blocklist.md`. The hedge-removal pass refuses to ship the brief while any blocked term appears in the draft.
- `top_n` — integer for "top N deals" and "top N risks" sections. Default `3`.
## Reference files
Read these from `references/` on every run. They are the levers the user adapts to their team — without them, the report is generic.
- `references/report-format-template.md` — the literal layout the brief follows, with placeholder blocks for headline metrics, top deals, top risks, the pattern, and the ask. The user edits this file to change the report shape; the skill does not invent its own layout.
- `references/segment-mapping.md` — defines the segments the report slices by (Enterprise / Mid-Market / SMB, or whatever the team uses) and the rule for assigning each deal to a segment when the snapshot does not carry one.
- `references/hedge-words-blocklist.md` — the wording rules. The hedge-removal pass rejects a draft if any of these appear. Replace as your team's vocabulary evolves.
## Method
Run these steps in order. Do not parallelize — later steps depend on earlier ones.
### 1. Load and validate both snapshots
Read `pipeline_snapshot` and `previous_snapshot`. Confirm that both share the same column shape and that `deal_id` is unique within each. If `previous_snapshot` is missing or the schema does not match, set `comparison_mode = none` and proceed — the brief will skip every WoW figure and label the header as a baseline run rather than fabricating zero-deltas.
### 2. Join to segment definitions
Apply `references/segment-mapping.md` to assign every deal to a segment. Engineering choice: segment-aware rather than aggregate. An aggregate "pipeline is up four percent" hides the case where Enterprise is down twelve and SMB is up thirty — opposite stories that the VP must respond to differently. The segment slice keeps the call honest. If a deal cannot be assigned to a segment, route it to a visible `unsegmented` bucket and surface the count in the report — never silently drop deals.
### 3. Compute headline metrics, segment-by-segment
For each segment compute: total open pipeline (sum of `amount`), deal count, average deal size, weighted pipeline (if probability data is present), pipeline by stage. For each metric: compute the WoW delta (absolute and percent) and a movement-direction label (`up`, `down`, `flat`). Engineering choice: include movement-direction on every metric, not just the headline. The VP scans the page in one pass. If only the top number carries direction, the rest reads as "data" instead of "story" and the eye skips it.
### 4. Identify the top deals moving the number
For each segment, rank deals by absolute change in `amount` or `stage` since `previous_snapshot`. Take the top `top_n` (default 3). For each: name, owner, amount, what changed (stage transition, amount adjustment, new add, slipped close date), and a one-line plain-English description of the move. Deals with no change do not appear here — this section is about motion, not size.
### 5. Identify the top risks
Rank deals by risk signal: stage regression, close date pushed for the second consecutive week, amount cut by more than 25 percent, or no activity for 14+ days on a deal forecast to close this quarter. Take the top `top_n`. For each: name, owner, the risk signal, and a one-line description. Engineering choice: surfaces deals that are *quietly* slipping. The loud risks (CFO email, "we lost") get escalated through other channels; this section is for the deals that look fine in the board view but smell off.
### 6. Find the single biggest pattern
Look across the segment metrics, the moving deals, and the risks. Name one pattern — e.g. "Enterprise pipeline is up but stage-1 dominates the add; the quarter is being filled with deals that will not close in it" or "Three of five top-risk deals are owned by the same AE." Engineering choice: one pattern, not five. The brief is read in three minutes. Five patterns is a list; one pattern is a point of view, which is what the VP needs to walk into the room with.
### 7. Recommend a single ask
Translate the pattern into one ask the VP can make of the room — "have the Enterprise lead defend the stage-1 quality of the new adds" or "review the pushed-twice deals owner-by-owner with the named AE." One ask. If the skill cannot produce one, it writes "no clear ask this week — pattern was diffuse" rather than padding.
### 8. Hedge-removal pass
Re-read the draft. If any term from `references/hedge-words-blocklist.md` appears (e.g. "may", "might", "could potentially", "appears to suggest"), rewrite the offending sentence. Engineering choice: hedging language drifts in because the model is being polite about uncertain data. The brief is more useful when it states the observed pattern flatly and lets the reader push back, than when it pre-hedges every claim. The hedge-removal pass is the guard against that drift — it is mechanical, run after the draft, and refuses to ship a brief that violates the blocklist.
## Output format
The brief follows this literal structure (also stored at `references/report-format-template.md` for the user to edit):
```markdown
# Weekly pipeline brief — {Week of YYYY-MM-DD}
## Headline (vs. last Monday)
- Total open pipeline: $X.XM (up $Y.YM, +Z%)
- Weighted pipeline: $X.XM (down $Y.YM, -Z%)
- Deal count: NNN (flat, +0)
- Avg deal size: $X.XK (up $Y.YK, +Z%)
## By segment
| Segment | Open $ | WoW | Deal count | WoW |
|---|---|---|---|---|
| Enterprise | $X.XM | up +Z% | NN | up +N |
| Mid-Market | $X.XM | down -Z% | NN | flat |
| SMB | $X.XM | up +Z% | NN | up +N |
## Top 3 deals moving the number
1. **{Deal name}** — {Owner}, $XXk. Stage 2 → Stage 4 this week; demo with
{stakeholder} landed.
2. **{Deal name}** — {Owner}, $XXk. New add; sourced from {channel}.
3. **{Deal name}** — {Owner}, $XXk. Amount up $XXk after scope expansion.
## Top 3 risks
1. **{Deal name}** — {Owner}, $XXk. Close date pushed for the second week.
2. **{Deal name}** — {Owner}, $XXk. Stage regressed 4 → 3.
3. **{Deal name}** — {Owner}, $XXk. No activity for 18 days; forecast Q-end.
## The pattern this week
{One paragraph naming the single biggest pattern. Flat statement, no hedging.}
## Recommended ask
{One sentence — the ask the VP makes of the room.}
```
If `comparison_mode = none`, replace the "(vs. last Monday)" header with "(baseline — no prior snapshot)" and drop every WoW column.
## Watch-outs
- **Confident-but-stale data.** The HubSpot snapshot is only as fresh as the extractor's last run. If `last_modified` on the snapshot file is more than 24 hours old, the brief prepends a one-line warning: "Snapshot is N hours stale — figures may not reflect Friday's late-week activity." Guard: the snapshot freshness check runs before step 1; the brief refuses to ship without it.
- **Hedging language drifting in despite removal.** The hedge-removal pass uses a fixed blocklist; new hedge phrasings the model invents will slip through. Guard: the user is expected to extend `references/hedge-words-blocklist.md` whenever they spot a hedge that landed. The blocklist is a living file, not a one-time setup.
- **Downstream readers citing this as the forecast.** The brief headlines an open-pipeline number, which a casual reader will round to "the forecast." Guard: the brief footer always reads "Operational summary, not a forecast. Forecast is owned by {VP name} and produced in the Friday call." This line is in the report-format template; do not remove it.
- **Owner reassignments mid-week.** If a deal changed owner since the previous snapshot, both the old owner's "lost the deal" delta and the new owner's "gained a deal" delta will fire — double-counting motion. Guard: the skill emits a "deals reassigned this week: N" footnote and excludes those deals from the "top deals moving the number" section to avoid attributing the move to either owner.
# Report format — TEMPLATE
> Replace the placeholders below with values from your snapshot. The
> weekly-pipeline-report skill reads this file as the literal layout it
> follows. Edit this file, not the skill, to change the report shape.
# Weekly pipeline brief — Week of {YYYY-MM-DD}
## Headline (vs. last Monday)
- Total open pipeline: {$X.XM} ({up/down/flat} {$Y.YM}, {±Z%})
- Weighted pipeline: {$X.XM} ({up/down/flat} {$Y.YM}, {±Z%})
- Deal count: {NNN} ({up/down/flat}, {±N})
- Avg deal size: {$X.XK} ({up/down/flat} {$Y.YK}, {±Z%})
> Every metric carries a movement-direction word. If the previous-snapshot
> input is missing, replace this whole block with: "Baseline run — no prior
> snapshot to compare against."
## By segment
| Segment | Open $ | WoW | Deal count | WoW |
| ------------ | -------- | ----------- | ---------- | ----------- |
| Enterprise | {$X.XM} | {up +Z%} | {NN} | {up +N} |
| Mid-Market | {$X.XM} | {down -Z%} | {NN} | {flat} |
| SMB | {$X.XM} | {up +Z%} | {NN} | {up +N} |
| Unsegmented | {$X.XM} | {-} | {NN} | {-} |
> The unsegmented row stays in the table even when zero — its presence is the
> evidence that the segment-mapping pass actually ran.
## Top 3 deals moving the number
1. **{Deal name}** — {Owner}, {$XXk}. {What changed in plain English: stage transition, new add, scope expansion, slipped close date.}
2. **{Deal name}** — {Owner}, {$XXk}. {What changed.}
3. **{Deal name}** — {Owner}, {$XXk}. {What changed.}
## Top 3 risks
1. **{Deal name}** — {Owner}, {$XXk}. {Risk signal: pushed twice, stage regression, amount cut, dormant.}
2. **{Deal name}** — {Owner}, {$XXk}. {Risk signal.}
3. **{Deal name}** — {Owner}, {$XXk}. {Risk signal.}
## The pattern this week
{One paragraph naming the single biggest pattern across the segments, the moving deals, and the risks. Flat statement, no hedging. If the data is diffuse, write "no dominant pattern this week" rather than padding.}
## Recommended ask
{One sentence the VP can carry into the room. If the pattern was diffuse and no clean ask follows, write "no clear ask this week" — do not invent one.}
---
Operational summary, not a forecast. Forecast is owned by {VP name} and produced in the Friday forecast call.
Snapshot freshness: {N hours} (extractor ran {YYYY-MM-DD HH:MM}). Deals reassigned this week: {N} (excluded from top-moves section).
# Segment mapping — TEMPLATE
> Replace the rules below with your team's segmentation. The
> weekly-pipeline-report skill applies these rules to assign every deal in
> the snapshot to one segment row in the report. Deals that match no rule
> land in the visible `unsegmented` bucket — never silently dropped.
## Segment definitions
The skill emits one row per segment named here. Order in the report follows the order in this file.
- **Enterprise** — {definition rule, e.g. "deal `amount` >= $100k OR account headcount >= 1000"}
- **Mid-Market** — {definition rule, e.g. "$25k <= `amount` < $100k OR account headcount 100-999"}
- **SMB** — {definition rule, e.g. "`amount` < $25k OR account headcount < 100"}
> If your team segments by industry, geography, or product line instead of
> deal size, replace the dimensions above. The skill is agnostic — it
> applies whatever rules this file declares, in order.
## Assignment rule
When a deal would match more than one segment row, the **first match wins**. That is why segment order in this file matters. If you want amount-then-headcount precedence, list the amount segment first.
## Snapshot column
The skill expects each deal row in the snapshot to carry the columns the rules reference (e.g. `amount`, `account_headcount`, `industry`). If a rule references a column the snapshot does not have, the rule is skipped and the skill logs the skipped rule in the report's footer.
## Owner-to-segment override
Optional. Some teams assign owners to segments rather than deriving from the deal. If an owner-to-segment table is present here, it overrides the deal-level rules above.
| Owner ID | Owner name | Segment |
| --------- | --------------- | ------------- |
| {12345} | {Alice Example} | Enterprise |
| {12346} | {Bob Example} | Mid-Market |
| {12347} | {Carol Example} | SMB |
## Unsegmented handling
Deals that match no rule (and have no owner-to-segment override) appear in the report as `unsegmented`. The brief surfaces the count even when zero. A non-zero unsegmented count for two consecutive weeks is the signal to revisit this file.
## Last edited
{YYYY-MM-DD}
# Hedge words blocklist
> The weekly-pipeline-report skill runs a hedge-removal pass after the draft.
> If any term below appears in the brief, the skill rewrites the offending
> sentence before shipping. Extend this list whenever a hedge slips through
> in production — the file is meant to evolve.
## Why a blocklist
Hedging language drifts in because the model is being polite about uncertain data. A weekly brief that hedges every claim is unreadable, and the VP starts ignoring it. The blocklist enforces flat statements; the reader pushes back if a claim is wrong, which is the correct shape of the loop.
## Blocked phrases (rewrite required)
### Modal hedges
- may
- might
- could
- could potentially
- possibly
- perhaps
- presumably
### Epistemic hedges
- seems to
- appears to
- appears to suggest
- looks like it might
- it is unclear whether
- it is unclear if
- it is worth noting that
- it is important to note that
### Quantifier hedges
- somewhat
- relatively
- generally
- broadly
- to some extent
- in some cases
- arguably
### Qualified-recommendation hedges
- you may want to consider
- it might be worth
- one option could be
- it could be useful to
- you could potentially
### Vague intensifiers (allowed in dialog, blocked in the brief)
- significant
- meaningful
- notable
> The intensifiers above are blocked because they describe size without
> quantifying it. The brief carries every metric with a number; size words
> without numbers are noise.
## Allowed alternatives
The hedge-removal pass rewrites blocked phrases into one of these patterns:
- Replace "X may be Y" with "X is Y" (if the data supports it) or with "the data does not show whether X is Y" (if it does not).
- Replace "X seems to be growing" with "X grew $N WoW" or drop the claim.
- Replace "you may want to consider Z" with "Z" as an imperative, or with "do Z" — the brief is operational; the recommendation is the recommendation.
- Replace "significant increase" with the actual percent or dollar figure.
## Exceptions
The "Recommended ask" section may use an imperative without softening ("review the pushed-twice deals owner-by-owner"). It does not need an allowed-alternative rewrite — the imperative is already the target shape.
## Last edited
{YYYY-MM-DD}