Skip to content

feat: gate index/DB creation on consent (no .cartog.toml ⇒ no .cartog/)#144

Merged
jrollin merged 2 commits into
mainfrom
feat/index-creation-consent-gate
Jun 27, 2026
Merged

feat: gate index/DB creation on consent (no .cartog.toml ⇒ no .cartog/)#144
jrollin merged 2 commits into
mainfrom
feat/index-creation-consent-gate

Conversation

@jrollin

@jrollin jrollin commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Summary

cartog no longer creates a .cartog/ index for a config-less project on its own. A fresh, config-less repo stays untouched until the user opts in. Consent is any one of:

  1. a present .cartog.toml (cartog init);
  2. an existing index — once .cartog/db.sqlite (or legacy .cartog.db) exists, the project is opted in and steady-state updates keep working;
  3. CARTOG_AUTO_INIT set — indexes with in-memory defaults, writes no config file.

A Rejected (broken) .cartog.toml is not consent. An explicit cartog pull you typed is consent (it's an explicit action, like init).

This closes the gap where any command run on a config-less repo — index, serve, even a search — would materialize a .cartog/ nobody asked for.

Behavior when no consent signal holds

Surface Behavior
cartog index / rag index / watch Refuse (non-zero) with a hint; no .cartog/ created
cartog serve / serve --watch (MCP plugin default) Start degraded: no .cartog/, read tools return empty + hint, write tools refuse, cartog_stats reports "degraded": true. With --watch, the watcher pre-builds the index the moment cartog init runs (or a DB / CARTOG_AUTO_INIT appears); the running server stays degraded until relaunch (no live swap)
Read commands & read MCP tools Empty results + hint; no .cartog/ created
init / config / doctor / completions / manpage / self * Never gated
pull / push Not gated — invoking them is the opt-in; pull materializes .cartog/ because that's its job

Installation / editor wiring (install, ide, the plugin MCP entry) are independent of the gate — binary + MCP config files only.

Implementation

  • cartog-db: Database::open_existing (no create_dir_all; DbError::NotFound when absent).
  • config: pure allow_index_creation(db_path, config_present) + CARTOG_AUTO_INIT; evaluated once in main.rs, threaded as allow_create into run_serverWatchConfig/CartogServer (mirrors walk_filter/redact).
  • CLI: write commands refuse before dispatch; reads fall back to open_memory().
  • MCP: degraded serve, refuse_if_degraded gates the 2 write tools, cartog_stats.degraded, staleness banners suppressed while degraded. A read-only secondary against an absent DB also starts degraded (so the second client in a multi-window setup never crashes).
  • watch: degraded watcher pre-builds on consent; watcher_consents walks cwd→git-root for .cartog.toml (subdir-launched serve still pre-builds on a git-root init).
  • doctor: "database not found" hint is consent-aware (points at cartog init).
  • hook (ensure_indexed.sh): gate = toml-walk-up OR db-exists OR CARTOG_AUTO_INIT.
  • docs + site: consent-gate section, CARTOG_AUTO_INIT env var, serve-degraded note, push/pull clarification, SKILL.md fresh-repo rewrite.

Review

Reviewed scenario-by-scenario (MCP no-config / legacy-DB / with-config / config-added-mid-session) and via an adversarial multi-angle code review. All 7 confirmed findings fixed (flaky test, 2nd-peer degraded attach, doctor hint, pull/docs contradiction, hook walk-up, degraded stale-banner) plus cleanups.

Tests

cartog-db open_existing; config predicate (serialized env tests); CLI integration (refuse / no-create read / AUTO_INIT / after-init / existing-DB / degraded-serve contrast); MCP degraded (write-tool refusal, stats, read-only-secondary-against-absent-DB); watcher consent (.cartog.toml trigger, git-root walk-up, stops-at-git-root); doctor consent-aware hint; hook db-exists + intermediate-dir branches.

Gates: cargo fmt, clippy (default + --no-default-features), cargo test --workspace + --no-default-features, make check-skill — all green. End-to-end verified with the real binary (refuse/init/AUTO_INIT/existing-DB, degraded serve + mid-session init pre-build, multi-peer degraded attach).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added opt-in support for first-time indexing in config-less projects via CARTOG_AUTO_INIT.
    • cartog serve can now start in a degraded mode when no index exists, still allowing reads and reporting status clearly.
  • Bug Fixes

    • Prevents creating .cartog/ unexpectedly for uninitialized projects.
    • Read commands now return empty results instead of failing when no index exists.
    • Watch mode now waits for consent/config before indexing.
  • Documentation

    • Updated CLI, config, troubleshooting, and usage docs to explain the new consent flow.

cartog no longer creates a .cartog/ index for a config-less project on its own.
Consent is any one of: a present .cartog.toml, an existing index (Branch 1), or
CARTOG_AUTO_INIT (indexes with defaults, writes no config). A Rejected TOML is
not consent. An explicit `cartog pull` you typed is itself consent.

- cartog-db: add Database::open_existing (no create_dir_all; DbError::NotFound
  when absent). open()/open_memory() unchanged.
- config: pure allow_index_creation(db_path, config_present) predicate;
  CARTOG_AUTO_INIT env. Evaluated once in main.rs, threaded as allow_create into
  run_server -> WatchConfig/CartogServer (mirrors walk_filter/redact).
- CLI: index / rag index / watch refuse before dispatch (is_gated_write_command
  = indexes_with_config minus Serve, so the set is defined once). Write commands
  use open_db_create; reads fall back to open_memory() via open_db.
- MCP: serve starts degraded when consent is absent + no DB (empty in-memory DB,
  no .cartog/); refuse_if_degraded gates the 2 write tools; cartog_stats reports
  degraded (serialized only when true) + a banner; staleness banners suppressed
  while degraded. A read-only secondary against an absent DB (its primary is
  degraded) also starts degraded instead of failing open_readonly, so the
  serve-for-all-clients flow never leaves a second client without a server.
- watch: WatchConfig.allow_create; stays degraded when unmet and pre-builds the
  index once consent appears. watcher_consents re-checks live each pass and
  walks up from the watch root to the git root for a .cartog.toml (subdir-
  launched serve still pre-builds on a git-root init). No live swap.
- doctor: the "database not found" hint is consent-aware — points at cartog init
  when no config, since cartog index would now refuse.
- hook: ensure_indexed.sh gate = _has_toml OR db-file-exists OR CARTOG_AUTO_INIT,
  with a full cwd->git-root walk-up for .cartog.toml (intermediate-dir configs).
- docs + site: consent-gate section, CARTOG_AUTO_INIT env var, serve degraded
  note, push/pull clarified as explicit-action opt-in (not "never gated"),
  SKILL.md fresh-repo rewrite.

Tests: cartog-db open_existing, config predicate (serialized env tests), CLI
integration (incl. degraded-serve contrast), MCP degraded (incl. read-only
secondary against absent DB), watcher consent (.cartog.toml trigger + git-root
walk-up + stops-at-git-root), doctor consent-aware hint, hook db-exists +
intermediate-dir walk-up branches.
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jrollin, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 30 minutes and 1 second. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c16cb895-67fb-4518-bb1f-535f06d91eb9

📥 Commits

Reviewing files that changed from the base of the PR and between d78d148 and b3f9740.

📒 Files selected for processing (13)
  • crates/cartog-db/src/store/lifecycle.rs
  • crates/cartog-db/src/tests/errors.rs
  • crates/cartog-mcp/src/single_writer.rs
  • crates/cartog-mcp/src/tests/degraded.rs
  • crates/cartog-watch/src/lib.rs
  • crates/cartog/src/commands/doctor.rs
  • crates/cartog/src/commands/manage.rs
  • crates/cartog/src/commands/shared.rs
  • crates/cartog/src/config/load.rs
  • crates/cartog/tests/consent_gate_test.rs
  • crates/cartog/tests/remote_integration.rs
  • skills/cartog/SKILL.md
  • skills/cartog/scripts/ensure_indexed.sh
📝 Walkthrough

Walkthrough

Adds an index-creation consent gate: cartog will not create a .cartog/ directory for config-less, un-indexed projects unless .cartog.toml exists, the DB file already exists, or CARTOG_AUTO_INIT is non-empty. Write CLI commands refuse; cartog serve starts degraded with empty reads and refused write tools; the watcher polls until consent appears.

Changes

Index-creation consent gate

Layer / File(s) Summary
DbError::NotFound and Database::open_existing
crates/cartog-db/src/lib.rs, crates/cartog-db/src/store/lifecycle.rs, crates/cartog-db/src/tests/errors.rs
Adds DbError::NotFound { path } variant and Database::open_existing that returns it for absent DB files without creating .cartog/; refactors open to share an open_no_create_dir helper; four new tests cover all edge cases.
allow_index_creation predicate and AUTO_INIT_ENV
crates/cartog/src/config/load.rs, crates/cartog/src/config/tests/load.rs
Adds AUTO_INIT_ENV constant, allow_index_creation(db_path, config_present), and auto_init_enabled() helper with tests covering all allow/deny combinations including empty-string env var and WAL-only stray file.
open_db / open_db_create split in CLI commands
crates/cartog/src/commands/shared.rs, crates/cartog/src/commands/index.rs, crates/cartog/src/commands/rag.rs
open_db uses open_existing with in-memory fallback on NotFound; new open_db_create calls Database::open for write paths. cmd_index and cmd_rag_index switched to open_db_create. Empty-index hint and unit tests updated.
Consent gate wiring in main, cmd_watch, cmd_doctor
crates/cartog/src/main.rs, crates/cartog/src/commands/manage.rs, crates/cartog/src/commands/doctor.rs
main adds is_gated_write_command, computes allow_create, aborts gated write commands when consent is absent, and threads allow_create into cmd_watch and run_server. cmd_doctor hint text now varies by config_present.
CartogServer degraded mode and refuse_if_degraded
crates/cartog-mcp/src/lib.rs, crates/cartog-mcp/src/single_writer.rs
Adds degraded: bool field, updates new to accept allow_create and start in-memory with degraded=true when consent is absent, updates new_read_only similarly, suppresses stale-snapshot banners, adds is_degraded/refuse_if_degraded helpers, and threads allow_create through run_server.
Tool-level degraded gates and StatsResult
crates/cartog-mcp/src/tools/index.rs, crates/cartog-mcp/src/tools/search.rs, crates/cartog-mcp/src/types.rs
cartog_index and cartog_rag_index call refuse_if_degraded early. cartog_stats includes a degraded field and returns a "no index yet" banner when degraded. StatsResult gains degraded: bool with skip-serialize-if-false.
WatchConfig allow_create and consent-wait loop
crates/cartog-watch/Cargo.toml, crates/cartog-watch/src/lib.rs
Adds allow_create to WatchConfig, implements watcher_consents, cartog_toml_at_or_above, wait_for_consent, and install_root_watcher. watch_loop enters a degraded wait when consent is absent. Adds serial_test dev-dep and unit/integration tests.
MCP degraded integration tests
crates/cartog-mcp/src/tests/degraded.rs, crates/cartog-mcp/src/tests/mod.rs, crates/cartog-mcp/src/tests/schema.rs
New test file verifies write-tool refusal, non-degraded primary not refusing, cartog_stats degraded output, read-only absent-DB degraded start, and no-.cartog/-creation assertions. Schema test updated for degraded=false omission.
CLI consent gate integration tests
crates/cartog/tests/consent_gate_test.rs
Adds Sandbox harness and end-to-end tests covering refusal without consent, CARTOG_AUTO_INIT bypass, cartog init progression, serve degraded/consented behavior, and existing-DB-grants-consent.
ensure_indexed.sh walk-up and SKILL.md guidance
skills/cartog/scripts/ensure_indexed.sh, skills/cartog/tests/test_ensure_indexed.sh, skills/cartog/SKILL.md
Adds _find_cartog_toml ancestor walk-up helper, updates the foreground consent gate to use it, updates SKILL.md fresh-repo/SessionStart guidance, and adds two shell tests for existing-DB indexing and intermediate-dir walk-up.
Documentation
AGENTS.md, docs/reference/cli.md, docs/reference/config.md, docs/troubleshooting.md, docs/usage.md, site/src/pages/usage.astro
Documents the consent gate, CARTOG_AUTO_INIT env var, degraded serve behavior, per-command refusal/empty-result semantics, and troubleshooting guidance.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant main as cartog main
    participant config as config::allow_index_creation
    participant CartogServer
    participant Database

    User->>main: cartog index . (no .cartog.toml, no DB)
    main->>config: allow_index_creation(db_path, false)
    config-->>main: false
    main-->>User: error: run cartog init or set CARTOG_AUTO_INIT=1

    User->>main: cartog serve (no .cartog.toml, no DB)
    main->>CartogServer: new(allow_create=false)
    CartogServer->>Database: open_existing(path)
    Database-->>CartogServer: DbError::NotFound
    CartogServer->>Database: open_memory()
    CartogServer-->>main: Server{degraded=true}
    main-->>User: MCP server running (degraded)
    User->>CartogServer: cartog_index tool call
    CartogServer-->>User: error: no index yet, run cartog init
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • jrollin/cartog#37: Overlaps on Database::open/DB path semantics and when the .cartog/ parent directory gets materialized.
  • jrollin/cartog#55: Both modify cartog-mcp server initialization and which write tools are gated in non-primary/degraded scenarios.
  • jrollin/cartog#62: Both modify ensure_indexed.sh and its tests around the fresh-repo .cartog.toml consent-gate logic.

Poem

🐇 Hop, hop — no sneaky dirs today!
Without your blessing, I shall not stay.
.cartog.toml or a DB in place,
CARTOG_AUTO_INIT gives consent with grace.
Else I sit degraded, returning empty replies,
Until cartog init lets indexes rise! 🌱

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: consent-gated index/database creation for config-less projects.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/index-creation-consent-gate

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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: 6

🧹 Nitpick comments (5)
crates/cartog-mcp/src/tests/degraded.rs (1)

116-128: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

This test never exercises the allow_create=false startup branch.

It only rechecks Database::open_existing(...)=NotFound, so crates/cartog-mcp/src/lib.rs:948-1002 could regress while this still passes. Please either drive the real CartogServer::new(..., allow_create=false) path through an injectable test provider, or rename the test to match its narrower DB-layer contract.

🤖 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 `@crates/cartog-mcp/src/tests/degraded.rs` around lines 116 - 128, This test
only checks Database::open_existing and does not cover the real
allow_create=false startup path, so regressions in CartogServer::new can slip
through. Update the test to exercise CartogServer::new with allow_create=false
via the injectable test provider used by degraded startup, and assert the server
starts degraded without creating .cartog/; if you keep the current DB-only
check, rename the test to reflect that narrower contract.
crates/cartog/src/config/load.rs (1)

344-346: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add #[must_use] to allow_index_creation.

This predicate is the consent gate; dropping its return value would silently skip the opt-in check.

As per coding guidelines, "Put #[must_use] on builder methods returning Self and on any function whose ignored return value would always be a bug."

♻️ Suggested change
+#[must_use]
 pub fn allow_index_creation(db_path: &Path, config_present: bool) -> bool {
     config_present || db_path.exists() || auto_init_enabled()
 }
🤖 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 `@crates/cartog/src/config/load.rs` around lines 344 - 346, Add #[must_use] to
allow_index_creation in the config load module so callers cannot accidentally
ignore the consent-gate result; update the function signature for
allow_index_creation(db_path, config_present) accordingly and keep its predicate
logic unchanged.

Source: Coding guidelines

crates/cartog-watch/src/lib.rs (1)

89-96: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Mark WatchConfig::new as #[must_use].

Dropping a freshly-constructed config is always a caller bug, and this constructor is exactly the kind of Self-returning API the guideline calls out.

As per coding guidelines, "Put #[must_use] on builder methods returning Self and on any function whose ignored return value would always be a bug."

♻️ Suggested change
+#[must_use]
 pub fn new(root: PathBuf) -> Self {
     Self {
         root,
🤖 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 `@crates/cartog-watch/src/lib.rs` around lines 89 - 96, `WatchConfig::new`
returns a fully constructed `Self` and should not be silently ignored, so add
`#[must_use]` to the constructor to match the guideline for builder-like APIs.
Apply the attribute directly to `WatchConfig::new` in the `impl WatchConfig`
block so callers are warned when they drop the returned config.

Source: Coding guidelines

crates/cartog-mcp/src/single_writer.rs (1)

150-160: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add rustdoc for run_server.

This public entrypoint now exposes the consent gate through allow_create, but it still has no /// docs describing degraded startup and watcher behavior under that flag. As per coding guidelines, **/*.rs: Add /// doc comments to all public functions.

🤖 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 `@crates/cartog-mcp/src/single_writer.rs` around lines 150 - 160, The public
entrypoint run_server is missing rustdoc, including the new allow_create consent
gate behavior. Add /// documentation directly above run_server describing its
purpose, the meaning of allow_create, and how startup/watch behavior is degraded
when creation is disallowed. Also ensure any other public items in
single_writer.rs follow the same /// doc-comment requirement.

Source: Coding guidelines

crates/cartog/src/commands/manage.rs (1)

345-355: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add rustdoc for cmd_watch.

This public function now exposes the consent gate via allow_create, but it still has no /// docs explaining when watch may create .cartog/ versus stay consent-blocked/degraded. As per coding guidelines, **/*.rs: Add /// doc comments to all public functions.

🤖 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 `@crates/cartog/src/commands/manage.rs` around lines 345 - 355, Add rustdoc
comments to the public cmd_watch function, since it currently has no ///
documentation. Describe the watch command’s behavior and explicitly note how
allow_create controls whether it may create .cartog/ or remain
consent-blocked/degraded, so the public API matches the crate’s doc
requirements.

Source: Coding guidelines

🤖 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 `@crates/cartog-db/src/store/lifecycle.rs`:
- Around line 43-48: open_existing currently relies on db_path.exists() before
calling open_no_create_dir, which can race and still allow creating a new
database; update open_existing in lifecycle::Lifecycle to use open_with_flags
without SQLITE_OPEN_CREATE so it performs a true non-creating open, and keep the
shared migrate/setup path only after that open succeeds. Ensure the existing
open_no_create_dir/open_with_flags flow is used so a missing or removed db_path
returns NotFound instead of creating a fresh DB.

In `@crates/cartog/src/commands/doctor.rs`:
- Around line 470-475: The missing-database hint in doctor is still using
config_present instead of the real consent decision, so it can suggest cartog
init even when cartog index is already allowed via CARTOG_AUTO_INIT. Update the
consent plumbing in doctor.rs by threading the full predicate from
allow_index_creation(...) / auto_init_enabled() into check_database, and use
that value instead of the current config_present-only check so check_git_repo,
check_config, and check_database stay aligned with runtime behavior.

In `@crates/cartog/src/commands/shared.rs`:
- Around line 283-290: Strengthen open_db’s existing-index test by verifying it
reopens the on-disk database instead of falling back to open_memory(). In
open_db_opens_an_existing_index, after creating the real DB with Database::open,
insert a sentinel row before calling open_db, then assert that the reopened
Database still contains that row and not just that it is empty or that db.sqlite
exists. This should be done in the open_db test helper path in
crates/cartog/src/commands/shared.rs.

In `@crates/cartog/tests/consent_gate_test.rs`:
- Around line 103-115: The fresh-repo read-command test in
read_command_no_create_on_fresh_repo only checks exit status and that .cartog is
not created, so it should also assert the empty-index hint is returned. Update
this test to inspect the command output from sb.cmd(&["search", "foo"]) and
verify the user-facing empty-index guidance appears alongside the empty result,
using the existing stderr/stdout helpers and keeping the assertions tied to
read_command_no_create_on_fresh_repo.

In `@skills/cartog/scripts/ensure_indexed.sh`:
- Around line 356-368: The _find_cartog_toml helper only treats .git directories
as the repo boundary, so it can walk past git worktrees and submodules where
.git is a file. Update the boundary check in _find_cartog_toml to stop on either
a .git directory or a .git file before continuing upward, while keeping the
existing .cartog.toml lookup behavior intact.

In `@skills/cartog/SKILL.md`:
- Around line 44-46: The restart guidance is too unconditional and conflicts
with the degraded-server flow described in this section. Update the later “After
indexing…” sentence in the Cartog SKILL.md guidance to distinguish normal
attached-server behavior from the degraded case, and make it clear that only
servers already using the on-disk DB pick up new symbols on the next call while
a degraded MCP server still requires a relaunch to load the freshly built index.

---

Nitpick comments:
In `@crates/cartog-mcp/src/single_writer.rs`:
- Around line 150-160: The public entrypoint run_server is missing rustdoc,
including the new allow_create consent gate behavior. Add /// documentation
directly above run_server describing its purpose, the meaning of allow_create,
and how startup/watch behavior is degraded when creation is disallowed. Also
ensure any other public items in single_writer.rs follow the same ///
doc-comment requirement.

In `@crates/cartog-mcp/src/tests/degraded.rs`:
- Around line 116-128: This test only checks Database::open_existing and does
not cover the real allow_create=false startup path, so regressions in
CartogServer::new can slip through. Update the test to exercise
CartogServer::new with allow_create=false via the injectable test provider used
by degraded startup, and assert the server starts degraded without creating
.cartog/; if you keep the current DB-only check, rename the test to reflect that
narrower contract.

In `@crates/cartog-watch/src/lib.rs`:
- Around line 89-96: `WatchConfig::new` returns a fully constructed `Self` and
should not be silently ignored, so add `#[must_use]` to the constructor to match
the guideline for builder-like APIs. Apply the attribute directly to
`WatchConfig::new` in the `impl WatchConfig` block so callers are warned when
they drop the returned config.

In `@crates/cartog/src/commands/manage.rs`:
- Around line 345-355: Add rustdoc comments to the public cmd_watch function,
since it currently has no /// documentation. Describe the watch command’s
behavior and explicitly note how allow_create controls whether it may create
.cartog/ or remain consent-blocked/degraded, so the public API matches the
crate’s doc requirements.

In `@crates/cartog/src/config/load.rs`:
- Around line 344-346: Add #[must_use] to allow_index_creation in the config
load module so callers cannot accidentally ignore the consent-gate result;
update the function signature for allow_index_creation(db_path, config_present)
accordingly and keep its predicate logic unchanged.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 89eeb601-5698-4fec-8ce4-448356c968ae

📥 Commits

Reviewing files that changed from the base of the PR and between 251623f and d78d148.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (31)
  • AGENTS.md
  • crates/cartog-db/src/lib.rs
  • crates/cartog-db/src/store/lifecycle.rs
  • crates/cartog-db/src/tests/errors.rs
  • crates/cartog-mcp/src/lib.rs
  • crates/cartog-mcp/src/single_writer.rs
  • crates/cartog-mcp/src/tests/degraded.rs
  • crates/cartog-mcp/src/tests/mod.rs
  • crates/cartog-mcp/src/tests/schema.rs
  • crates/cartog-mcp/src/tools/index.rs
  • crates/cartog-mcp/src/tools/search.rs
  • crates/cartog-mcp/src/types.rs
  • crates/cartog-watch/Cargo.toml
  • crates/cartog-watch/src/lib.rs
  • crates/cartog/src/commands/doctor.rs
  • crates/cartog/src/commands/index.rs
  • crates/cartog/src/commands/manage.rs
  • crates/cartog/src/commands/rag.rs
  • crates/cartog/src/commands/shared.rs
  • crates/cartog/src/config/load.rs
  • crates/cartog/src/config/tests/load.rs
  • crates/cartog/src/main.rs
  • crates/cartog/tests/consent_gate_test.rs
  • docs/reference/cli.md
  • docs/reference/config.md
  • docs/troubleshooting.md
  • docs/usage.md
  • site/src/pages/usage.astro
  • skills/cartog/SKILL.md
  • skills/cartog/scripts/ensure_indexed.sh
  • skills/cartog/tests/test_ensure_indexed.sh

Comment thread crates/cartog-db/src/store/lifecycle.rs Outdated
Comment thread crates/cartog/src/commands/doctor.rs Outdated
Comment thread crates/cartog/src/commands/shared.rs Outdated
Comment thread crates/cartog/tests/consent_gate_test.rs
Comment thread skills/cartog/scripts/ensure_indexed.sh
Comment thread skills/cartog/SKILL.md
- CI: build_minimal_index ran `cartog index` on a config-less repo; the consent
  gate refused it. Set CARTOG_AUTO_INIT=1 (the documented config-less opt-in)
  for that fixture index. Fixes the red Coverage / Test-Remote jobs.
- cartog-db: open_existing now does a true non-creating open
  (SQLITE_OPEN_READ_WRITE, no CREATE) so a file vanishing between any pre-check
  and the open errors as NotFound instead of materializing a fresh DB (closes a
  TOCTOU window). Shared post-open setup factored into setup_opened_conn.
- doctor: the "database not found" hint now uses the full allow_index_creation
  predicate, so it suggests `cartog index` (not init) when CARTOG_AUTO_INIT
  alone already permits indexing.
- hook: _find_cartog_toml stops on a `.git` file too (worktrees/submodules),
  matching the binary's local_config_path.
- SKILL.md: clarified that only an attached (on-disk) MCP server picks up new
  symbols on the next call; a degraded server needs a relaunch.
- docs: run_server / cmd_watch rustdoc note allow_create; SERVE_LOCK_SLOT
  documented; #[must_use] on allow_index_creation and WatchConfig::new.

Tests: open_existing no-create-when-parent-dir-exists (TOCTOU); open_db
existing-index reopen asserted via a sentinel symbol; fresh-repo read asserts
the empty-index hint; degraded open_existing test renamed to its narrow contract
(full path covered by the read-only-secondary test).
@codecov

codecov Bot commented Jun 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.13953% with 51 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.03%. Comparing base (251623f) to head (b3f9740).

Files with missing lines Patch % Lines
crates/cartog-mcp/src/lib.rs 71.05% 22 Missing ⚠️
crates/cartog-watch/src/lib.rs 94.58% 11 Missing ⚠️
crates/cartog-db/src/store/lifecycle.rs 84.84% 5 Missing ⚠️
crates/cartog-mcp/src/tools/index.rs 33.33% 4 Missing ⚠️
crates/cartog/src/commands/doctor.rs 85.71% 3 Missing ⚠️
crates/cartog/src/commands/manage.rs 0.00% 2 Missing ⚠️
crates/cartog-mcp/src/single_writer.rs 88.88% 1 Missing ⚠️
crates/cartog/src/commands/rag.rs 0.00% 1 Missing ⚠️
crates/cartog/src/commands/shared.rs 97.95% 1 Missing ⚠️
crates/cartog/src/main.rs 90.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #144      +/-   ##
==========================================
+ Coverage   87.59%   88.03%   +0.44%     
==========================================
  Files          96       96              
  Lines       31790    32200     +410     
==========================================
+ Hits        27846    28347     +501     
+ Misses       3944     3853      -91     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jrollin jrollin merged commit 890d15b into main Jun 27, 2026
16 checks passed
@jrollin jrollin deleted the feat/index-creation-consent-gate branch June 27, 2026 19:51
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