* 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>
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 |
|
|
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
-
Hot memory pulse (v0.32). Before composing anything else, run:
gbrain recall --since-last-run --supersessions --pending --rollup --jsonFold the result into the briefing under a "Brain pulse" section at the top:
- Contradictions resolved overnight — the
--supersessionsoutput. Lead with these because they're new corrections to your model of the world. - Top mentions —
top_entitiesfrom--rollup(top 5 entity slugs by fact count in the window). - New facts since last briefing — group the
factsarray under each entity from the rollup; includekind,notability, andconfidence. - Pending consolidation footer — when
pending_consolidation_count > 0, noteN facts await dream-cycle consolidationso the operator can decide whether to rungbrain dreambefore reading further.
The
--since-last-runflag advances~/.gbrain/recall-cursors/<source>.jsonso the next briefing picks up exactly where this one left off. If you're running this as a cron job, pass--source <slug>or setGBRAIN_SOURCEexplicitly — 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. - Contradictions resolved overnight — the
-
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
-
Active deals. List deal pages in gbrain filtered to active status:
- Deadlines approaching in the next 7 days
- Recent timeline entries (last 7 days)
-
Time-sensitive threads. Open items from timeline entries:
- Items with deadlines in the next 48 hours
- Follow-ups that are overdue
-
Recent changes. Pages updated in the last 24 hours:
- What changed and why (read timeline entries from gbrain)
-
People in play. List person pages in gbrain sorted by recency:
- Updated in last 7 days
- Have high activity (many recent timeline entries)
-
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 pagegbrain 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 snapshotgbrain query "meetings this week"-- recent meeting pages with insightsgbrain query "pending commitments follow-ups"-- open threads and action itemsgbrain 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)