From 54fdd4ba81df524f7c3a2913e0c7d87d5e17f12b Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Sat, 11 Apr 2026 21:32:03 -1000 Subject: [PATCH] fix: CLI routing bugs found during DX review - Fixed subArgs reference error in handleCliOnly (used wrong variable name) - Renamed gbrain backlinks check/fix to gbrain check-backlinks to avoid conflict with existing backlinks operation (per-page incoming links) - Added TOOLS section to --help output showing publish, check-backlinks, lint, report - Added upload-raw and signed-url to FILES section in --help - Updated all docs/migration references to use check-backlinks --- CHANGELOG.md | 4 ++-- skills/migrations/v0.9.0.md | 20 ++++++++++---------- src/cli.ts | 20 ++++++++++++++------ src/commands/backlinks.ts | 12 ++++++------ 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index caa1dd564..176dc0d50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,8 +70,8 @@ All notable changes to GBrain will be documented in this file. uploaded, source_url, type). - **All skills** updated to reference actual `gbrain files` commands instead of theoretical patterns. -- **Back-link enforcer closes the loop.** `gbrain backlinks check` scans your - brain for entity mentions without back-links. `gbrain backlinks fix` creates +- **Back-link enforcer closes the loop.** `gbrain check-backlinks check` scans your + brain for entity mentions without back-links. `gbrain check-backlinks fix` creates them. The Iron Law of Back-Linking is in every skill, now the code enforces it. - **Page linter catches LLM slop.** `gbrain lint` flags "Of course! Here is..." diff --git a/skills/migrations/v0.9.0.md b/skills/migrations/v0.9.0.md index 16357d27b..150010725 100644 --- a/skills/migrations/v0.9.0.md +++ b/skills/migrations/v0.9.0.md @@ -39,12 +39,12 @@ mobile-optimized. Self-contained HTML, no server needed. (always encrypt), and sharing workflows (local file, cloud upload + signed URL, static hosting). -### 2. `gbrain backlinks check/fix` -- enforce the Iron Law +### 2. `gbrain check-backlinks check/fix` -- enforce the Iron Law ```bash -gbrain backlinks check --dir /path/to/brain # report missing back-links -gbrain backlinks fix --dir /path/to/brain # create them -gbrain backlinks fix --dir /path/to/brain --dry-run # preview +gbrain check-backlinks check --dir /path/to/brain # report missing back-links +gbrain check-backlinks fix --dir /path/to/brain # create them +gbrain check-backlinks fix --dir /path/to/brain --dry-run # preview ``` Scans all pages for entity mentions (links to people/ and companies/), checks @@ -104,7 +104,7 @@ operations, swap them for the built-in gbrain commands: | `node scripts/save-report.mjs --cron ` | `gbrain report --type --content "..."` | | `node scripts/validate-brain-links.mjs` | `gbrain files verify` | | `node scripts/migrate-brain-files.mjs` | `gbrain files mirror + redirect` | -| Manual back-link checking | `gbrain backlinks check --dir ` | +| Manual back-link checking | `gbrain check-backlinks check --dir ` | | Manual page quality review | `gbrain lint --fix` | **For each replacement:** @@ -143,11 +143,11 @@ gbrain report --type enrichment-sweep --title "Enrichment Sweep" --content "..." ```bash # Check back-link health -gbrain backlinks check --dir /path/to/brain +gbrain check-backlinks check --dir /path/to/brain # If gaps found, fix them: -gbrain backlinks fix --dir /path/to/brain --dry-run # preview -gbrain backlinks fix --dir /path/to/brain # apply +gbrain check-backlinks fix --dir /path/to/brain --dry-run # preview +gbrain check-backlinks fix --dir /path/to/brain # apply # Lint for quality issues gbrain lint /path/to/brain @@ -206,7 +206,7 @@ If you have cron jobs that call custom scripts, update them: ```bash # Daily backlink check + auto-fix -0 3 * * * gbrain backlinks fix --dir /path/to/brain +0 3 * * * gbrain check-backlinks fix --dir /path/to/brain # Weekly lint + auto-fix 0 4 * * 0 gbrain lint /path/to/brain --fix @@ -216,7 +216,7 @@ If you have cron jobs that call custom scripts, update them: The skill files have been updated to reference gbrain commands: - `skills/ingest/SKILL.md` -- uses `gbrain files upload-raw` for raw sources -- `skills/maintain/SKILL.md` -- uses `gbrain backlinks`, `gbrain lint`, `gbrain report` +- `skills/maintain/SKILL.md` -- uses `gbrain check-backlinks`, `gbrain lint`, `gbrain report` - `skills/publish/SKILL.md` -- NEW skill for `gbrain publish` - `skills/enrich/SKILL.md` -- references `gbrain files upload-raw` for raw API data - `skills/_brain-filing-rules.md` -- documents `.redirect.yaml` format and commands diff --git a/src/cli.ts b/src/cli.ts index 9a212c612..404779895 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -18,7 +18,7 @@ for (const op of operations) { } // CLI-only commands that bypass the operation layer -const CLI_ONLY = new Set(['init', 'upgrade', 'post-upgrade', 'check-update', 'integrations', 'publish', 'backlinks', 'lint', 'report', 'import', 'export', 'files', 'embed', 'serve', 'call', 'config', 'doctor', 'migrate']); +const CLI_ONLY = new Set(['init', 'upgrade', 'post-upgrade', 'check-update', 'integrations', 'publish', 'check-backlinks', 'lint', 'report', 'import', 'export', 'files', 'embed', 'serve', 'call', 'config', 'doctor', 'migrate']); async function main() { const args = process.argv.slice(2); @@ -249,22 +249,22 @@ async function handleCliOnly(command: string, args: string[]) { } if (command === 'publish') { const { runPublish } = await import('./commands/publish.ts'); - await runPublish(subArgs); + await runPublish(args); return; } - if (command === 'backlinks') { + if (command === 'check-backlinks') { const { runBacklinks } = await import('./commands/backlinks.ts'); - await runBacklinks(subArgs); + await runBacklinks(args); return; } if (command === 'lint') { const { runLint } = await import('./commands/lint.ts'); - await runLint(subArgs); + await runLint(args); return; } if (command === 'report') { const { runReport } = await import('./commands/report.ts'); - await runReport(subArgs); + await runReport(args); return; } @@ -388,6 +388,8 @@ IMPORT/EXPORT FILES files list [slug] List stored files files upload --page Upload file to storage + files upload-raw --page Smart upload (size routing + .redirect.yaml) + files signed-url Generate signed URL (1-hour) files sync Bulk upload directory files verify Verify all uploads @@ -409,6 +411,12 @@ TIMELINE timeline [] View timeline timeline-add Add timeline entry +TOOLS + publish [--password] Shareable HTML (strips private data, optional AES-256) + check-backlinks [dir] Find/fix missing back-links across brain + lint [--fix] Catch LLM artifacts, placeholder dates, bad frontmatter + report --type --content ... Save timestamped report to brain/reports/ + ADMIN stats Brain statistics health Brain health dashboard diff --git a/src/commands/backlinks.ts b/src/commands/backlinks.ts index 6f5c13a7b..b99ae9567 100644 --- a/src/commands/backlinks.ts +++ b/src/commands/backlinks.ts @@ -1,13 +1,13 @@ /** - * gbrain backlinks — Check and fix missing back-links across brain pages. + * gbrain check-backlinks — Check and fix missing back-links across brain pages. * * Deterministic: zero LLM calls. Scans pages for entity mentions, * checks if back-links exist, and optionally creates them. * * Usage: - * gbrain backlinks check [--dir ] # report missing back-links - * gbrain backlinks fix [--dir ] # create missing back-links - * gbrain backlinks fix --dry-run # preview fixes + * gbrain check-backlinks check [--dir ] # report missing back-links + * gbrain check-backlinks fix [--dir ] # create missing back-links + * gbrain check-backlinks fix --dry-run # preview fixes */ import { readFileSync, writeFileSync, readdirSync, statSync, existsSync } from 'fs'; @@ -175,7 +175,7 @@ export async function runBacklinks(args: string[]) { const dryRun = args.includes('--dry-run'); if (!subcommand || !['check', 'fix'].includes(subcommand)) { - console.error('Usage: gbrain backlinks [--dir ] [--dry-run]'); + console.error('Usage: gbrain check-backlinks [--dir ] [--dry-run]'); console.error(' check Report missing back-links'); console.error(' fix Create missing back-links (appends to Timeline)'); console.error(' --dir Brain directory (default: current directory)'); @@ -201,7 +201,7 @@ export async function runBacklinks(args: string[]) { console.log(` ${gap.targetPage} <- ${gap.sourcePage}`); console.log(` "${gap.entityName}" mentioned in "${gap.sourceTitle}"`); } - console.log(`\nRun 'gbrain backlinks fix --dir ${brainDir}' to create them.`); + console.log(`\nRun 'gbrain check-backlinks fix --dir ${brainDir}' to create them.`); } else { const label = dryRun ? '(dry run) ' : ''; const fixed = fixBacklinkGaps(brainDir, gaps, dryRun);