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
This commit is contained in:
Garry Tan
2026-04-11 21:32:03 -10:00
parent d798d81462
commit 54fdd4ba81
4 changed files with 32 additions and 24 deletions
+2 -2
View File
@@ -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..."
+10 -10
View File
@@ -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 <type>` | `gbrain report --type <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 <brain>` |
| Manual back-link checking | `gbrain check-backlinks check --dir <brain>` |
| Manual page quality review | `gbrain lint <brain> --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
+14 -6
View File
@@ -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 <file> --page <slug> Upload file to storage
files upload-raw <file> --page <s> Smart upload (size routing + .redirect.yaml)
files signed-url <path> Generate signed URL (1-hour)
files sync <dir> Bulk upload directory
files verify Verify all uploads
@@ -409,6 +411,12 @@ TIMELINE
timeline [<slug>] View timeline
timeline-add <slug> <date> <text> Add timeline entry
TOOLS
publish <page.md> [--password] Shareable HTML (strips private data, optional AES-256)
check-backlinks <check|fix> [dir] Find/fix missing back-links across brain
lint <dir|file> [--fix] Catch LLM artifacts, placeholder dates, bad frontmatter
report --type <name> --content ... Save timestamped report to brain/reports/
ADMIN
stats Brain statistics
health Brain health dashboard
+6 -6
View File
@@ -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 <brain-dir>] # report missing back-links
* gbrain backlinks fix [--dir <brain-dir>] # create missing back-links
* gbrain backlinks fix --dry-run # preview fixes
* gbrain check-backlinks check [--dir <brain-dir>] # report missing back-links
* gbrain check-backlinks fix [--dir <brain-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 <check|fix> [--dir <brain-dir>] [--dry-run]');
console.error('Usage: gbrain check-backlinks <check|fix> [--dir <brain-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);