Skip to content

feat: add gbrain relink — rebuild DB link graph from markdown#117

Closed
EagleEyez1 wants to merge 2 commits intogarrytan:masterfrom
EagleEyez1:feat/relink
Closed

feat: add gbrain relink — rebuild DB link graph from markdown#117
EagleEyez1 wants to merge 2 commits intogarrytan:masterfrom
EagleEyez1:feat/relink

Conversation

@EagleEyez1
Copy link
Copy Markdown

@EagleEyez1 EagleEyez1 commented Apr 14, 2026

Summary

  • Add gbrain relink [--dir <brain-dir>] [--dry-run]: walks every syncable markdown file under <brain-dir> and reconciles the Postgres links table against what the markdown actually says. Fixes the drift case where edits add or remove links without changing the page content hash (sync skips those pages, DB never sees the new links).
  • Wire reconcilePageLinks into importFromContent so fresh imports stay consistent without a separate pass. Covers both code paths: the hash-match skip branch and the main import branch.
  • Fall back to a ## Timeline heading in splitBody when the serialized --- delimiter is missing. Pages written by hand now split correctly into compiled_truth and timeline instead of dumping everything into compiled_truth.
  • Honor --help / -h on gbrain relink. No other command does this today — happy to drop that commit and match the existing convention, or split it into a follow-up PR that standardizes help across commands. Your call.
  • Bump to 0.9.4 and document the change in CHANGELOG.md.

Test Coverage

CODE PATH COVERAGE
==================
[+] extractInternalMarkdownLinks(content, sourceSlug)
    ├── [★★★ TESTED] extracts internal .md links with resolved target slugs — test/markdown.test.ts
    └── [★★★ TESTED] deduplicates identical target slugs across multiple matches — test/markdown.test.ts

[+] resolveInternalMarkdownLink(sourceSlug, href)
    ├── [★★★ TESTED] resolves relative and ../ paths to page slugs — test/markdown.test.ts
    ├── [★★★ TESTED] rejects external http(s) URLs — test/markdown.test.ts
    ├── [★★★ TESTED] rejects bare #anchors — test/markdown.test.ts
    └── [★★★ TESTED] rejects non-markdown assets (e.g. .png) — test/markdown.test.ts

[+] splitBody(body) — ## Timeline fallback
    └── [★★★ TESTED] splits on ## Timeline when --- delimiter is absent — test/markdown.test.ts

[+] reconcilePageLinks(engine, slug, desiredTargets) — via importFromContent
    ├── [★★★ TESTED] reconciles outgoing links on first import — test/import-file.test.ts
    └── [★★★ TESTED] reconciles outgoing links even when content hash is unchanged — test/import-file.test.ts

[-] runRelink(engine, args) — end-to-end is exercised via importFromContent tests above;
    the command itself is a thin walker + dispatcher, no dedicated unit tests added.

Tests: 716 → 722 (+6 new tests across 2 existing files)

Pre-Landing Review

  • Ran bun test on a fresh clone: 596 pass / 0 fail / 126 skip.
  • reconcilePageLinks is called inside engine.transaction(...) in both code paths, so a mid-reconcile crash cannot leak partial link state.
  • addLink errors are logged via console.warn and swallowed. This matches the soft-warning pattern for dangling link targets (common in real brains mid-sync). Real infrastructure failures would still bubble up via the enclosing transaction rollback.
  • Verified gbrain relink --dry-run --dir ~/brain reports 4236 syncable markdown file(s) on a real 4755-page brain without mutating state.
  • Verified gbrain relink --dir ~/brain (live) reconciles the full brain with per-slug warnings only for unresolved targets; gbrain doctor --json reports healthy afterward.

Design Review

No frontend files changed — design review skipped.

Eval Results

No prompt-related files changed — evals skipped.

TODOS

No TODO items completed in this PR.

Test plan

  • bun test test/markdown.test.ts — 19 pass, 0 fail
  • bun test test/import-file.test.ts — 18 pass, 0 fail
  • bun test — 596 pass, 0 fail, 126 skip
  • gbrain relink --help — prints usage, does not execute
  • gbrain relink -h — same
  • gbrain relink --dry-run --dir ~/brain — reports file count, no writes
  • gbrain relink --dir ~/brain — reconciles on a 4755-page brain, warns only on unresolved targets
  • gbrain doctor --json — returns healthy after a live relink run
  • Tier-2 E2E skipped: DATABASE_URL not set in this environment.

Documentation

  • CHANGELOG.md: added the 0.9.4 release note.
  • VERSION and package.json: bumped to 0.9.4.
  • README.md: added gbrain relink to the LINKS + GRAPH section.
  • docs/guides/cron-schedule.md: referenced gbrain relink in the weekly maintenance and dream-cycle flows.

… links

- New gbrain relink [--dir <brain-dir>] CLI command
- extractInternalMarkdownLinks / resolveInternalMarkdownLink in core/markdown
- reconcilePageLinks in core/import-file — syncs DB links to markdown links on every import, even for unchanged content
- Body splitter now falls back to ## Timeline heading when delimiter is absent
- Docs: cron-schedule.md and README.md updated to reference relink in weekly + dream-cycle flows
- Tests: import-file and markdown test coverage for link extraction and reconciliation

Work-in-progress local feature, preserved here before fast-forwarding master to origin/master. Rebase onto master once main checkout is updated.
Previously `gbrain relink --help` would try to relink because argument
parsing didn't recognize --help as a help request and fell through to
the normal execution path. Add an explicit short-circuit at the top of
runRelink and document the command surface.
@EagleEyez1
Copy link
Copy Markdown
Author

Closing — the functionality this PR was adding is now fully covered by upstream:

No reason to carry a separate relink command. Thanks for the project.

@EagleEyez1 EagleEyez1 closed this Apr 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant