Files
gbrain/skills/maintain/SKILL.md
T
11abb24ddd v0.20.4 feat: merge gbrain-jobs into minion-orchestrator — single unified minions skill (#381)
* feat: merge gbrain-jobs into minion-orchestrator — single unified minions skill

* fix(skill/minion-orchestrator): correct MCP boundary, real handler names, PGLite path

The initial merge commit a51c737 documented `submit_job name="shell"` as
agent-callable, but src/core/operations.ts:1106 rejects protected names
from MCP callers (shell is in src/core/minions/protected-names.ts:16) —
shell-job submission is CLI-only. Subagent examples referenced non-existent
handler names (`research`, `orchestrate`) instead of the real `subagent` /
`subagent_aggregator` handlers. PGLite section wrongly told users to
migrate to Supabase when `gbrain jobs submit ... --follow` inline mode
works per docs/guides/minions-shell-jobs.md:15. Contract section canonized
"every task through Minions" against the `pain_triggered` default in
skills/conventions/subagent-routing.md:16,27.

Rewrite addresses all four:
- Shell Jobs section is explicit about CLI-only submission; agents observe
  via get_job / list_jobs / get_job_progress (non-protected).
- Subagent examples route through `gbrain agent run` (user-facing CLI)
  with raw handler names documented as the power-user path.
- PGLite gets --follow inline execution, not migration friction.
- Contract softened to point at subagent-routing.md convention.

Also adds a Preconditions block for Shell Jobs (env gate, RCE warning,
execution-mode choice, verification command), narrows the frontmatter
"gbrain jobs" trigger to "gbrain jobs submit" + "submit a gbrain job"
(bare was too broad — CLI namespace covers 9 subcommands), inlines a
"replaces older gbrain-jobs routing intent" note in the description, and
removes non-existent `get_job_stats` from the tools list (CLI is
`gbrain jobs stats`; no MCP equivalent).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(resolver): narrow "gbrain jobs" trigger to specific intents

Replace bare "gbrain jobs" in the routing table with "gbrain jobs submit"
+ "submit a gbrain job". The bare phrase was too broad — the CLI namespace
covers 9 subcommands (submit, list, get, retry, delete, prune, stats,
smoke, work). Users asking about stats/prune/retry now fall through to
`gbrain --help` instead of getting misrouted to minion-orchestrator, which
only documents shell execution and subagent orchestration.

Matches the frontmatter trigger narrow in minion-orchestrator/SKILL.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(resolver): add round-trip + skill-example-name validator

Two new assertion blocks in test/resolver.test.ts:

1. RESOLVER.md trigger round-trip: every quoted phrase in a routing-table
   row has a fuzzy match in the target skill's frontmatter `triggers:` list.
   Catches RESOLVER ↔ frontmatter drift that checkResolvable's reachability
   check doesn't. Fuzzy match is case-insensitive, trailing-punctuation-
   insensitive, and splits on "/" for compound phrases like
   "pause/resume agent" — accommodates RESOLVER.md's natural-language
   summary style without allowing real drift through.

2. Skill example-name validator: every `name="<word>"` reference in any
   SKILL.md body must resolve to either a declared operation in
   src/core/operations.ts or a known Minions handler in
   PROTECTED_JOB_NAMES. Would have caught the `name="research"` /
   `name="orchestrate"` drift that slipped through the first review
   — nothing in CI caught those handler names referencing non-existent
   handlers until a Codex cold-read found them. This test closes that
   class of regression gap.

51 / 51 tests pass locally. Full E2E suite (bun run test:e2e) still
passes 197 / 197 across 19 files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(e2e): PGLite shell-job --follow inline path

Closes the T4 coverage gap surfaced during PR #381 eng review. The sibling
test/e2e/minions-shell.test.ts covers Postgres + persistent-daemon; this
file covers the PGLite + --follow path the minion-orchestrator skill now
documents.

Two assertions:

1. submit → registerBuiltinHandlers → worker.start → shell runs → completes
   with exit_code 0 and stdout_tail "hello\n". Exercises the exact dispatch
   path src/commands/jobs.ts:207 takes when --follow is set, including the
   GBRAIN_ALLOW_SHELL_JOBS=1 gate.

2. With GBRAIN_ALLOW_SHELL_JOBS unset, registerBuiltinHandlers leaves the
   shell handler unregistered. Confirms the env gate from
   src/commands/jobs.ts:611 works.

Runs in-memory against PGLiteEngine — no DATABASE_URL, no Docker, runs in
CI unconditionally. Completes in ~1.2s.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: pre-landing review fixes

Pre-landing review caught 4 doc bugs + 2 test fragilities + 2 pre-existing
drift cases. All auto-fix category (clear correct answer, single obvious fix).

minion-orchestrator/SKILL.md:
- Shell submit examples used nonexistent `--cmd`/`--argv`/`--cwd` flags. Real
  CLI takes `--params '{"cmd":"...","cwd":"..."}'` (src/commands/jobs.ts:55-85).
  Examples now match `gbrain jobs submit --help` output.
- `--tools "search,web_search"` referenced `web_search` which isn't in
  BRAIN_TOOL_ALLOWLIST (src/core/minions/tools/brain-allowlist.ts:47-59).
  Swapped to `search,query`. Added a full allowlist enumeration so
  readers don't have to grep.
- `gbrain agent run` flags section listed `--queue`, `--priority`,
  `--max-attempts`, `--delay` — none of these exist on that command
  (src/commands/agent.ts:105-129). Replaced with the real flag set
  (`--subagent-def`, `--model`, `--max-turns`, `--tools`, `--timeout-ms`,
  `--fanout-manifest`, `--follow`, `--no-follow`, `--detach`) and a note
  about using `gbrain jobs submit` for queue tuning.
- MCP boundary claim "returns permission_denied" was imprecise. Reworded:
  throws an OperationError with code permission_denied.

test/resolver.test.ts:
- D5/C row regex required the backtick-quoted skill path to be followed
  immediately by `|`, silently skipping rows with trailing parentheticals
  (e.g., `` `skills/maintain/SKILL.md` (extraction sections) |``). Broadened
  to `[^|]*\|` so every row gets audited.

test/e2e/minions-shell-pglite.test.ts:
- Shared engine across both tests with no per-test reset. Future test
  additions would hit order-dependency. Added beforeEach TRUNCATE on
  minion_jobs / minion_inbox / minion_attachments, matching the Postgres
  sibling at test/e2e/minions-shell.test.ts:55-58.

skills/query/SKILL.md:
- Added 4 triggers RESOLVER.md routes to this skill but the frontmatter
  never declared: "who knows who", "relationship between", "connections",
  "graph query". Pre-existing drift — the broadened D5/C regex surfaced it.

skills/maintain/SKILL.md:
- Added 6 triggers with the same pre-existing drift: "extract links",
  "build link graph", "populate timeline", "populate links", "backfill graph",
  "extract timeline entries".

57/57 tests pass on the fixed tree.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: second-pass review fixes — stale CLI flag + handler name

Two more stale references caught by specialist re-dispatch on the fixed tree:

skills/minion-orchestrator/SKILL.md:72 — Routing table row described shell
  jobs as taking `--cmd` or `--argv` as CLI flags. Same class of bug as M1
  from the prior fix commit but in a different location. Now says `--params`
  with `cmd` or `argv`, matching the corrected submit examples (lines 112-120).

skills/conventions/subagent-routing.md:82 — "Check `get_job_stats`
  queue_health.active" referenced an MCP operation that doesn't exist in
  src/core/operations.ts. The new minion-orchestrator skill cross-references
  this convention file, so agents following the routing pointer would hit a
  non-existent op. Replaced with the real ops: `list_jobs --status active`
  (MCP) or `gbrain jobs stats` (CLI).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: adversarial pass cleanups — manifest.json + anti-pattern scope

Claude adversarial subagent caught two last consistency gaps:

skills/manifest.json:135 — Skill description still read "Manage background
  agents via Minions job queue" (subagent-only framing), out of sync with
  the reframed SKILL.md frontmatter. Manifest is what the skill registry
  indexes; leaving this stale meant shell-job-intent routers would miss it.
  Updated to match the unified wording.

skills/minion-orchestrator/SKILL.md:288 — Anti-pattern line "Don't use
  sessions_spawn with runtime: subagent when Minions is available" was
  subagent-lane-specific inside the now-consolidated skill, reading like
  the one rule in the skill but only addressing one lane. Scoped to
  "For subagent work" and pointed at `gbrain agent run` so the rule
  doesn't confuse shell-job readers.

Two investigate-class items deferred to follow-up:
- D13 regex could false-positive on future skills with unrelated `name="..."`
  usage. Today clean; scope to backtick-fenced snippets if it bites.
- PGLite E2E env-var race if bun:test ever goes file-parallel. Today isolated
  per file; add helper + comment when needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

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

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: update README + CLAUDE.md for v0.19.2 Minions consolidation

- Skill count 28 -> 29 across README and CLAUDE.md (adds smoke-test from
  v0.19.1 to the Skills section, closes a prior drift).
- README minion-orchestrator row rewritten to name both lanes (shell jobs
  via `gbrain jobs submit shell`, LLM subagents via `gbrain agent run`)
  so the surface matches the consolidated skill file.
- README Operational table gains a smoke-test row.
- CLAUDE.md key-files entry for minion-orchestrator now describes the
  v0.19.2 consolidation, trust boundary (MCP permission_denied on
  protected names), and the narrowed trigger set.
- CLAUDE.md Skills section notes the consolidation and the new v0.19.1
  smoke-test skill.
- CLAUDE.md test inventory picks up `test/e2e/minions-shell-pglite.test.ts`
  and the v0.19.2 round-trip + name-validator additions in
  `test/resolver.test.ts`.

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

* fix(ci): update PGLite test for new env-gate behavior + regenerate llms-full.txt

CI caught two issues:

1. `test/e2e/minions-shell-pglite.test.ts` — the "GBRAIN_ALLOW_SHELL_JOBS
   unset → shell handler not registered" test was written against pre-v0.20.3
   `registerBuiltinHandlers` behavior (env gate at registration time). Master's
   queue-resilience merge moved the gate from registration to execution:
   shell handler is now always registered so claimed jobs emit a clear rejection
   log, and `shellHandler` itself throws UnrecoverableError when
   GBRAIN_ALLOW_SHELL_JOBS != '1' (see src/core/minions/handlers/shell.ts:210).
   Updated the test to invoke shellHandler directly with a minimal ctx and
   assert the throw. Preserves the test's intent (prove the guard works) under
   the new control flow.

2. `llms-full.txt` drift — README.md + CLAUDE.md updates in v0.19.2 and v0.20.4
   updated the skill count to 29 and rewrote the minion-orchestrator
   description, but the committed `llms-full.txt` bundle still reflected the
   pre-consolidation content. Regenerated via `bun run build:llms`.

The third CI failure (`planInstall + applyInstall D-CX-11`) passes cleanly
locally (26/26 in test/skillpack-install.test.ts). The 1ms runtime in CI
suggests a filesystem-mtime flake, not a real regression from this branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(skillpack): treat future-mtime lock as stale (CI race fix)

D-CX-11 ("--force-unlock overrides a stale lock") flaked in CI with a 1ms
runtime. Root cause: on fast CI filesystems (ext4 with high-resolution
mtimes on GitHub runners), `writeFileSync` can set a lock's mtime a few
microseconds ahead of the subsequent `Date.now()`, making `age` negative.

Old logic:
  const stale = age >= staleMs;

With `staleMs: 0` and `age = -0.3ms`: `-0.3 >= 0` is false → NOT stale →
the `!stale` branch throws `lock_held` before reaching the force-unlock
path. Test failed at the first ms, never exercised the actual unlock logic.

Fix (src/core/skillpack/installer.ts:189):
  const stale = age < 0 || age >= staleMs;

Treats negative age (future mtime) as stale. Safe: if the lock's mtime is
in the future, either the filesystem clock just jumped forward or the
lock was written by a racing process; either way it's not a live,
healthy lock and the stale path is the correct branch.

Passes locally (26/26 in test/skillpack-install.test.ts).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: root <root@localhost>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 01:39:58 -07:00

12 KiB

name, version, description, triggers, tools, mutating
name version description triggers tools mutating
maintain 1.0.0 Brain health checks: back-link enforcement, citation audit, filing validation, stale info detection, orphan pages, and benchmarks. Use when asked to check brain health, run maintenance, or audit quality.
brain health
check backlinks
citation audit
maintenance
orphan pages
stale pages
extract links
build link graph
populate timeline
populate links
backfill graph
extract timeline entries
get_health
get_page
put_page
list_pages
get_backlinks
add_link
search
true

Maintain Skill

Periodic brain health checks and cleanup.

Contract

This skill guarantees:

  • All health dimensions are checked (stale, orphan, dead links, cross-refs, backlinks, citations, filing, tags)
  • Each issue found has a specific fix action
  • Back-link iron law is enforced
  • Citation format is validated against the standard
  • Results are reported with counts per dimension

Phases

  1. Run health check. Check gbrain health to get the dashboard.
  2. Check each dimension:

Stale pages

Pages where compiled_truth is older than the latest timeline entry. The assessment hasn't been updated to reflect recent evidence.

  • Check the health output for stale page count
  • For each stale page: read the page from gbrain, review timeline, determine if compiled_truth needs rewriting

Orphan pages

Pages with zero inbound links. Nobody references them.

  • Review orphans: are they genuinely isolated or just missing links?
  • Add links in gbrain from related pages or flag for deletion

Links pointing to pages that don't exist.

  • Remove dead links in gbrain

Missing cross-references

Pages that mention entity names but don't have formal links.

  • Read compiled_truth from gbrain, extract entity mentions, create links in gbrain

If link_count is 0 or low relative to page_count, run batch extraction:

gbrain extract links --dir ~/brain

This scans all markdown files for entity references, See Also sections, and frontmatter fields, then creates typed links in the database.

Timeline extraction

If timeline_entry_count is 0, extract structured timeline from markdown:

gbrain extract timeline --dir ~/brain

Parses - **YYYY-MM-DD** | Source — Summary and ### YYYY-MM-DD — Title formats. Note: extracted entries improve structured queries (gbrain timeline), not vector search.

Autopilot check

Verify autopilot is running:

gbrain autopilot --status

If not running, install it:

gbrain autopilot --install --repo ~/brain

Autopilot runs sync, extract, and embed in a continuous loop with adaptive scheduling. In v0.11.1+, autopilot dispatches each cycle as a single autopilot-cycle Minion job and supervises the worker child — one install step gives you sync + extract + embed + backlinks + durable job processing.

Fix a half-migrated install

A v0.11.0 install where the migration skill never fired leaves Minions partially set up: schema is applied, but ~/.gbrain/preferences.json doesn't exist, autopilot runs inline, host manifests still reference agentTurn. Repair:

# Check migration status
gbrain apply-migrations --list

# Apply pending migrations (idempotent; safe on healthy installs)
gbrain apply-migrations --yes

# If host-specific handlers are flagged in ~/.gbrain/migrations/pending-host-work.jsonl:
# walk them per skills/migrations/v0.11.0.md + docs/guides/plugin-handlers.md,
# ship handler registrations in the host repo, then re-run apply-migrations.

Full troubleshooting guide: docs/guides/minions-fix.md.

Check that the back-linking iron law is being followed:

  • For each recently updated page, check if entities mentioned in it have corresponding back-links FROM those entity pages
  • A mention without a back-link is a broken brain
  • Fix: add the missing back-link to the entity's Timeline or See Also section
  • Format: - **YYYY-MM-DD** | Referenced in [page title](path) -- brief context

Filing rule violations

Check for common misfiling patterns (see skills/_brain-filing-rules.md):

  • Content with clear primary subjects filed in sources/ instead of the appropriate directory (people/, companies/, concepts/, etc.)
  • Use gbrain search to find pages in sources/ that reference specific people, companies, or concepts -- these may be misfiled
  • Flag misfiled pages for review or re-filing

Citation audit

Spot-check pages for missing [Source: ...] citations:

  • Read 5-10 recently updated pages
  • Check that compiled truth (above the line) has inline citations
  • Check that timeline entries have source attribution
  • Flag pages where facts appear without provenance

Tag consistency

Inconsistent tagging (e.g., "vc" vs "venture-capital", "ai" vs "artificial-intelligence").

  • Standardize to the most common variant using gbrain tag operations

Graph population (v0.10.3+)

The links and timeline_entries tables are the structured graph layer. Populate them periodically or after major imports:

  • gbrain extract links --source db — backfill structured links by walking pages from the engine. Reads [Name](people/slug) / [Name](companies/slug) references and infers relationship types (attended, works_at, invested_in, founded, advises, mentions, source). Idempotent. Use --source fs --dir <brain> if you have a markdown checkout to walk instead.
  • gbrain extract timeline --source db — backfill structured timeline entries. Parses - **YYYY-MM-DD** | summary lines from page content. Idempotent (DB UNIQUE constraint).
  • gbrain extract all --source db — both in one run.
  • gbrain graph-query <slug> --depth 2 — verify connectivity (use any well-known entity slug as a probe).
  • gbrain stats — verify link_count > 0 and timeline_entry_count > 0 after extraction.
  • gbrain health — review link_coverage and timeline_coverage percentages on entity pages (person/company). Below 50% means more extraction is needed.

Available link types (use with gbrain graph-query --type): attended, works_at, invested_in, founded, advises, mentions, source.

Going forward, every gbrain put call auto-creates and reconciles links via the auto-link post-hook (default on; disable: gbrain config set auto_link false). So link-extract is mostly a one-time backfill. timeline-extract should be re-run after bulk imports or content edits that add new dated entries.

Embedding freshness

Chunks without embeddings, or chunks embedded with an old model.

  • For large embedding refreshes (>1000 chunks), use nohup: nohup gbrain embed refresh > /tmp/gbrain-embed.log 2>&1 &
  • Then check progress: tail -1 /tmp/gbrain-embed.log

Security (RLS verification)

Run gbrain doctor --json and check the RLS status. All tables should show RLS enabled. If not, run gbrain init again.

Schema health

Check that the schema version is up to date. gbrain doctor --json reports the current version vs expected. If behind, gbrain init runs migrations automatically.

File storage health

Check the integrity of stored files and redirect pointers:

  • Run gbrain files verify to check all DB records have valid data
  • Run gbrain files status to see migration state (local, mirrored, redirected)
  • Check for orphan .redirect.yaml pointers that reference missing storage files
  • Check for large binary files (>= 100 MB) still in git that should be in cloud storage
  • If storage backend is configured: verify redirect pointers resolve (download test)

Open threads

Timeline items older than 30 days with unresolved action items.

  • Flag for review

Benchmark Testing

Periodically verify search quality hasn't regressed. Run a battery of test queries across difficulty tiers:

  • Tier 1 (entity lookup): known names -- should always resolve
  • Tier 2 (topic recall): concepts, topics -- keyword search should handle
  • Tier 3 (semantic): queries with no exact keyword match -- needs embeddings
  • Tier 4 (cross-domain): relational/connection queries -- only semantic handles

Compare results from gbrain search (keyword) vs gbrain query (hybrid). Quality matters more than speed (2.5s right > 200ms wrong).

When to run benchmarks:

  • After major brain imports or re-imports
  • After gbrain version upgrades
  • After embedding regeneration
  • Monthly to track quality drift

Heartbeat Integration

For production agents running on a schedule, integrate gbrain health checks into your operational heartbeat.

On every heartbeat (hourly or per-session)

Run gbrain doctor --json and check for degradation. Report any failing checks to the user. Key signals: connection health, schema version, RLS status, embedding staleness.

Weekly maintenance

Run gbrain embed --stale to refresh embeddings for pages that have changed since their last embedding. For large brains (>5000 pages), run this with nohup:

nohup gbrain embed --stale > /tmp/gbrain-embed.log 2>&1 &

Daily verification

Verify sync is running: check gbrain stats and confirm last_sync is within the last 24 hours. If sync has stopped, the brain is drifting from the repo.

Stale compiled truth detection

Flag pages where compiled truth is >30 days old but the timeline has recent entries. This means new evidence exists that hasn't been synthesized. These pages need a compiled truth rewrite (see the maintain workflow above).

Report Storage

After maintenance runs, save a report:

  • Health check results (before/after scores for each dimension)
  • Back-link violations found and fixed
  • Filing rule violations found
  • Citation gaps flagged
  • Benchmark results (if run)
  • Outstanding issues requiring user attention

This creates an audit trail for brain health over time.

Quality Rules

  • Never delete pages without confirmation
  • Log all changes via timeline entries
  • Check gbrain health before and after to show improvement

Anti-Patterns

  • Fixing pages without reading them first -- you must understand context before editing
  • Silently skipping dimensions -- every dimension must be checked and reported, even if clean
  • Deleting orphan pages without checking if they should be linked instead
  • Running embedding refresh during peak usage hours
  • Batch-fixing back-links without verifying the relationship is real
  • Marking a dimension "clean" without actually querying it
  • Rewriting compiled truth without reading the full timeline first
  • Removing tags without checking if other pages use the same tag consistently

Output Format

The maintenance report follows this structure:

## Brain Health Report — YYYY-MM-DD

| Dimension           | Issues Found | Fixed | Remaining |
|----------------------|-------------|-------|-----------|
| Stale pages          | N           | N     | N         |
| Orphan pages         | N           | N     | N         |
| Dead links           | N           | N     | N         |
| Missing cross-refs   | N           | N     | N         |
| Back-link violations | N           | N     | N         |
| Citation gaps        | N           | N     | N         |
| Filing violations    | N           | N     | N         |
| Tag inconsistencies  | N           | N     | N         |
| Embedding staleness  | N           | N     | N         |
| Security (RLS)       | N           | N     | N         |
| Schema health        | N           | N     | N         |
| File storage         | N           | N     | N         |
| Open threads         | N           | N     | N         |

### Details
[Per-dimension breakdown with specific pages and actions taken]

### Benchmark Results (if run)
[Tier 1-4 query results with pass/fail]

### Outstanding Issues
[Items requiring user attention or confirmation]

Tools Used

  • Check gbrain health (get_health)
  • List pages in gbrain with filters (list_pages)
  • Read a page from gbrain (get_page)
  • Check backlinks in gbrain (get_backlinks)
  • Link entities in gbrain (add_link)
  • Remove links in gbrain (remove_link)
  • Tag a page in gbrain (add_tag)
  • Remove a tag in gbrain (remove_tag)
  • View timeline in gbrain (get_timeline)