* 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>
5.2 KiB
5.2 KiB
GBrain Skill Resolver
This is the dispatcher. Skills are the implementation. Read the skill file before acting. If two skills could match, read both. They are designed to chain (e.g., ingest then enrich for each entity).
Always-on (every message)
| Trigger | Skill |
|---|---|
| Every inbound message (spawn parallel, don't block) | skills/signal-detector/SKILL.md |
| Any brain read/write/lookup/citation | skills/brain-ops/SKILL.md |
Brain operations
| Trigger | Skill |
|---|---|
| "What do we know about", "tell me about", "search for" | skills/query/SKILL.md |
| "Who knows who", "relationship between", "connections", "graph query" | skills/query/SKILL.md (use graph-query) |
| Creating/enriching a person or company page | skills/enrich/SKILL.md |
| Where does a new file go? Filing rules | skills/repo-architecture/SKILL.md |
| Fix broken citations in brain pages | skills/citation-fixer/SKILL.md |
| "Research", "track", "extract from email", "investor updates", "donations" | skills/data-research/SKILL.md |
| Share a brain page as a link | skills/publish/SKILL.md |
Content & media ingestion
| Trigger | Skill |
|---|---|
| User shares a link, article, tweet, or idea | skills/idea-ingest/SKILL.md |
| Video, audio, PDF, book, YouTube, screenshot | skills/media-ingest/SKILL.md |
| Meeting transcript received | skills/meeting-ingestion/SKILL.md |
| Generic "ingest this" (auto-routes to above) | skills/ingest/SKILL.md |
Thinking skills (from GStack)
| Trigger | Skill |
|---|---|
| "Brainstorm", "I have an idea", "office hours" | GStack: office-hours |
| "Review this plan", "CEO review", "poke holes" | GStack: ceo-review |
| "Debug", "fix", "broken", "investigate" | GStack: investigate |
| "Retro", "what shipped", "retrospective" | GStack: retro |
These skills come from GStack. If GStack is installed, the agent reads them directly. If not, brain-only mode still works (brain skills function without thinking skills).
Operational
| Trigger | Skill |
|---|---|
| Task add/remove/complete/defer/review | skills/daily-task-manager/SKILL.md |
| Morning prep, meeting context, day planning | skills/daily-task-prep/SKILL.md |
| Daily briefing, "what's happening today" | skills/briefing/SKILL.md |
| Cron scheduling, quiet hours, job staggering | skills/cron-scheduler/SKILL.md |
| Save or load reports | skills/reports/SKILL.md |
| "Create a skill", "improve this skill" | skills/skill-creator/SKILL.md |
| "Skillify this", "is this a skill?", "make this proper" | skills/skillify/SKILL.md |
| "Is gbrain healthy?", morning health check, skillpack-check | skills/skillpack-check/SKILL.md |
| Post-restart health + auto-fix, "did the container restart break anything", smoke test | skills/smoke-test/SKILL.md |
| Cross-modal review, second opinion | skills/cross-modal-review/SKILL.md |
| "Validate skills", skill health check | skills/testing/SKILL.md |
| Webhook setup, external event processing | skills/webhook-transforms/SKILL.md |
| "Spawn agent", "background task", "parallel tasks", "steer agent", "pause/resume agent", "gbrain jobs submit", "submit a gbrain job", "submit a shell job", "shell job" | skills/minion-orchestrator/SKILL.md |
Setup & migration
| Trigger | Skill |
|---|---|
| "Set up GBrain", first boot | skills/setup/SKILL.md |
| "Migrate from Obsidian/Notion/Logseq" | skills/migrate/SKILL.md |
| Brain health check, maintenance run | skills/maintain/SKILL.md |
| "Extract links", "build link graph", "populate timeline" | skills/maintain/SKILL.md (extraction sections) |
| "Brain health", "what features am I missing", "brain score" | Run gbrain features --json |
| "Set up autopilot", "run brain maintenance", "keep brain updated" | Run gbrain autopilot --install --repo ~/brain |
| Agent identity, "who am I", customize agent | skills/soul-audit/SKILL.md |
| "Populate links", "extract links", "backfill graph" | skills/maintain/SKILL.md (graph population phase) |
| "Populate timeline", "extract timeline entries" | skills/maintain/SKILL.md (graph population phase) |
Identity & access (always-on)
| Trigger | Skill |
|---|---|
| Non-owner sends a message | Check ACCESS_POLICY.md before responding |
| Agent needs to know its identity/vibe | Read SOUL.md |
| Agent needs user context | Read USER.md |
| Operational cadence (what to check and when) | Read HEARTBEAT.md |
Disambiguation rules
When multiple skills could match:
- Prefer the most specific skill (meeting-ingestion over ingest)
- If the user mentions a URL, route by content type (link → idea-ingest, video → media-ingest)
- If the user mentions a person/company, check if enrich or query fits better
- Chaining is explicit in each skill's Phases section
- When in doubt, ask the user
Conventions (cross-cutting)
These apply to ALL brain-writing skills:
skills/conventions/quality.md— citations, back-links, notability gateskills/conventions/brain-first.md— check brain before external APIsskills/conventions/subagent-routing.md— when to use Minions vs inline workskills/_brain-filing-rules.md— where files goskills/_output-rules.md— output quality standards