Skip to content

fix(cli): improve inspect concurrency performance hints - #101

Merged
Moskize91 merged 17 commits into
mainfrom
codex/inspect-json-index-enable
Jul 6, 2026
Merged

Moskize91 merged 17 commits into
mainfrom
codex/inspect-json-index-enable

Conversation

@Moskize91

Copy link
Copy Markdown
Contributor

Summary

  • show request concurrency optimization hints before job concurrency hints
  • suggest request concurrency 8 when the current value is below the preferred range
  • share generation concurrency defaults between inspect and job queue estimates

Tests

  • pnpm exec vitest run test/cli/archive.test.ts test/cli/queue.test.ts
  • pnpm exec tsc -p tsconfig.json --noEmit
  • pnpm run lint

@coderabbitai

coderabbitai Bot commented Jul 6, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f81b7e66-12bf-457d-b342-18c8ebd11fca

📥 Commits

Reviewing files that changed from the base of the PR and between f8a9553 and 75b8679.

📒 Files selected for processing (17)
  • data/help/commands/uri.jinja
  • data/help/topics/format.jinja
  • data/help/topics/recipe.jinja
  • data/help/topics/uri.jinja
  • src/archive/query/archive-view.ts
  • src/cli/archive.ts
  • src/cli/args.ts
  • src/cli/help.ts
  • src/cli/queue.ts
  • src/cli/shell.ts
  • src/legacy-sdpub/upgrade.ts
  • src/wikipage/cache.ts
  • test/archive/query/archive-view.test.ts
  • test/cli/archive.test.ts
  • test/cli/args.test.ts
  • test/cli/shell.test.ts
  • test/gc/gc.test.ts
✅ Files skipped from review due to trivial changes (4)
  • test/cli/shell.test.ts
  • data/help/topics/format.jinja
  • data/help/commands/uri.jinja
  • data/help/topics/uri.jinja
🚧 Files skipped from review as they are similar to previous changes (8)
  • data/help/topics/recipe.jinja
  • src/cli/help.ts
  • src/legacy-sdpub/upgrade.ts
  • test/archive/query/archive-view.test.ts
  • src/wikipage/cache.ts
  • test/gc/gc.test.ts
  • test/cli/args.test.ts
  • test/cli/archive.test.ts

Summary by CodeRabbit

  • New Features

    • Added --reverse support for archive retrieval and evidence-related commands.
    • Introduced new index enable and index disable commands for searchable index management.
    • Added cleanup for expired Wikipedia page cache data.
  • Bug Fixes

    • Search and evidence results now follow document-flow order more consistently.
    • Improved result pagination and evidence previews when reverse ordering is used.
    • Expanded text search hits are now grouped more cleanly in results.
  • Documentation

    • Updated help text and readiness guidance to match the new command names and behaviors.
    • Clarified when --json is available for text vs. structured outputs.

Walkthrough

This PR renames archive index commands from build/clear to enable/disable, adds --reverse support for selected archive retrieval commands, and threads document-order-aware sorting through archive listing, evidence, related results, and continuation cursors. It adds document_order persistence to serial storage and TOC updates, refactors serial generation to write source fragments before topology building, introduces a wikipage cache GC job, and updates queue estimates, inspect reporting, help text, and tests to match the new flows.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as archive CLI
  participant Args as args parser
  participant ArchiveView as archive-view
  participant Stores as document serial store
  participant Cursor as continuation cursor

  CLI->>Args: parse --reverse / --query / index action
  Args-->>CLI: validated options and action
  CLI->>ArchiveView: list/get/evidence/related with order
  ArchiveView->>Stores: listDocumentOrders()
  Stores-->>ArchiveView: serialId -> documentOrder map
  ArchiveView-->>CLI: ordered results and evidence
  CLI->>Cursor: create/read continuation cursor with order
  Cursor-->>CLI: serialized cursor payload
Loading
sequenceDiagram
  participant Facade as chapter/import/digest
  participant Serial as SerialGeneration
  participant Document as document store
  participant Fragments as stored fragments

  Facade->>Document: writeSerialSource(stream)
  Document->>Fragments: persist fragments
  Facade->>Serial: buildTopologyInto(serialId, options)
  Serial->>Fragments: list stored fragments
  Fragments-->>Serial: batches with startSentenceIndex
  Serial-->>Facade: topology ready
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the required type(scope): subject format and matches the main change.
Description check ✅ Passed The description is clearly related to the concurrency hint and shared default changes in the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch codex/inspect-json-index-enable

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/archive/query/archive-view.ts (1)

2988-3074: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Thread documentOrders through evidence previews to avoid repeated queries.

hydrateFindHitEvidence fans out into preview helpers that each re-read document.serials.listDocumentOrders(). listArchiveCollection already computes that map once, so pass it through to createSourceEvidencePreview/filterAndSortSourceEvidenceRangesByFtsQuery instead of doing one DB query per hit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/archive/query/archive-view.ts` around lines 2988 - 3074,
hydrateFindHitEvidence is still causing repeated document order lookups inside
the evidence preview path. Thread the precomputed documentOrders map from
listArchiveCollection through hydrateFindHitEvidence into the preview helpers it
calls, especially createMentionLinkEvidencePreview and
createMentionEvidencePreview, and then pass it onward to
createSourceEvidencePreview/filterAndSortSourceEvidenceRangesByFtsQuery so they
stop re-reading document.serials.listDocumentOrders() per hit.
🧹 Nitpick comments (2)
src/facade/chapter-build.ts (1)

575-579: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

ensureCreated() runs after the first createDraft().

fragments.ensureCreated() (Line 579) is invoked only after serial.createDraft() (Line 575). If draft creation touches the fragments directory before it exists, this ordering is fragile. Consider ensuring the directory first.

♻️ Suggested reorder
   const fragments = new Fragments(documentPath);
   const serial = fragments.getSerial(chapterId);
+  await fragments.ensureCreated();
   let draft = await serial.createDraft();
   let draftWordsCount = 0;
   let hasSentences = false;
-
-  await fragments.ensureCreated();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/facade/chapter-build.ts` around lines 575 - 579, The draft setup in
chapter-build is ordering the fragment initialization too late:
`serial.createDraft()` runs before `fragments.ensureCreated()`, which can be
fragile if draft creation depends on the fragments directory existing. Update
the setup flow so `fragments.ensureCreated()` is called before
`serial.createDraft()`, keeping the rest of the draft initialization
(`draftWordsCount`, `hasSentences`, and `draft`) unchanged.
src/wikipage/cache.ts (1)

216-266: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Unconditional VACUUM on any expired-row deletion may be costly for the disambiguation cache.

VACUUM is triggered whenever expired > 0 (Line 242-253), regardless of how much data is deleted relative to total DB size. Since disambiguation_cache stores full page text, this table can grow large, and VACUUM rewrites the entire file — meaning even a single expired row on a large cache triggers a full-file rewrite on every GC pass. Consider gating VACUUM on a minimum freed-row ratio/size, or switching to SQLite's incremental vacuum mode to amortize this cost.

♻️ Example: only vacuum when a meaningful fraction of rows were removed
-    if (!context.dryRun && expired > 0) {
+    if (!context.dryRun && expired > 0 && expired / scanned >= 0.1) {
       await database.transaction(async () => {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/wikipage/cache.ts` around lines 216 - 266, The GC flow in
runWikipageCacheGc unconditionally runs VACUUM whenever any expired rows are
removed, which can cause expensive full-file rewrites for large wikipage caches.
Update the logic around countExpiredWikipageCacheRows, the delete transaction,
and the database.run("VACUUM") call so vacuuming only happens when a meaningful
amount of data was reclaimed (for example by row/size threshold) or use SQLite
incremental vacuum instead. Keep the existing delete behavior and result
accounting in GcContext/GcJobResult intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/cli/args.ts`:
- Around line 1010-1034: The archive reverse-flag validation is incomplete for
index URI parsing, allowing `wikg://<archive>/index get --reverse` to be
silently accepted and ignored. Update `parseArchiveIndexUriArguments()` to
explicitly validate `values.reverse` with `rejectArchiveBooleanFlag(action,
"--reverse", values.reverse, helpRoute)` so the flag is rejected for unsupported
index actions, and keep `rejectUnsupportedArchiveReverse()` aligned with the
same action handling in `rejectUnsupportedArchiveReverse()` and
`parseArchiveIndexUriArguments()`.

In `@src/wikipage/cache.ts`:
- Around line 255-261: The dry-run result in the cache GC path is reporting
actual freed bytes instead of candidate savings, so update the logic in the
cache cleanup flow around the `readFileSize`/return block to distinguish dry-run
from real execution. Use the same `removed`/`scanned` counters, but when dry-run
is enabled compute `freedBytes` as an estimate of the space that would be
reclaimed (for example by deriving it from the candidate removals rather than
comparing `beforeBytes` and `afterBytes`), while keeping the existing actual
before/after size calculation for non-dry-run runs. Make sure the returned
object from this method reports `freedBytes` consistently with the documented
candidate freed disk space behavior.

---

Outside diff comments:
In `@src/archive/query/archive-view.ts`:
- Around line 2988-3074: hydrateFindHitEvidence is still causing repeated
document order lookups inside the evidence preview path. Thread the precomputed
documentOrders map from listArchiveCollection through hydrateFindHitEvidence
into the preview helpers it calls, especially createMentionLinkEvidencePreview
and createMentionEvidencePreview, and then pass it onward to
createSourceEvidencePreview/filterAndSortSourceEvidenceRangesByFtsQuery so they
stop re-reading document.serials.listDocumentOrders() per hit.

---

Nitpick comments:
In `@src/facade/chapter-build.ts`:
- Around line 575-579: The draft setup in chapter-build is ordering the fragment
initialization too late: `serial.createDraft()` runs before
`fragments.ensureCreated()`, which can be fragile if draft creation depends on
the fragments directory existing. Update the setup flow so
`fragments.ensureCreated()` is called before `serial.createDraft()`, keeping the
rest of the draft initialization (`draftWordsCount`, `hasSentences`, and
`draft`) unchanged.

In `@src/wikipage/cache.ts`:
- Around line 216-266: The GC flow in runWikipageCacheGc unconditionally runs
VACUUM whenever any expired rows are removed, which can cause expensive
full-file rewrites for large wikipage caches. Update the logic around
countExpiredWikipageCacheRows, the delete transaction, and the
database.run("VACUUM") call so vacuuming only happens when a meaningful amount
of data was reclaimed (for example by row/size threshold) or use SQLite
incremental vacuum instead. Keep the existing delete behavior and result
accounting in GcContext/GcJobResult intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 814e90dc-7c06-40dc-8c45-45fdf72834dc

📥 Commits

Reviewing files that changed from the base of the PR and between ae7bcb4 and 433ada9.

📒 Files selected for processing (36)
  • data/help/commands/gc.jinja
  • data/help/commands/predicate.jinja
  • data/help/commands/uri.jinja
  • data/help/topics/format.jinja
  • data/help/topics/readiness.jinja
  • data/help/topics/recipe.jinja
  • data/help/topics/uri.jinja
  • src/archive/query/archive-view.ts
  • src/archive/query/continuation-cursor.ts
  • src/cli/archive-index.ts
  • src/cli/archive.ts
  • src/cli/args.ts
  • src/cli/generation-planning.ts
  • src/cli/help.ts
  • src/cli/main.ts
  • src/cli/queue.ts
  • src/document/document.ts
  • src/document/schema.ts
  • src/document/stores.ts
  • src/document/types.ts
  • src/facade/chapter-build.ts
  • src/facade/chapter.ts
  • src/facade/digest.ts
  • src/facade/import.ts
  • src/gc/runner.ts
  • src/serial.ts
  • src/wikipage/cache.ts
  • src/wikipage/index.ts
  • test/archive/query/archive-view.test.ts
  • test/cli/archive.test.ts
  • test/cli/args.test.ts
  • test/cli/main.test.ts
  • test/cli/queue.test.ts
  • test/facade/chapter-graph.test.ts
  • test/gc/gc.test.ts
  • test/serial.test.ts

Comment thread src/cli/args.ts
Comment thread src/wikipage/cache.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/legacy-sdpub/upgrade.ts (1)

947-958: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Use SQLite identifier quoting instead of JSON.stringify.

JSON.stringify(tableName) is not SQL identifier escaping, so this helper can generate malformed PRAGMA SQL for table names containing quotes. Keep the helper safe if it is reused beyond the current "serials" literal.

Proposed hardening
+function quoteSqlIdentifier(identifier: string): string {
+  return `"${identifier.replace(/"/g, '""')}"`;
+}
+
 async function listTableColumns(
   database: Database,
   tableName: string,
 ): Promise<ReadonlySet<string>> {
   const columns = await database.queryAll(
-    `PRAGMA table_info(${JSON.stringify(tableName)})`,
+    `PRAGMA table_info(${quoteSqlIdentifier(tableName)})`,
     undefined,
     (row) => String(row.name),
   );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/legacy-sdpub/upgrade.ts` around lines 947 - 958, The listTableColumns
helper currently builds PRAGMA SQL with JSON.stringify(tableName), which is not
valid SQLite identifier quoting and can break for table names containing quotes.
Update listTableColumns to use proper SQLite identifier escaping/quoting when
constructing the PRAGMA table_info query, keeping the logic in database.queryAll
safe even if tableName is not a fixed literal like "serials".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/legacy-sdpub/upgrade.ts`:
- Around line 947-958: The listTableColumns helper currently builds PRAGMA SQL
with JSON.stringify(tableName), which is not valid SQLite identifier quoting and
can break for table names containing quotes. Update listTableColumns to use
proper SQLite identifier escaping/quoting when constructing the PRAGMA
table_info query, keeping the logic in database.queryAll safe even if tableName
is not a fixed literal like "serials".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f4fd8518-3270-45e9-88a8-8972d94feb88

📥 Commits

Reviewing files that changed from the base of the PR and between 433ada9 and f8a9553.

📒 Files selected for processing (8)
  • src/archive/query/archive-view.ts
  • src/cli/archive.ts
  • src/cli/queue.ts
  • src/document/schema.ts
  • src/legacy-sdpub/upgrade.ts
  • test/cli/archive.test.ts
  • test/document/stores.test.ts
  • test/document/wiki-graph-schema.test.ts
💤 Files with no reviewable changes (1)
  • src/document/schema.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • test/cli/archive.test.ts
  • src/cli/archive.ts
  • src/archive/query/archive-view.ts

@Moskize91 Moskize91 changed the title Fix inspect concurrency performance hints fix(cli): improve inspect concurrency performance hints Jul 6, 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