Conversation
- skills/maintain/SKILL.md: drop "citation audit" trigger; the focused
citation-fixer skill is the single owner. Silences the MECE overlap
warning surfaced by src/core/check-resolvable.ts.
- skills/RESOLVER.md: add citation-audit disambiguation row pointing
citation-fixer (focused fix) and chain-into maintain for broader audit.
Broaden query triggers ("who is", "background on", "notes on") so
the failing routing-eval fixtures resolve.
- skills/enrich/SKILL.md: replace inlined Citation Requirements block with
backtick-wrapped `skills/conventions/quality.md` reference (the format
extractDelegationTargets recognizes). Silences the dry_violation warning.
- skills/citation-fixer/routing-eval.jsonl: rewrite the two failing fixtures
to embed "fix citations" verbatim so the substring matcher passes.
- skills/query/SKILL.md frontmatter: mirror the broadened RESOLVER.md
triggers so the trigger round-trip test passes.
Result: gbrain check-resolvable reports 0 warnings, 0 errors against
the actual checked-in skills/ tree.
Add an opt-in validation surface to parseMarkdown(): when called with
{ validate: true }, returns errors[] populated with seven canonical
ParseValidationError codes:
MISSING_OPEN, MISSING_CLOSE, YAML_PARSE, SLUG_MISMATCH,
NULL_BYTES, NESTED_QUOTES, EMPTY_FRONTMATTER
Existing callers are unaffected — validation is opt-in via the new
opts argument. The validation logic lives here as the single source of
truth for what counts as malformed brain-page frontmatter.
src/commands/lint.ts now consumes parseMarkdown(..., { validate: true })
and emits stable lint rule names (frontmatter-missing-close,
frontmatter-yaml-parse, frontmatter-null-bytes, frontmatter-nested-quotes,
frontmatter-slug-mismatch, frontmatter-empty). MISSING_OPEN is suppressed
to avoid double-reporting with the legacy no-frontmatter rule.
Tests: test/markdown-validation.test.ts (NEW, all 7 codes) +
test/lint-frontmatter.test.ts (NEW, lint integration + suppression).
Thin orchestrator (~280 lines) on top of parseMarkdown(..., {validate:true})
and isSyncable() (the canonical brain-page filter from src/core/sync.ts).
Three consumers call into this module: the gbrain frontmatter CLI, the
frontmatter_integrity doctor subcheck, and the v0.22.4 migration audit
phase. Single source of truth — no parallel validation stack.
Public API:
- autoFixFrontmatter(content, opts?): { content, fixes }
Mechanical auto-repair for the fixable subset (NULL_BYTES,
MISSING_CLOSE, NESTED_QUOTES, SLUG_MISMATCH). Idempotent.
- writeBrainPage(filePath, content, opts): path-guarded, .bak backup
before any in-place mutation. Path guard refuses writes outside
sourcePath. .bak is the safety contract for non-git brain repos.
- scanBrainSources(engine, opts?): walks every registered source via
direct SQL on sources.local_path, uses isSyncable() to filter,
blocks symlinks (matches sync's no-symlink policy), respects
AbortSignal.
The dirty-tree guard from src/core/dry-fix.ts:getWorkingTreeStatus() is
NOT used here — it rejects non-git repos as unsafe, but brain repos
aren't always git repos. .bak backups are the contract that works
universally.
Tests: test/brain-writer.test.ts (NEW, 16 cases) — autoFix idempotency,
path-guard reject, .bak backup, per-source rollup, AbortSignal mid-scan,
single-source filter, missing-source-path graceful skip, symlink no-loop.
New top-level command surface for the frontmatter-guard feature:
gbrain frontmatter validate <path> [--json] [--fix] [--dry-run]
Validate one .md file or recursively scan a directory. --fix writes
.bak then rewrites in place. No git-tree-clean guard — .bak is the
safety contract (works for both git and non-git brain repos).
gbrain frontmatter audit [--source <id>] [--json]
Read-only scan via scanBrainSources(). Per-source rollup grouped by
error code. --fix is intentionally NOT available here; use validate
--fix on the source path to repair.
gbrain frontmatter install-hook [--source <id>] [--force] [--uninstall]
Drops a pre-commit hook in each source that's a git repo (skips
non-git sources with a one-line note). Hook script gracefully
degrades when gbrain is missing on PATH (prints a warning, exits 0).
Refuses to clobber existing hooks without --force; writes <hook>.bak.
--uninstall reverses cleanly.
src/cli.ts wires frontmatter through handleCliOnly so --help works
without a DB connection. The audit subcommand instantiates an engine
internally only when needed.
Tests: test/frontmatter-cli.test.ts (NEW, 9 cases) +
test/frontmatter-install-hook.test.ts (NEW, 6 cases) — --help no-DB,
clean/broken validate, --fix dry-run, --fix non-git, --json envelope,
recursive directory scan with isSyncable filter parity, hook install
+ overwrite-protection + --force + --uninstall + silent-refresh.
Adds a frontmatter_integrity subcheck under gbrain doctor that calls scanBrainSources() (the same shared scanner the CLI and migration use). Reports per-source counts grouped by error code, with a fix hint pointing at `gbrain frontmatter validate <path> --fix`. Wrapped in a doctor progress phase with heartbeat so 50K-page brain scans stay visible. Tests: test/doctor.test.ts (UPDATE) — assertion that the subcheck calls scanBrainSources and the fix hint references the correct CLI.
New skill at skills/frontmatter-guard/SKILL.md that wraps the gbrain frontmatter CLI for agent-driven workflows. Agent-agnostic — no references to private host libraries. Registered in skills/manifest.json and skills/RESOLVER.md (the trigger row was added in the Part A commit). Triggers: "validate frontmatter", "check frontmatter", "fix frontmatter", "frontmatter audit", "brain lint". Includes routing-eval fixtures that pass the substring matcher. The SKILL.md has the conformance-required Output Format and Anti-Patterns sections. Anti-patterns explicitly call out: don't auto-fix MISSING_OPEN or EMPTY_FRONTMATTER without user input, don't skip .bak backups, don't install the pre-commit hook on non-git brain dirs.
Adds the v0.22.4 migration that surveys every registered source for
frontmatter issues and queues per-source repair commands without ever
mutating brain content. Three idempotent phases:
- schema: no-op (no DB changes in v0.22.4)
- audit: scanBrainSources() across ALL registered sources; writes
JSON report to ~/.gbrain/migrations/v0.22.4-audit.json
- emit-todo: appends one entry per source-with-issues to
~/.gbrain/migrations/pending-host-work.jsonl, each with the exact
`gbrain frontmatter validate <source-path> --fix` command
The agent reads skills/migrations/v0.22.4.md after upgrade, surfaces
the report counts to the user, and runs the fix command only with
explicit consent. `apply-migrations --yes` never silently rewrites
brain pages.
Filename convention: TS orchestrator at v0_22_4.ts (underscores, since
TS module paths can't have dots); user-facing migration doc at
skills/migrations/v0.22.4.md (dotted, matches existing convention).
The pending-host-work.jsonl skill field references the dotted-path doc.
Skips cleanly when no sources are registered (fresh install).
Tests: test/migrations-v0_22_4.test.ts (NEW, 9 cases) + updated
test/migration-orchestrator-v0_21_0.test.ts to allow v0.22.4 after,
test/apply-migrations.test.ts skippedFuture arrays extended to include
v0.22.4, test/check-resolvable.test.ts regression guard asserting the
actual checked-in skills/ tree has 0 warnings + 0 errors.
- docs/integrations/pre-commit.md (NEW): recipe doc covering install,
bypass (`git commit --no-verify`), uninstall, and downstream-fork
integration notes. Includes the full pipeline diagram showing how
the hook (write-time gate), doctor (audit gate), and CLI (fix tool)
share parseMarkdown(..., {validate:true}) as the single source of
truth.
- docs/UPGRADING_DOWNSTREAM_AGENTS.md: append v0.22.4 section with the
diff pattern for forks that had inline frontmatter validators. Covers
the five upgrade actions: replace ad-hoc validators, drop
lib/brain-writer.mjs references (it never shipped), wire the doctor
subcheck into custom health pipelines, optionally install the
pre-commit hook on git-backed brain repos, and walk
pending-host-work.jsonl after apply-migrations.
- llms.txt + llms-full.txt: regenerated from build:llms script after
the new docs landed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…arnings-v2 # Conflicts: # CHANGELOG.md # VERSION
CI typecheck caught three call sites that passed loadConfig()'s GBrainConfig | null result straight into toEngineConfig() (which expects GBrainConfig, not null): - src/commands/frontmatter.ts:64 (audit subcommand connect) - src/commands/frontmatter-install-hook.ts:86 (install-hook connect) - src/commands/migrations/v0_22_4.ts:59 (audit phase connect) The frontmatter CLI and install-hook paths follow the existing src/commands/repair-jsonb.ts pattern: throw 'No brain configured. Run: gbrain init' so users get an actionable message instead of a TS-shaped runtime crash. The v0.22.4 migration audit phase takes a different shape: a fresh install or test environment running apply-migrations shouldn't fail hard just because there's no brain to scan yet. Return a clean 'skipped: no_brain_configured' phase result so the orchestrator continues normally and the ledger records a complete (skipped) run.
Closes plan item B14 (the E2E that was promised but not delivered before
the original ship). Runs the v0_22_4 orchestrator end-to-end on PGLite
against a fixture brain with two registered sources and synthetic
malformed pages on disk. Asserts:
- audit phase writes ~/.gbrain/migrations/v0.22.4-audit.json with
per-source counts (NESTED_QUOTES + NULL_BYTES on alpha,
NESTED_QUOTES on beta)
- emit-todo phase appends one entry per source-with-issues to
pending-host-work.jsonl, each pointing at skills/migrations/v0.22.4.md
with the exact `gbrain frontmatter validate <source> --fix` command
- the migration is audit-only — no fixture page is mutated
during apply-migrations (no .bak created, contents byte-identical)
- re-running the orchestrator is idempotent — JSONL stays at 2 lines
Adds a small test-injection point to v0_22_4.ts:
__setTestEngineOverride(engine: BrainEngine | null): void
Mirrors src/commands/repair-jsonb.ts pattern. When set, phaseBAudit
uses the injected engine instead of loadConfig + createEngine. Production
path is unchanged: the override is null by default and the existing
loadConfig logic runs end-to-end. Required because Bun's os.homedir()
does not observe mid-process process.env.HOME mutations, so we can't
redirect loadConfig's config-file lookup via env-var overrides; the
injection point is the only hermetic way to E2E-test the orchestrator
without writing to the user's real ~/.gbrain/config.json.
Test runs unconditionally in CI's Tier 1 (no DATABASE_URL needed,
PGLite in-memory).
…arnings-v2 # Conflicts: # CHANGELOG.md # VERSION # package.json
garrytan
added a commit
that referenced
this pull request
Apr 28, 2026
Merges 5 master commits since last merge: v0.22.1 autopilot fix wave (#447), v0.22.2 minions worker reliability (#458), v0.22.4 frontmatter-guard (#448), sourceId in cycle sync phase (#475), and post-migration schema verification (#488). Conflict resolutions: - VERSION: kept this branch's reserved 0.27.0 slot (master at 0.22.6). - CHANGELOG.md: kept v0.27.0 entry at top, then master's v0.22.6 → v0.21.0 entries below in order. - CLAUDE.md: merged the v0.27 cycle bullet (8 phases, synthesize, patterns, transcript-discovery, dream CLI flags) with master's v0.22.1/v0.22.5 cycle additions (signal: AbortSignal, willRunExtractPhase, resolveSourceForDir). - src/core/cycle.ts: kept v0.27 yieldDuringPhase + synthInputFile/synthDate/synthFrom/synthTo CycleOpts fields AND added master's v0.22.1 signal: AbortSignal field. Both coexist. - llms-full.txt: regenerated against the merged tree. The dream_verdicts schema migration moved v25 → v30 in the prior merge. Master ended at v29 (cathedral_ii_code_edges_rls); v30 is uncontested. Tests pass post-merge: 105/105 dream + cycle tests across 9 files. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bundle of Part A (resolve all 7
gbrain check-resolvablewarnings on master) plus Part B (ship frontmatter-guard as a real feature with library, CLI, doctor subcheck, migration, and pre-commit hook).Resolver warnings (Part A):
skills/maintain/SKILL.md: drop"citation audit"trigger so the focusedcitation-fixerskill is the single ownerskills/RESOLVER.md: add citation-audit disambiguation row + broaden query triggers ("who is","background on","notes on")skills/enrich/SKILL.md: replace inlined Citation Requirements block with backtick-wrapped convention reference (the formatextractDelegationTargetsrecognizes)skills/citation-fixer/routing-eval.jsonl: rewrite the two failing fixtures to embed"fix citations"so substring matching passesskills/query/SKILL.md: mirror broadened triggers in frontmatterFrontmatter-guard feature (Part B):
src/core/markdown.ts—parseMarkdown(..., { validate: true })returns the seven canonicalParseValidationErrorcodes (MISSING_OPEN,MISSING_CLOSE,YAML_PARSE,SLUG_MISMATCH,NULL_BYTES,NESTED_QUOTES,EMPTY_FRONTMATTER). Existing callers unaffected.src/commands/lint.ts— frontmatter rules delegate toparseMarkdownfor stable rule names.src/core/brain-writer.ts(NEW) — thin orchestrator:autoFixFrontmatter(4 fixable codes),writeBrainPagewith path-guard +.bakbackup,scanBrainSourceswalking every registered source viasource-resolver.tsandisSyncable().src/commands/frontmatter.ts(NEW) —gbrain frontmatter validate <path> [--fix] [--dry-run] [--json]andgbrain frontmatter audit [--source <id>] [--json]. Theauditsubcommand is read-only.src/commands/frontmatter-install-hook.ts(NEW) —gbrain frontmatter install-hookdrops a pre-commit hook in git-backed sources; refuses to clobber without--force; gracefully degrades whengbrainis missing on PATH.src/commands/doctor.ts— newfrontmatter_integritysubcheck callsscanBrainSources()and reports per-source counts with a fix hint.src/commands/migrations/v0_22_4.ts(NEW) — audit-only migration. Three idempotent phases (schema noop, audit, emit-todo). Writes a JSON report to~/.gbrain/migrations/v0.22.4-audit.jsonand queues per-sourcegbrain frontmatter validate <source> --fixcommands topending-host-work.jsonl. Never silently mutates brain content during apply-migrations.skills/frontmatter-guard/SKILL.md(NEW) — agent-agnostic skill, registered inmanifest.jsonandRESOLVER.md.Test coverage:
parseMarkdownvalidation + lint integration +brain-writer(16 cases) + CLI subprocess (9 cases) + install-hook (6 cases) + migration orchestrator (9 cases).test/check-resolvable.test.tsadds a regression guard asserting the actual checked-inskills/tree has 0 warnings + 0 errors.Versioning:
package.jsonandVERSIONboth bumped to 0.22.4 (master shipped v0.22.0 in PR v0.22.0 feat: source-aware search ranking — curated pages win, swamp dampened #439 — source-aware search ranking — while this branch was in flight; v0.22.4 leaves room for parallel work).bun build --compile && ./bin/gbrain --versionprints0.22.4.Test Coverage
Pre-Landing Review
Plan-eng-review ran before implementation: 13 decisions captured (D1–D13), codex outside-voice ran with 9 findings (7 mechanical bugs folded in, 2 strategic forks resolved by user — D12 source-aware throughout, D13 extend
parseMarkdowninstead of standalone validation stack). No issues remained at implementation time.Plan Completion
All planned items DONE. The plan's three deferred items remain deferred:
writeBrainPageintegration intosrc/core/import-file.ts— explicitly out of scope per D7check-resolvableto parse RESOLVER.md disambiguation rules — added to TODOS.md as P2 follow-up (D10)Documentation
docs/integrations/pre-commit.md(NEW) — recipe doc covering install/bypass/uninstall/downstream-fork notesdocs/UPGRADING_DOWNSTREAM_AGENTS.md— appended v0.22.4 section with the diff pattern for forks that had inline validators (droplib/brain-writer.mjsreferences — that file never shipped)CHANGELOG.md— full v0.22.4 entry per project format (release summary + numbers + "To take advantage of v0.22.4" block + itemized changes)TODOS.md— added D10 entry for the check-resolvable disambiguation parser follow-upTest plan
gbrain check-resolvable --skills-dir ./skills→OK — 30 skills, all reachable(was 7 warnings on master)bun test test/markdown-validation.test.ts test/lint-frontmatter.test.ts test/brain-writer.test.ts test/frontmatter-cli.test.ts test/frontmatter-install-hook.test.ts test/migrations-v0_22_4.test.ts test/check-resolvable.test.ts test/doctor.test.ts test/apply-migrations.test.ts test/migration-orchestrator-v0_21_0.test.ts test/resolver.test.ts test/skills-conformance.test.ts test/markdown.test.ts test/lint.test.ts test/build-llms.test.ts)bun build --compile && ./bin/gbrain --versionprints0.22.4gbrain frontmatter --helpworks without DB connection--fixwrites.bakand rewrites,auditper-source rolluporigin/master(which shipped v0.22.0 in PR v0.22.0 feat: source-aware search ranking — curated pages win, swamp dampened #439) cleanly; no functional conflicts🤖 Generated with Claude Code