| name | brief-generation |
| description | Produce or update the workspace brief — load context, identify focus repo + user lean, cross-reference activity into Kai-relevant action items, synthesize, save |
| version | 1.0.0 |
| author | kai-agent |
| metadata | {"kai":{"tags":["kai","lifecycle","brief","status","dashboard"]}} |
Brief Generation
You are writing the workspace's brief — the status page the team sees when they open the Brief page. Not a diary. Not a once-a-day report. It updates whenever there is something the team should know — a critical vuln confirmed, a PR shipped, a plan change. The brief is rolling status, not a daily log.
Think of the brief as your Slack status + LinkedIn update combined — it's how your teammates see your work without asking. If they check the Brief page at 3pm and you've been busy, they should see what you've been busy with.
The Rules
- Activity-grounded, not stat-counter shaped. The brief reflects real recent work — Kai's own + the team's GitHub work — not abstract counters.
- Headline the delta vs yesterday, never the absolute state. A finding that was already in yesterday's brief lives in
needsAttention; the headline rotates to the next most-impactful change.
- Salience first, preference second, balance fallback. Critical vulns / regressions / blockers always lead. Non-critical slots tilt toward the user's observed lean. Force category diversity only when both signals are weak.
- Always update. Even on a quiet cycle — a frozen brief looks like Kai is asleep. Use the quiet-cycle template instead of skipping.
- No fake confidence on first cycles. First-cycle briefs are scoping-shaped. Say what's known, what isn't, what we'll go after first.
Phase 0 — Load context (read-only, parallelizable)
Before deciding anything, gather the inputs in parallel.
- The previous brief (today's if it already exists for this
cycleTag, otherwise yesterday's) — what was the headline, which needsAttention items are still pending? Read via kai_get_workspace_briefing (or list endpoint) so you can compare-against-last. If today's brief already exists, you are updating it, not replacing it.
kai_workspace_blueprint_get — current understanding of the workspace (architecture, team, infra, posture).
kai_workspace_learnings_list — recent facts (last 7 days). If the brief was triggered by a chat with a specific user, prefer learnings tagged @<handle>: for that user.
kai_get_agent_analytics — Kai's own activity (audits run, optimizations, findings, credits) since the last cycle.
- Integration activity (one-time per session:
kai_activate_category(category="integrations")):
kai_list_pull_requests(workspaceId, repoId, state="all", limit=30) on each top active repo, filtered to last cycle window.
kai_list_commits(workspaceId, repoId, since="<last cycle>", limit=50) on each top active repo.
If a data source is unavailable, note it in one line and move on. Don't fabricate.
Phase 1 — Identify focus + observed user lean
Focus repo
The repo with the most user activity this cycle is the focus repo. Rank by: merged PRs > new commits > newly opened issues. If two repos are close, pick the one with security-adjacent file paths. If everything is quiet across the board, the focus is the workspace itself, not a repo — see the quiet-cycle template.
Observed user lean
What category does the user's behavior tilt toward? Pull from these signals, in order:
- Recent learnings tagged
@<handle>: for the current speaker (chat-triggered briefs only).
- Recent lifecycle actions they've approved (audit-heavy? optimization-heavy? hygiene-heavy?).
- Recent chat themes — if you have prior conversation context, what did they want to talk about?
- Workspace blueprint hints — explicit notes like "team prioritizes performance" or "security review every sprint."
If the signal is weak (first cycle, new user, mixed behavior across all four), record lean = "unbiased" and fall through to balance fallback in Phase 3.
Phase 2 — Cross-reference patterns
Turn raw activity into Kai-relevant action items. Walk the catalog. Each match becomes a needsAttention candidate or a highlight.
| Pattern | Slot |
|---|
| User merged PR touching repo X + last audit on X is older than 14d | freshness needsAttention |
| New dependency added in package manifest + dependency has CVE history | audit-on-deps candidate |
| Repo with high recent commit velocity + low test coverage | hygiene candidate |
| Function refactored (rename / signature change) + perf benchmarks not updated | optimization-verify candidate |
| Open critical PR + author silent for >3 days | blocker needsAttention |
| New critical vuln since last brief | headline candidate (overrides preference) |
Same finding still in needsAttention from yesterday + still unresolved | keep, do not re-headline |
| New repo connected since last brief | scoping highlight (run baseline audit?) |
| Long-running optimization completed | highlight (with bestScore delta) |
Add patterns specific to this workspace as you discover them — write them as workspace_learnings (category="pattern") so future cycles inherit them.
Phase 3 — Synthesize
Apply the salience-first rule.
Salience first — any unpatched critical vuln, regression, or blocker leads regardless of user lean.
Criticality + recency are immovable.
Preference second — in non-critical slots (highlights, suggestedChatPrompts, secondary needsAttention),
tilt toward the observed lean from Phase 1.
Balance fallback — when there's no critical signal AND no clear lean, default to category diversity.
Build:
- headline — delta vs yesterday, not absolute state. See Headline rules.
- summary — 2–4 sentences. Open with a timestamp line:
_Updated: 2026-04-27 14:32 UTC_.
- posture + trend — per the threshold rules below.
- highlights — 3–6
{icon, text} items, biased per salience-first.
- needsAttention — only when actually needed, max 5. Every item must be clickable (
actionId or inline markdown link).
- suggestedChatPrompts — 3–5 follow-up prompts per the criteria below.
Headline rules
- 8–14 words, written as a newspaper headline.
- Start with a concrete subject. Use an active verb. Name a number when relevant.
- Headline the delta vs yesterday's brief, not the absolute state.
- Bad: "Today I made progress on the audit"
- Bad: "3 critical CVEs still open in payment-service" (if same as yesterday)
- Good: "Patched 3 critical CVEs in payment-service; 12% latency win shipped on /checkout"
- Good: "alice merged payment-service refactor; no audit since — freshness check overdue"
- Quiet cycle (use verbatim shape): "Quiet cycle: no audits run, no PRs merged, posture stable."
Posture & trend selection
POSTURE
critical: any unpatched high/critical vuln older than 7 days
attention: open lifecycle actions awaiting approval >48h, OR regressions, OR blocked work
healthy: no open criticals, all approved actions in flight, audits current
TREND (compared against last 3 cycles)
improving: criticals fixed faster than they appear; net wins shipped
declining: net new criticals, blocked actions accumulating, audit freshness slipping
stable: no meaningful delta
These are thresholds, not vibes. If the data doesn't fit one cleanly, pick the more conservative option and explain in the summary.
Suggested-prompt criteria
3–5 prompts that surface as clickable buttons under the brief. They must be:
- Specific to this brief's content. Bad: "Tell me more." Good: "Why does payment-service still have no audit after alice's refactor?"
- Actionable — each leads to a useful conversation.
- Varied — mix investigation, planning, and communication.
- Spread across categories (audit / optimize / hygiene / review) but biased per salience-first.
Pass them as suggestedChatPrompts in the kai_save_workspace_briefing call.
Phase 4 — Cover image + save
-
Cover image (best-effort, optional — skip on failure rather than blocking the brief):
generate_cover_image(seed=f"{workspaceId}:{cycleTag}")
Same seed → same image all day. Rotates tomorrow.
-
Save with kai_save_workspace_briefing(...):
cycleTag: today's date, YYYY-MM-DD. Successive calls on the same cycleTag update the same brief.
headline, summary, posture, trend, highlights, needsAttention, suggestedChatPrompts
coverImage: pass the returned url + prompt + subjectIndex from generate_cover_image if it succeeded.
stats: {findingsTotal, findingsCritical, scansRun, actionsCompleted, creditsUsed} — pulled from kai_get_agent_analytics.
Edge cases
Quiet cycle (no meaningful work since last brief)
Still update. Use the quiet-cycle headline shape. Lean on suggestedChatPrompts to surface what could happen next ("Run a freshness audit on the oldest repo?", "Review the 2 open PRs that haven't moved in 5 days?"). Set posture = "healthy" if no criticals, trend = "stable". Do not skip — a frozen brief looks like Kai is asleep.
Same finding spanning days
Once an action exists for a finding, the finding lives in needsAttention until resolved. The headline rotates to the next most-impactful delta. Don't re-headline the same critical day after day — the user will tune it out.
First-cycle workspace
The brief is scoping-shaped: what's connected, what's known so far, what we'll go after first. No fake confidence. Default to balance fallback (no lean signal yet). Posture is whatever the initial scan supports — not "healthy by default."
Multi-repo workspace, no clear focus
If activity is spread thin across many repos, name 2–3 repos in the summary and pick highlights from across them. The focus-repo logic is a default, not a constraint.
Per-speaker awareness (chat-triggered briefs)
When the brief is triggered inside a chat with a specific user:
- Prefer that user's
@<handle>: learnings for content focus and tone.
- Use their observed lean from Phase 1.
- Do NOT mention their handle inside the brief markdown — the brief is workspace-facing, not 1:1.
When triggered by cron with no current speaker, fall back to workspace-level learnings only — preference signal weakens, salience-first still leads.
What NOT to do
- Don't force a 2-2-2 distribution across audit / optimization / hygiene. Salience and lean drive the mix.
- Don't re-headline yesterday's findings. They live in
needsAttention until resolved.
- Don't write generic suggested prompts. "Tell me more" is filler.
- Don't dump raw counters as the headline ("3 critical, 7 high, 14 medium"). The headline is one delta, not a tally.
- Don't skip the brief on a quiet day. Use the quiet-cycle template instead.
- Don't fabricate activity. If a data source is empty, say so in one line.
Smoke checklist (run mentally before saving)