Files
gbrain/skills/briefing/SKILL.md
T
17b190e227 v0.33.0 feat: gbrain recall morning pulse + thin-client routing fix (9 commands) (#879)
* feat(engine): add countUnconsolidatedFacts to BrainEngine + both engines

New `BrainEngine.countUnconsolidatedFacts(sourceId): Promise<number>` returns
the count of active + unconsolidated facts for a source. Single SQL:
COUNT(*) WHERE source_id = $1 AND consolidated_at IS NULL AND expired_at IS NULL.

Backs the v0.33 `gbrain recall --pending` flag and the `recall` MCP op's new
`include_pending` param. Source-scoped, no index needed (existing
facts(source_id) index covers the predicate).

* feat(recall): cursor state + recall rewrite + thin-client routing + watch loop

`gbrain recall` gains four new flags backed by a new cursor-state file:

- `--since-last-run` reads ~/.gbrain/recall-cursors/<source>.json. First run
  defaults to 24h. Cursor is T_start (captured BEFORE the read SQL), not
  T_finish, so facts inserted during render don't fall in a black hole
  (Codex round 1 #2).
- `--pending` appends a "Pending consolidation: N" footer. Backed by the
  new engine method; remote round-trips through one MCP call via the
  recall op's new `include_pending` param.
- `--rollup` prepends a "Top mentions" header — top-5 entities by fact
  count over the FULL result set, not a LIMIT slice (Codex round 1 #8).
  JSON shape `top_entities: [{entity_slug, count}]` matches the existing
  pinned key at test/facts-doctor-shape.test.ts:49.
- `--watch [SECONDS]` re-runs on interval. Default 60, range [1, 3600].
  TTY: clear-and-redraw. Non-TTY: plain `--- <ts> ---` delimited blocks.
  SIGINT-only clean exit. Per-tick try/catch + exponential backoff
  `min(SECONDS × 2^(N-1), 5×SECONDS)`; exit after 5 consecutive failures
  with briefing cursor NOT advanced. Watch uses a separate cursor file
  (<source>.watch.json) so operator quitting watch doesn't clobber the
  standalone briefing cursor (Codex round 2 #8).

Thin-client routing: runRecall + runForget mirror the salience.ts:80
pattern. On `gbrain init --mcp-only` installs the local engine call is
swapped for callRemoteTool('recall' | 'forget_fact', ...). The local
canonical source resolver's assertSourceExists check is skipped on
thin-client (empty local sources table); the kebab-case SOURCE_ID_RE
syntactic gate still runs locally. Fixes pre-existing silent-empty-results
on thin-client recall — the v0.31.1 wave missed it (Codex round 2 #6).

`recall` MCP op extended with optional `include_pending` param +
`pending_consolidation_count` output field. Backward-compatible.
No new MCP op. No schema migration.

State file uses atomic write via unique per-call tmp filename
(<source>.json.tmp.<pid>.<random>) + rename(2) (Codex round 1 #7).
Read returns null on missing/corrupt/future-shifted timestamps; caller
falls back to 24h.

* feat(thin-client): route jobs list/get + REFUSE 7 host-bound commands

Continues the v0.31.1 thin-client routing wave. v0.33 audit (Codex round 2
#4) source-grounded against operations.ts + each command file:

ROUTE additions (have MCP ops, mirror salience.ts:80 pattern):
- `gbrain jobs list` → callRemoteTool('list_jobs', ...)
- `gbrain jobs get <id>` → callRemoteTool('get_job', ...)
  Other jobs subcommands (submit, cancel, retry, work, supervisor, prune,
  stats, smoke) stay host-bound — they manage local queue state.

REFUSE additions to cli.ts THIN_CLIENT_REFUSED_COMMANDS + matching hints
in THIN_CLIENT_REFUSE_HINTS:
- `pages` — purge-deleted is admin+localOnly (operations.ts:856-864)
- `files` — file_list / file_url MCP ops are localOnly:true
- `eval` — export/prune/replay touch local engine; no MCP equivalent
- `code-def` / `code-refs` / `code-callers` / `code-callees` — NO MCP ops
  exist for symbol lookup in operations.ts:2630-2671; deferred as a v0.34
  candidate to add them

Each refuse hint names the host-side path the user should use instead.
Closes the silent-wrong-brain bug class for 9 commands total (recall +
forget routing landed in the prior commit).

* test: cover v0.33 recall extensions + thin-client routing audit (45 cases)

Three new test files pinning the v0.33 behavior + critical regression
guards from both Codex review rounds:

- test/recall-extensions.test.ts (17 cases, PGLite-backed). Covers
  countUnconsolidatedFacts SQL semantics (ignores expired, ignores
  consolidated, source-scoped, returns 0 on empty), cursor state file
  round-trip + corrupt/future fallback + briefing vs watch separation
  (Codex round 2 #8 regression guard) + atomic write tmp suffix
  (Codex round 1 #7 regression guard) + non-fatal write failures.
  Uses withEnv() for GBRAIN_HOME isolation per check-test-isolation.sh R1.

- test/recall-rollup.test.ts (8 pure-function cases). CRITICAL
  regression guards for Codex round 1 #8:
    1. Top-K computed over the FULL FactRow[], not a LIMIT-100 slice
       (seeded with 150 facts to prove full-window math)
    2. JSON shape pinned to `{entity_slug, count}` matching
       test/facts-doctor-shape.test.ts:49 (the existing shape pin)
    3. null entity_slug skipped, NOT bucketed as "(no entity)"
    4. Ties broken alphabetically for stable output

- test/thin-client-routing-audit.test.ts (20 source-grounded cases).
  Pins every v0.33 REFUSE addition in THIN_CLIENT_REFUSED_COMMANDS +
  every matching hint in THIN_CLIENT_REFUSE_HINTS + every v0.31.1-era
  original (no accidental removals). Pins every ROUTE addition's
  callRemoteTool import + call site in recall.ts and jobs.ts. Catches
  the audit-table regression mode that motivated the v0.31.1 wave
  originally.

Net: 45 new test cases. All pass green against the v0.33 implementation.

* chore: bump version and changelog (v0.33.0)

v0.33.0 — agent integration: gbrain recall morning pulse + thin-client routing fix.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 23:20:17 -07:00

6.0 KiB

name, description, triggers, tools, mutating
name description triggers tools mutating
briefing Compile daily briefing with meeting context, active deals, and citation tracking
daily briefing
morning briefing
what's happening today
search
query
get_page
list_pages
get_timeline
false

Briefing Skill

Compile a daily briefing from brain context.

Filing rule: When the briefing creates or updates brain pages, follow skills/_brain-filing-rules.md.

Contract

  • Every fact in the briefing includes an inline [Source: slug, updated DATE] citation.
  • Meeting participants are resolved against the brain; gaps are explicitly flagged.
  • Active deals and action items include deadlines and recency context.
  • The briefing is read-only: no brain pages are created or modified unless the user explicitly requests it.
  • Stale alerts surface pages relevant to today's context, not just all stale pages.

Phases

  1. Hot memory pulse (v0.32). Before composing anything else, run:

    gbrain recall --since-last-run --supersessions --pending --rollup --json
    

    Fold the result into the briefing under a "Brain pulse" section at the top:

    1. Contradictions resolved overnight — the --supersessions output. Lead with these because they're new corrections to your model of the world.
    2. Top mentionstop_entities from --rollup (top 5 entity slugs by fact count in the window).
    3. New facts since last briefing — group the facts array under each entity from the rollup; include kind, notability, and confidence.
    4. Pending consolidation footer — when pending_consolidation_count > 0, note N facts await dream-cycle consolidation so the operator can decide whether to run gbrain dream before reading further.

    The --since-last-run flag advances ~/.gbrain/recall-cursors/<source>.json so the next briefing picks up exactly where this one left off. If you're running this as a cron job, pass --source <slug> or set GBRAIN_SOURCE explicitly — cron doesn't start in your repo-root cwd, so dotfile resolution may miss the right source. Thin-client installs (gbrain init --mcp-only) route through the remote brain transparently.

  2. Today's meetings. For each meeting on the calendar:

    • Search gbrain for each participant by name
    • Read their pages from gbrain for compiled_truth context
    • Summarize: who they are, recent timeline, relationship to you
  3. Active deals. List deal pages in gbrain filtered to active status:

    • Deadlines approaching in the next 7 days
    • Recent timeline entries (last 7 days)
  4. Time-sensitive threads. Open items from timeline entries:

    • Items with deadlines in the next 48 hours
    • Follow-ups that are overdue
  5. Recent changes. Pages updated in the last 24 hours:

    • What changed and why (read timeline entries from gbrain)
  6. People in play. List person pages in gbrain sorted by recency:

    • Updated in last 7 days
    • Have high activity (many recent timeline entries)
  7. Stale alerts. From gbrain health check:

    • Pages flagged as stale that are relevant to today's meetings

GBrain-Native Context Loading

Before generating any briefing, load context from gbrain systematically.

Before a meeting

For every attendee on the calendar invite:

  • gbrain search "<attendee name>" -- find their brain page
  • gbrain get <slug> -- load compiled truth, recent timeline, relationship context
  • If no page exists, note the gap ("No brain page for Sarah Chen -- consider enrichment")

Before an email reply

Before drafting or triaging any email:

  • gbrain search "<sender name>" -- load sender context
  • Read their compiled truth to understand who they are, what they care about, and your relationship history. This turns a cold reply into an informed one.

Daily briefing queries

Run these queries to populate the briefing sections:

  • gbrain query "active deals status" -- deal pipeline snapshot
  • gbrain query "meetings this week" -- recent meeting pages with insights
  • gbrain query "pending commitments follow-ups" -- open threads and action items
  • gbrain search --type person --sort updated --limit 10 -- people in play

Output Format

DAILY BRIEFING -- [date]
========================

MEETINGS TODAY
- [time] [meeting name]
  Participants: [name] (slug: people/name, [key context])

ACTIVE DEALS
- [deal name] -- [status], deadline: [date]
  Recent: [latest timeline entry]

ACTION ITEMS
- [item] -- due [date], related to [slug]

RECENT CHANGES (24h)
- [slug] -- [what changed]

PEOPLE IN PLAY
- [name] -- [why they're active]

Back-Linking During Briefing

If the briefing creates or updates any brain pages (e.g., new meeting prep pages, updated entity pages), the back-linking iron law applies: every entity mentioned must have a back-link from their page. See skills/_brain-filing-rules.md.

Citation in Briefings

When presenting facts from brain pages, include inline citations:

  • "Jane is CTO of Acme [Source: people/jane-doe, updated 2026-04-01]"
  • This lets the user trace any claim back to the brain page and assess freshness

Anti-Patterns

  • Briefing without brain queries. Never generate a briefing from memory alone; always query gbrain for current data.
  • Uncited facts. Every claim must include [Source: slug, updated DATE]. A fact without a citation is unverifiable.
  • Stale context presented as current. If a page hasn't been updated in 30+ days, flag the staleness explicitly rather than presenting it as fresh.
  • Modifying brain pages unprompted. The briefing is read-only by default. Do not create or update pages unless the user explicitly requests it.
  • Ignoring coverage gaps. When a meeting participant has no brain page, say so. Silence about gaps hides ignorance.

Tools Used

  • Search gbrain by name (query)
  • Read a page from gbrain (get_page)
  • List pages in gbrain by type (list_pages)
  • Check gbrain health (get_health)
  • View timeline entries in gbrain (get_timeline)