---
title: Weekly Summary (Monday-morning recap, folded into Daily Digest)
---

# Weekly Summary (Monday-morning recap, folded into Daily Digest)

## What it is

Weekly Summary is a once-a-week AI-written recap of how you used Omniscio over the just-completed week, plus a short list of personalized suggestions for getting more out of the app. As of **2026-05-14** it ships as a **briefing inside [Daily Digest](daily-digest.md)** — same sidebar entry ("Briefings"), same inbox section, same triage shortcuts. The time window is `Monday 00:00 → Sunday 23:59:59 local` (ISO week) and the input is a single envelope blending three things: aggregate stats (sessions, messages, top projects, top features, AI spend, week-over-week deltas), an eleven-field detector payload (six privacy-preserving behavioral detectors from Workflow Coach plus four newer ones: top operator phrases, feature-usage deltas, attention backlog aging, cron-job health), and the last 90 days of suggestion dismissals so the model learns from your past "not useful" picks. The suggestions themselves come from a **Map → Reduce → Verify** three-step pipeline (Luna → Opus 4.7 → Luna) where Opus must self-cite which envelope fields each suggestion depends on and Luna fact-checks those claims before the row lands. (The Map and Verify model follows the global Utility AI model setting and the per-feature `weeklySummaryModel` override — see _Settings field map_ below; Reduce stays on Opus 4.7.) Weekly Summary **subsumes Workflow Coach** — the standalone Suggestions panel and the separate weekly inbox alert are gone. In the inbox the briefing now surfaces as **two cards** (2026-07-20): a slim scannable recap card and a separate "N suggestions from last week" card, so the suggestions get their own labelled row (see _How to use it_ §4).

**On by default** (owner decision 2026-07-27): a fresh install generates a recap every Monday at 7 AM local without opting in. On first launch it seeds **only the most-recently-completed week** — older missed weeks are treated as **past-due** and skipped (the freshness gate under _How it works_, 2026-08-03), so a user who missed an app update or was away for a while never gets a burst of stale, weeks-old recaps dumped into their inbox. Existing users were force-enabled once when default-on shipped (a one-time `weeklySummaryDefaultOnMigrationDone` flip — their config already carried an explicit `false`, so the new schema default couldn't reach them). It costs nothing until there's an **API-key account** to bill — an account on a Claude login (OAuth) can't call the Messages API, so the Monday run skips instead of erroring. That skip is **no longer silent** (2026-08-29): because OAuth tokens can never reach the Messages API, it fired every week forever with nothing but a log line — the skip returns before the LLM calls, so it throws nothing, never reaches the failure path, and never fed the give-up alert, leaving an on-by-default feature permanently dead and unexplained. It now raises the shared **"Add an API key to turn on AI helpers"** inbox card — the same deduped card the other AI helpers use, carrying the one-click _Add API key_ button, latched once per run and self-clearing once a key exists. Turn it off any time in Settings (below); once off, it stays off — and a user who turned it off gets no card.

## Where to find it

Open **Briefings** from the Omniscio sidebar. That one entry lists daily digests and weekly summaries together, newest first, each row carrying a header pill that says which cadence it is, with unread rows marked by the same small amber dot used elsewhere for needs-you signals. A weekly row falls into the same **Active**, **Snoozed** and **Archived** buckets as a daily one.

In the **Inbox**, the same week appears under the **Briefings** section as two separate rows: the recap card, and a second card titled "N suggestions from last week".

Its settings live at **Settings → Email & Summaries → Daily digest**. Expand the card and scroll to the **Weekly Summary** sub-section at the bottom of the panel, where the master toggle, the generation hour, the daily cost cap and the **Run now** button all sit. The standalone weekly sidebar entry, its own inbox section and its old Settings → AI Coach home are gone — those four surfaces were folded into Daily Digest.

## How it behaves

### How to use it

1. **It's already on (change it here).** Weekly Summary is on by default — there's nothing to enable. To turn it off (or back on): Settings → **Email & Summaries** → **Daily digest** (expand the card), scroll to the **Weekly Summary** sub-section at the bottom of the panel, and flip the master toggle. Pick a generation hour (0–23, defaults to 7 AM local — the summary lands before you check email Monday morning). Optionally tune the daily cost cap (default **$0.10**, range `$0.05` – `$5.00`) — once the cap is hit Omniscio stops generating that day and resumes the next. The Daily Digest and Weekly Summary toggles are independent — you can turn one on without the other.
2. **Let it run.** A periodic tick (every 15 minutes) checks the clock; once your chosen hour has passed on a Monday and the just-completed week's summary hasn't been generated yet, it runs. **First launch:** if `weeklySummaryBackfillCompleted` is still false, Omniscio seeds **only the most-recently-completed week** — older candidate weeks are **past-due** (below the freshness horizon) and skipped, so a stranded or returning user never gets a backlog of old recaps. The generation is still gated by the same daily cost cap as the live path, and the flag flips in `finally` so a transient error doesn't loop on every relaunch (a past-due skip is not a cap-halt, so the flag still completes).
3. **Read it.** Click **Briefings** in the Omniscio sidebar. The left pane lists every briefing newest-first — daily digests AND weekly summaries appear in the same list, distinguished by a header pill on each row. Unread rows carry the same small **amber** dot used elsewhere for needs-you signals. Clicking opens the viewer: a stats card at the top (sessions total / active, agent vs. operator message counts, top projects with session counts, top features with usage counts, weekly AI **usage** (a nominal, pay-as-you-go value — see _AI usage is a nominal value_ below), and total tokens for the week — shown as the combined input+output count with an "in / out" breakdown; every stat-card figure renders in the app's compact form, e.g. `25.4K` messages · `$237.6K` spend · `62.2B` tokens, matching the Statistics dashboard), the AI-written **scannable recap** in the middle (a bold headline + highlight bullets, not dense paragraphs), then the suggestion cards at the bottom. (This dedicated Briefings **sidebar** viewer shows the full recap + suggestions; the **inbox** splits the same content into the two cards described in §4.)
4. **Inbox cards (TWO, since 2026-07-20).** The current week surfaces as **two independent rows** in the unified Inbox under the **Briefings** section (the same section Daily Digest rows appear under): a **recap card** (`weekly-summary` integration — prose + stats, no suggestions) and a separate **suggestions card** (`weekly-suggestions` integration — titled "N suggestions from last week"). The split exists so the AI's suggestions get their own labelled, unmissable row instead of being buried at the bottom of a paragraph-heavy recap. The two are independent: dealing with one never removes the other. Click either row (or press Enter) to open its pane; right-click for the same context menu (**Archive**, **Snooze**, **Unsnooze**), or press **S** while the row is active to open the SnoozePalette. The suggestions card always reflects the **latest week only** — it never reaches back to older summaries, so dismissing it leaves nothing older to pop up in its place (fixing the 2026-07-20 backlog "whack-a-mole") — and **self-clears** when every suggestion has been dismissed (open count → 0). Both cards derive from the SAME weekly-summary row/store — no new store, no migration. Architecture + invariants: [weekly-suggestions-card-contract.md](/.claude/memory/contracts/weekly-suggestions-card-contract.md).
5. **Generate or archive manually.** The **Run now** button at the bottom of Settings → Daily digest → Weekly Summary forces a recap for the most-recently-completed week (useful if you just changed sources, want to re-run after an error, or skipped a Monday). To archive a summary you've finished reading, use middle-click on the row (desktop), right-click → **Archive**, the **E** keyboard shortcut while the row is selected, or the small **X** button shown on mobile widths only. Archived summaries move to a collapsed **Archived** section at the bottom of the Briefings sidebar; nothing is hard-deleted and a 5-second **Undo** toast restores the row if you clicked by mistake.
6. **Snooze.** Right-click → **Snooze** opens the shared SnoozePalette ("1 hour", "Until tomorrow morning", custom date/time). The row immediately moves to the **Snoozed** bucket of the Briefings sidebar, vanishes from the Inbox, and decrements the unread badge. When `Date.now() > snoozedUntil`, the row passively re-buckets back to **Active** on the next render — no notification, no badge.
7. **Suggestion cards.** Each suggestion has a short title (e.g. "Archive your idle sessions in project X"), 1–3 sentences explaining the why + how (citing the detector evidence — counts, project name), and optionally a **Build it now** button (wand icon) when there's a concrete next step the renderer can carry out: `create-automation` opens the Automation Builder pre-filled with the suggested trigger/conditions/actions; `archive-idle-sessions` resolves the idle sessions in the flagged project (freshly, at click time), confirms the real count, then bulk-archives them (undoable); `explore-feature` opens the Settings panel at the named feature. (The old `save-quick-reply` action was retired **2026-07-06** — repeated phrases now get their own always-on inbox nudge; see [quick-reply-nudge.md](quick-reply-nudge.md).) Suggestions never include raw text from your messages — the action payload is restricted to small structured keys. Each card also has a small **X** in the top-right that opens a "why are you hiding this?" picker — pick a reason (`I'm already doing this`, `Not useful`, `Doesn't fit my workflow`, `Wrong / inaccurate`, `Other`) and the card collapses to a one-line dismissed strip with an **Undo** button. Dismissal reasons feed back into the next weekly generation so the model learns to skip near-duplicates.

### Where it lives now (the 2026-05-14 merge)

Weekly Summary used to have its own sidebar entry under **WEEKLY SUMMARY** with its own Active/Snoozed/Archived buckets, its own inbox section, and its own settings home at Settings → AI Coach → Weekly Summary. On 2026-05-14 we folded all four surfaces into Daily Digest so the two cadences (daily + weekly) share one place to read, triage, and configure:

- **Sidebar entry**: gone. Use **Briefings** (the Daily Digest sidebar entry) — weekly summaries appear in the same Active/Snoozed/Archived buckets as daily digests, sorted by date.
- **Inbox section**: gone. The **Briefings** inbox section now carries both cadences. Each row's header pill identifies which kind it is.
- **Settings home**: moved. Was Settings → AI Coach → Weekly Summary; now Settings → Email & Summaries → Daily digest → **Weekly Summary** (the sub-section at the bottom). The legacy `weekly-summary` SettingsSection key is preserved as an alias in `LEGACY_FEATURE_SECTIONS` that redirects directly to `email` (the Email & Summaries panel where Daily Digest now lives), so older deep links (e.g. from a saved bookmark) still land on the right panel. The redirect goes straight to `email` — NOT via `daily-digest` — because `LEGACY_FEATURE_SECTIONS` is a single-hop lookup, not a chain; a `weekly-summary → daily-digest → email` indirection would land users on a blank screen.
- **Virtual project row**: retired. Migration v179 soft-deletes the `__weekly_summary__` row in `projects` — the sidebar entry stops rendering. If you'd customized the entry's pin or color, the row stays in the DB with `is_deleted = 1` so it's recoverable on request.

The **service**, the **DB tables**, the **IPC handlers**, and the **AI model calls** are all unchanged. Only the renderer surface relocated.

### How it works

#### The Monday-morning fire path

The service is [/src/main/services/weekly-summary-service.ts](/src/main/services/weekly-summary-service.ts). On app boot it calls `start()`, which:

1. Runs `softMigrateFromWorkflowCoachOnce()` — gated by `weeklyCoachMigrationDone`. If your previous setup had `workflowCoachEnabled: true`, the service flips `weeklySummaryEnabled: true` and copies your Workflow Coach daily cost cap (`workflowCoachDailyCostCapUsd`) onto `weeklySummaryDailyCostCapUsd`. Since default-on shipped it **never writes `weeklySummaryEnabled: false`** — a coach that was off just leaves the on-by-default value alone (clobbering it would opt a new user out). The migration only fires once.
2. Runs `forceEnableWeeklySummaryOnce()` — gated by `weeklySummaryDefaultOnMigrationDone`. Default-on (2026-07-27) can't reach existing users through the schema default because their config already holds an explicit `weeklySummaryEnabled: false`, so this flips it `true` once and marks itself done (a harmless no-op write on a new install). Runs BEFORE the enable-gate so a freshly force-enabled user boots straight into registration + backfill.
3. Gates on `weeklySummaryEnabled`. Off → returns immediately (no interval, no registration).
4. Registers the service with the service registry (`pausable: true`) so the global Pause/Resume controls apply.
5. Fires an IIFE that sequences `backfillRecentWeeks()` → `catchUp()`. Fire-and-forget; failures are logged but never propagate from `start()`.
6. Sets a 15-minute `setInterval` running `periodicCheck()` — which compares the current local time against `weeklySummaryScheduleHour` and, if the just-completed week's summary hasn't been generated yet, calls `generate()`.

#### Load-aware deferral (don't gather during a box storm)

The three **automatic** entry points — `periodicCheck()` (the 15-min tick), `catchUp()`, and `backfillRecentWeeks()` — check the shared whole-box load signal `isBoxUnderHeavyLoad()` (CPU ≥ 85% **or** disk hard-fault pressure, from [/src/main/process/cpu-load-sampler.ts](/src/main/process/cpu-load-sampler.ts)) **before** launching the heavy gather, and **defer** when the box is under heavy load. The gather spawns a short-lived DB host that scans the multi-GB cold archive plus 12 detectors, so during a whole-box storm it would otherwise (a) lose the off-thread reader's 90 s per-RPC deadline (`"The database is taking too long to respond"`) and (b) add archive-paging fuel to the storm. Deferring is a clean skip — the natural retry (the next 15-min tick, or the next boot for catch-up/backfill) picks it up on a calm tick, and `backfillRecentWeeks()` returns **before** its completion-flag `finally`, so a deferred backfill retries next boot instead of being wrongly marked done. This mirrors how `holdForCalmDispatchWindow` (cron) and `waitWhileBoxHeavyForArchiveCopy` (backups) defer the same class of heavy scheduled work. The **manual Run now** button (`generate()` via IPC) is intentionally exempt — a user-initiated action always runs.

Because a box-load timeout is transient infra (not an AI failure), a gather failure while `isBoxUnderHeavyLoad()` is true is **not** counted toward the give-up streak (below). **Neither is a credential or billing failure** (2026-09-08): a rejected API key, an exhausted monthly AI allowance, no key left to fall back to, or a dry credit balance are things only *you* can fix, so they must not accumulate into a "the AI pipeline keeps failing" alarm that points nowhere — the shared `isCredentialOrBillingFailure` predicate excludes them, the same one the daily digest routes on ([daily-digest-credential-contract.md](/.claude/memory/contracts/daily-digest-credential-contract.md) I7). This mattered in practice: the streak counter on the owner's install had reached **62** on exactly those errors. So the "Couldn't build your weekly summary" alert fires only for a genuine AI-pipeline failure (provider outage / parse error), never a passing box storm and never a credential problem.

#### Generating a single week (Map → Reduce → Verify)

`generate(weekStartIso?)` is the canonical path. With no argument it picks the **just-completed** week (Mon→Sun, last full ISO week). It short-circuits in four idempotency layers:

1. `weeklySummaryEnabled` off → `null`.
2. Service paused (via the Pause/Resume controls) → `null`.
3. `hasWeeklySummaryForWeek(weekStartIso)` already true → returns the existing row (no API call).
4. Same `weekStartIso` already `inFlight` (in-process Set) → `null`. Guards against a second tick firing while the first is still mid-generation.

If none short-circuit, the daily cap pre-flight runs: `getTodayCostByLabel('weekly-summary')` ≥ `weeklySummaryDailyCostCapUsd` → log + return `null`. Otherwise the week is added to `inFlight` and `doGenerate(bounds)` proceeds:

1. **Gather stats.** [`gatherWeekRawStats(weekStartDate, weekEndDate)`](/src/main/services/weekly-summary-service.ts) reads `sessions`, `conversation_messages`, `feature_events`, and `api_cost_log` to produce a `RawStats` object — sessions total / active counts, agent vs. operator message counts, top **5** projects by session count, top **8** features by usage count, weekly AI spend in USD, and total tokens (`SUM(input_tokens)` / `SUM(output_tokens)` over the **same** session set as the spend, so cost and tokens always agree). Also gathers the **prior week's** raw stats so the envelope can carry signed week-over-week deltas (`deltaSessions`, `deltaMessages`, `deltaAiCostUsd`, `deltaTokens`). The token fields surface on `WeeklySummaryStats` as optional `totalInputTokens` / `totalOutputTokens` / `deltaTokens` — optional so summaries stored before this shipped still parse and the renderer hides the tile when they are absent (same pattern as the `commits` tally).
2. **No-activity skip.** If both `sessionsTotal === 0` and `messagesAgent === 0`, the function returns `null` without calling any LLM (a "you didn't use the app this week" suggestion would be noise, and the row would still cost API credits).
3. **Run the detectors (richer envelope, detectorVersion `'4'`).** [`runAllDetectors()`](/src/main/services/workflow-coach/detectors.ts) emits an `AggregatedSignals` payload of **hashes and counts only** — never raw operator text. The single allow-listed `sampleText` carve-out is PII-scrubbed and capped at 200 chars per the workflow-coach hash module. Eleven detector fields ship: the original six (`repeatedOutgoingClusters`, `manualArchive`, `idleSessions`, `duplicateApprovals`, `featureGaps`, `featureUsage`) + `activityLandscape` (v3) + four new ones the Map → Reduce → Verify pipeline depends on: `topOperatorPhrases` (30-day phrase-frequency mining), `featureDeltas` (week-over-week usage trends with direction labels), `attentionBacklog` (error / needs-you / stalled aging buckets), `cronJobStatus` (failing-job names with `redactPII()` applied so the canary token is scrubbed).
4. **Pick an account.** AI features call Anthropic's Messages API which does NOT accept OAuth tokens. Order: active apikey account → first available apikey account → fail with `"No API key account available for AI features (login accounts cannot use the Messages API directly)"`. CLI session spawning is unaffected.
5. **Build the envelope.** A single JSON envelope `{ weekStartIso, weekEndIso, stats, detectorSignals, priorDismissals, featureCatalog }` is built **once** and reused across all three phases (Map sees it, Reduce sees it, Verify sees it). `priorDismissals` is the last **90 days** of suggestion rejections (capped at 100, newest first) projected down to `{ suggestionTitle, reason, dismissedAt }` — title + reason teach the pattern; body is intentionally omitted to keep the envelope small. `featureCatalog` (added **2026-08-31**) is the released-feature menu Reduce may recommend from — see _Feature recommendations_ below.
6. **Map (Luna / user-configured utility model, ≤2000 tokens, 45 s timeout).** First LLM call. Asks the model to extract **8–15 factual observation bullets** from the envelope — no advice, no interpretation. Each bullet must cite the specific envelope field it came from in parentheses (e.g. `"(topOperatorPhrases[0])"`), quote numbers verbatim, and skip empty/null signals. Output is plain text, not JSON; the parser strips `"- "` markers and caps at 20 bullets. This step exists so Reduce has a pre-digested factual checklist instead of having to re-read the whole envelope.
7. **Reduce (Opus 4.7, ≤4000 tokens, 120 s timeout).** Second LLM call. Receives the envelope **plus** the Map bullets and produces the final JSON `{ summaryMd, suggestions[] }`. Each suggestion MUST include a `groundednessCheck: { signalsUsed[], claimsInBody[] }` self-citation — `signalsUsed` lists dot-paths into the envelope the suggestion depends on; `claimsInBody` breaks every numeric/named claim out as a separate string for Verify to fact-check. The Reduce system prompt also folds in the dismissal-feedback rules: if `priorDismissals` shows a near-duplicate suggestion was rejected as `already-doing` / `not-useful` / `not-relevant` / `wrong`, Reduce either skips it or reframes with materially-stronger NEW evidence (full reason-code semantics are spelled out in the prompt). Code fences are stripped from the response before `JSON.parse`. On parse failure the row still lands with `summaryMd = rawText, suggestions = []` (logged warn) so a malformed Opus response never silently swallows a week.
8. **Verify (Luna / user-configured utility model, ≤1500 tokens, 45 s timeout).** Third LLM call. Receives the envelope + the Reduce JSON and fact-checks each suggestion's `claimsInBody` against the envelope. Returns `{ ok, issues: [{ suggestionIndex, reason }] }`. Defense-in-depth, never a hard blocker: a parse failure / shape mismatch is treated as `{ ok: true, issues: [] }`. `applyVerifyIssues()` drops any suggestion whose index appears in `issues[]`; the `summaryMd` is unchanged (Verify only judges suggestion-level fabrications). Flagged drops are logged with `kept N/M` so you can see Verify intervention in `main.log`.
9. **Track cost (per phase).** Every `messages.create` is followed by `trackApiCost(accountId, 'weekly-summary', model, input_tokens, output_tokens)` so the dashboard total matches the Anthropic console. The label `'weekly-summary'` is registered in `OTHER_AI_SOURCE_LABELS` so it appears in the Cost tab filters. A per-phase `ModelChainEntry { phase, model, inputTokens, outputTokens, costUsd }` is also accumulated for the row's `modelChain` column (lets you split a single week's spend into its Map / Reduce / Verify components in postmortems).
10. **Insert.** `insertWeeklySummary({ weekStartIso, weekEndIso, stats, summaryMd, suggestions, detectorSignals, inputTokens, outputTokens, costUsd, modelChain })` writes the row. `week_start_iso` is `UNIQUE` so a parallel insert (e.g. backfill + periodicCheck racing on the same week) is caught at the DB level — the second insert fails, but the first row stands. Row-level `inputTokens` / `outputTokens` / `costUsd` are the sum of the three `modelChain` entries.
11. **Emit push.** `emitPush(IPC.WEEKLY_SUMMARY_GENERATED, { summary: stripFullPayload(inserted) })` (lean list-entry only, full stats/suggestions/detectorSignals fetched on demand via `WEEKLY_SUMMARY_GET`) and `IPC.WEEKLY_SUMMARY_UNREAD_CHANGED`. Renderer's `useWeeklySummaryPushEvents` hook updates the Briefings sidebar / inbox / unread badge live — both daily and weekly use the same merged unread count.

#### Why three steps (vs. one Haiku call)

Up through the Workflow Coach era the suggestions came from a single Haiku call per detector type — eight short-prompt calls that often produced surface-level "save a quick reply" / "make an automation" output regardless of whether the underlying signal was meaningful. P5 retired those 8 per-kind prompts in favor of the single Map → Reduce → Verify pipeline because:

- **Opus 4.7's writing is materially better** at synthesizing across detector signals (citing the project name and exact counts in the body, not just the title). Per-suggestion cost is higher but call count is fixed at 3 per week, so the line item stays under $0.10/day even on backfill.
- **Cross-signal correlation needs the whole envelope at once.** "You sent 'please continue' 23 times AND your top project is X" is a better suggestion than either phrase frequency or top-projects alone could produce. The per-kind shape couldn't see across signals.
- **Verify catches fabrication that single-pass prompts can't self-detect.** When Opus invents a project name or rounds a count, the Verify pass — looking at the envelope and the JSON side-by-side — flags it. The flagged suggestion is dropped; the rest of the week ships. Without Verify, a single fabricated number in week N would erode trust in week N+1's whole list.

#### Dismissal memory + the why-picker

Each suggestion card has a small **X** in the top-right that opens a five-button "why are you hiding this?" picker (`'already-doing' | 'not-useful' | 'not-relevant' | 'wrong' | 'other'`). The chosen reason is recorded in `weekly_summary_dismissals` (one row per `(weekly_summary_id, suggestion_index)` — composite UNIQUE so re-picking last-write-wins). The card collapses to a one-line "Dismissed: \<title\> — Reason: \<label\>" strip with an **Undo** button that hard-deletes the dismissal row (no soft delete). Dismissals are populated on `WEEKLY_SUMMARY_GET` via the `dismissals?: WeeklySummaryDismissal[]` slice on `WeeklySummary`.

The same store of dismissals is read back by `buildPriorDismissals()` (last 90 days, cap 100, newest first) and folded into every future Reduce call's envelope as `priorDismissals: Array<{ suggestionTitle, reason, dismissedAt }>`. The Reduce system prompt's "learn from past rejections" block then steers Opus around near-duplicate topics — reason codes carry stable meanings (see the type comment in `shared/types.ts`):

- `already-doing` → skip near-duplicates (user already has it covered)
- `not-useful` → avoid the same category
- `not-relevant` → only re-raise if THIS week's evidence is materially stronger
- `wrong` → treat related topics with extra rigor on `groundednessCheck`
- `other` → treat as a soft `not-useful`

If the dismissal read fails for any reason (`getRecentWeeklySummaryDismissals` throws), the envelope still ships with `priorDismissals: []` — dismissal memory degrades gracefully, never blocks a generation.

IPC: `IPC.WEEKLY_SUMMARY_DISMISS_SUGGESTION { weeklySummaryId, suggestionIndex, suggestionTitle, suggestionBody, reason }` and `IPC.WEEKLY_SUMMARY_UNDISMISS_SUGGESTION { weeklySummaryId, suggestionIndex }`. Both push `WEEKLY_SUMMARY_UPDATED` so other open viewers refresh.

## For agents

### Settings field map

| Setting key                      | Default | Range         | Notes                                                                     |
| -------------------------------- | ------- | ------------- | ------------------------------------------------------------------------- |
| `weeklySummaryEnabled`                | `true`  | bool          | Master toggle — **on by default** (owner decision 2026-07-27)              |
| `weeklySummaryScheduleHour`           | `7`     | `0`–`23`      | Local-time hour on Monday                                                 |
| `weeklySummaryDailyCostCapUsd`        | `0.1`   | `0.05`–`5.00` | Cumulative cap per UTC day                                                |
| `weeklySummaryBackfillCompleted`      | `false` | bool          | Internal — flips after first backfill attempt; NOT in renderer Zod schema |
| `weeklyCoachMigrationDone`            | `false` | bool          | Internal — flips after one-time Workflow Coach migration                  |
| `weeklySummaryDefaultOnMigrationDone` | `false` | bool          | Internal — flips after the one-time force-enable of existing users when default-on shipped; NOT in renderer Zod schema |
| `weeklySummaryModel`                  | Luna (Automatic) | model id | Per-feature utility model override — Map + Verify phases only; Luna sentinel = inherit global / auto-DeepSeek / Luna. See [utility-ai-model.md](utility-ai-model.md). |

## Related

This page continues in [Weekly Summary (part 2)](weekly-summary-part-2.md), which carries the rest of the behaviour — what the recap may recommend, the buttons a suggestion can carry, the first-launch backfill and its freshness gate, the nominal AI usage figure, the phrase exclusions, the commit tally, the cost cap and the Workflow Coach retirement — plus the stored tables, settings keys and renderer surfaces behind all of it.

- [daily-digest.md](daily-digest.md) — daily sibling. Same generation shape, same inbox card, **same sidebar entry (Briefings) as of 2026-05-14**, same Active/Snoozed/Archived buckets, same triage hotkeys.
- [workflow-coach.md](workflow-coach.md) — retired; redirects here.
- [ai-providers.md](ai-providers.md) — Weekly Summary Map + Verify run on Luna (the cheap/utility model) by default, overridable via `weeklySummaryModel`; Reduce runs on Opus 4.7. Falls back through apikey accounts when active account is OAuth.
- [inbox-overview.md](inbox-overview.md) — Weekly Summary row appears under **Briefings** (the merged Daily Digest section); J/K nav and the 6-slice mutex.
