Skip to content

The index path's output contradicts itself: --dry-run index suggests converting 500 already-converted filings, db stats suggests a db setup that cannot help, and sec index ignores --json #370

Description

@sroussey

Three separate defects on one path, all of them guidance — which CLAUDE.md treats as one
mechanism: "use the same command strings sec status prints, so the map and the suggestions stay
one vocabulary."

(a) sec --dry-run index prints three lines, two of them false

With 500 converted, unindexed documents in filing_document and the kb tables already built:

$ sec --dry-run index
-> Dry run — no data will be written
Would index 500 filing(s) into the knowledge base.
indexed 0 filing(s) · 0 sections

  Next:
    sec update documents   there is nothing converted to index yet

Five hundred filings are converted and waiting — the line above says so.

Mechanism: 6d9ee18 made the dry-run branch return { indexed: 0, sections: 0, skipped, truncated }
(IndexFilingSectionsTask.ts:185-188), and the renderer keys its summary and its suggestion off
that zero (ask.ts:69-81):

console.log(`indexed ${out.indexed} filing(s) · ${out.sections} sections` + );
if (out.indexed > 0 || out.skipped > 0) { suggest({ command: 'sec ask "..."' }); }
else { suggest({ command: "sec update documents", why: "there is nothing converted to index yet" }); }

Fix: put the count on the output — wouldIndex (or a dryRun: true discriminator alongside
work.length) — and have the renderer print and branch on it. The console.log inside the task
then goes away too, which is (c).

(b) db stats tells the operator to run a command that cannot fix what it is pointing at

b3c7552d appends the three knowledge-base tables to the report with rows: null, deliberately
"the same signal a registered-but-uncreated table reports" (kbTableStats.ts:29). But
src/cli/groups/db.ts:70 renders that signal as one fixed sentence:

console.log(`\n${missing} table(s) not counted (n/a) — run \`db setup\`?`);

and db setup does not create them — they are outside storageRegistry, built lazily by the
first command that opens the index:

$ sec db setup                      # exit 0
$ sec db stats | tail -5
kb_document                n/a
kb_chunk                   n/a
kb_index                   n/a

3 table(s) not counted (n/a) — run `db setup`?      # ← immediately after db setup succeeded

The command that fixes it is sec index. Fix: let a TableStat carry the command that creates
it, or split the footer into the registry rows (db setup) and the kb rows (sec index). This
matters more than it looks: it is the only n/a an operator can actually hit on a healthy database,
so it is the only time that footer is ever read.

(c) sec index ignores --json

The global flag is advertised as "Emit status and error output as machine-parseable JSON"
(GlobalOptions.ts:16) and status honours it — valid JSON, including nextSteps. index does
not, and under --dry-run it interleaves one genuine JSON status line with two plain-text lines on
the same stream:

$ sec --json --dry-run index
{"status":"info","message":"Dry run — no data will be written"}
Would index 0 filing(s) into the knowledge base.
indexed 0 filing(s) · 0 sections
--> INVALID JSON: Unexpected non-whitespace character after JSON at position 64 (line 2 column 1)

ask gets this right (ask.ts:143-146). index needs the same branch. Note the second line
comes from a console.log inside the task (IndexFilingSectionsTask.ts:186) — consistent
with the nine other tasks that print inside an isDryRun() branch, so this is a house pattern
rather than a one-off, and it is invisible to isJsonOutput() by construction. Returning the
count and letting the command render it fixes (a) and (c) together.

Verify

sec db setup && sec index                      # build the kb tables
# seed filing_document with a few converted, unindexed rows
sec --dry-run index                            # (a)
sec db setup && sec db stats | tail -5         # (b)
sec --json --dry-run index | node -e 'let s="";process.stdin.on("data",d=>s+=d)
  .on("end",()=>{try{JSON.parse(s);console.log("VALID")}catch(e){console.log("INVALID:",e.message)}})'   # (c)

Found during the 2026-09-14 review. Snapshot: workglow-dev/prdanalysis/grades/2026-09-14/sec-detailed.md §4.5.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions