Skip to content

fix(cli): register 'reindex' in CLI_ONLY so v0.32.7 sweep is reachable#913

Open
vinsew wants to merge 1 commit into
garrytan:masterfrom
vinsew:fix-reindex-cli-only
Open

fix(cli): register 'reindex' in CLI_ONLY so v0.32.7 sweep is reachable#913
vinsew wants to merge 1 commit into
garrytan:masterfrom
vinsew:fix-reindex-cli-only

Conversation

@vinsew
Copy link
Copy Markdown
Contributor

@vinsew vinsew commented May 12, 2026

Summary

gbrain reindex --markdown (introduced in v0.32.7 #898) exits with "Unknown command: reindex" on every invocation. The dispatcher in src/cli.ts only reaches case 'reindex' (inside handleCliOnly) when CLI_ONLY.has(command) is true at line 90, but the set lists 'reindex-code' and 'reindex-frontmatter' without bare 'reindex'. Adding the missing token wires the case back into the dispatch.

Reproduce on unmodified origin/master

$ gbrain reindex --markdown --dry-run --json
Unknown command: reindex
Run gbrain --help for available commands.
EXIT=1

Same input after this patch (gbrain reindex --markdown --dry-run --json) returns the expected {"pending":N,"would_reindex":N,"dry_run":true,"chunker_version":2}.

Byte-level evidence the case is reachable only via CLI_ONLY

  • src/cli.ts:30CLI_ONLY set, currently lists 'reindex-code', 'reindex-frontmatter', not 'reindex'.
  • src/cli.ts:90if (CLI_ONLY.has(command)) { await handleCliOnly(...); return; } is the only path into handleCliOnly.
  • src/cli.ts:96-100 — fallthrough is cliOps.get(command) → undefined for 'reindex' (zero name: 'reindex' entry in src/core/operations.ts) → console.error('Unknown command: ${command}'); process.exit(1).
  • src/cli.ts:1075case 'reindex' lives inside async function handleCliOnly (line 707). Identical pattern to case 'orphans' (1069) and case 'salience' (1081), both of which are registered in CLI_ONLY.

Why CI didn't catch this in #898

test/reindex.test.ts exercises runReindex(engine, args) directly, bypassing the CLI dispatcher. Two new cases in this PR close that gap:

  1. Structural — read src/cli.ts, locate the CLI_ONLY = new Set(...) line, require it match /'reindex',/.
  2. Runtime — spawn bun run src/cli.ts reindex --markdown --help in a subprocess and assert stderr+stdout does NOT contain Unknown command: reindex.

The structural test is the same shape as test/book-mirror.test.ts's "book-mirror is in CLI_ONLY (does not get 'Unknown command')" guard from PR #564.

Context on the #898 review note

#898 body recorded Codex outside-voice finding #3 as a false positive ("CLI_ONLY is the set that doesn't need an engine; reindex correctly belongs to the engine-backed dispatch"). The premise that CLI_ONLY excludes engine-backed commands does not match the current codebase: handleCliOnly orchestrates engine connect inside per-case branches for many commands (orphans, salience, anomalies, sources, mounts, dream, etc.). All currently-working engine-backed commands inside handleCliOnly are in CLI_ONLY; reindex is the only one that isn't, which is why it's the only one that fails this way.

Verified end-to-end

Production brain (Postgres, 279 pages, all chunker_version=1 before fix) with this patch applied:

$ gbrain reindex --markdown --dry-run --json
{"pending":279,"would_reindex":279,"dry_run":true,"chunker_version":2}

$ gbrain reindex --markdown --json
[reindex.markdown] 279/279 (100%) done
{"pending":279,"reindexed":279,"skipped":0,"failed":0,"chunker_version":2}

279/279 reindexed, 0 failures, ~3:28, ~$0.08 in OpenAI text-embedding-3-large. CJK sync (品牌圣经.md) round-trips cleanly through the new chunker on the post-sweep brain.

Test plan

  • bun run typecheck — clean
  • bun test test/reindex.test.ts — 8 pass / 0 fail (was 6; 2 new cases for CLI_ONLY registration)
  • Subprocess reproduction (before fix): gbrain reindex --markdown --dry-run → "Unknown command: reindex", EXIT=1
  • Subprocess reproduction (after fix): gbrain reindex --markdown --dry-run --json → valid JSON, EXIT=0
  • End-to-end sweep against production Postgres brain (279 pages)

🤖 Generated with Claude Code


View in Codesmith
Need help on this PR? Tag @codesmith with what you need.

  • Let Codesmith autofix CI failures and bot reviews

`case 'reindex'` lives inside `handleCliOnly` (src/cli.ts:1075), which the
dispatcher only enters when `CLI_ONLY.has(command)` is true at src/cli.ts:90.
The set lists `'reindex-code'` and `'reindex-frontmatter'` but not bare
`'reindex'`, so the markdown re-chunk sweep introduced in v0.32.7 is dead
code: every invocation falls through to `cliOps.get('reindex')` (undefined,
no Operation registered) and exits 1 with "Unknown command: reindex".

Reproduce on unmodified origin/master:

    $ gbrain reindex --markdown --dry-run --json
    Unknown command: reindex
    Run gbrain --help for available commands.
    EXIT=1

Fix: add `'reindex',` next to `'reindex-code'` / `'reindex-frontmatter'`.

Test coverage added in `test/reindex.test.ts`:

- Structural: parse the CLI_ONLY line and require it match `/'reindex',/`.
- Runtime: spawn `bun run src/cli.ts reindex --markdown --help` and assert
  stderr+stdout does NOT contain "Unknown command: reindex". The
  pre-existing `test/reindex.test.ts` cases only call `runReindex(engine, ...)`
  directly, bypassing the dispatcher — which is how this regression slipped
  past CI in garrytan#898.

Verified locally on a production brain: with the fix in place,
`gbrain reindex --markdown` swept 279 pre-bump pages to chunker_version=2
in 3:28, 0 failures, ~$0.08 in OpenAI embeddings.

Context: PR garrytan#898 (v0.32.7) body marked Codex finding garrytan#3 (reindex not in
CLI_ONLY) as a false positive on the grounds that "CLI_ONLY is the set
that doesn't need an engine; reindex correctly belongs to the engine-backed
dispatch." That premise is incorrect for this codebase — `handleCliOnly`
contains many engine-backed commands (orchestrating engine connect inside
the per-case branch). `case 'reindex'` at src/cli.ts:1075 follows the same
pattern as `case 'orphans'` (1069) and `case 'salience'` (1081), both of
which are in CLI_ONLY.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
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.

2 participants