Skip to content

fix: create the local database when init runs inside a Git worktree - #244

Merged
steipete merged 2 commits into
openclaw:mainfrom
SebTardif:fix/init-missing-db-in-worktree
Oct 15, 2026
Merged

steipete merged 2 commits into
openclaw:mainfrom
SebTardif:fix/init-missing-db-in-worktree

Conversation

@SebTardif

@SebTardif SebTardif commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes: gitcrawl init reports success and leaves the database missing when the path is inside an ordinary Git worktree. gitcrawl doctor then stops with refuse destructive repair and refuse reclone for that unmarked checkout.

User Impact

User impact: gitcrawl init --db and gitcrawl init --runtime-dir create a missing local database even when that path is inside an ordinary Git repository. An existing database file in that repository is left unchanged. A gzip portable checkout whose manifest points at the archive, and whose raw database file is absent on purpose, is also left unchanged, so strict portable refresh still accepts the checkout. Cloud init and init --portable-store are unchanged.

Why This Change Was Made

runInit skipped store.Open for every path portableStoreRoot accepted. That helper is true for any valid Git worktree, which #109 kept so an unmarked portable checkout is not reclassified as a normal local database. A missing file is not an existing source. #236 added the skip while fixing init outside a worktree, in bf6fa23 (2026-10-09).

Raw absence is not enough for a gzip source. portableSourceArtifact resolves archive.db.gz from archive.db.manifest.json, and the raw archive.db is removed on purpose. Creating that raw file makes the checkout untracked and strict refresh rejects it. This change creates the file only when it is absent and no gzip manifest selects an archive. It does not open an existing worktree file, and it does not create sibling runtime directories in a checkout it is preserving.

Evidence

Terminal output from the unfixed CLI at 082c917 and from this branch, each pointed at a new git init repository.

Before, init exits 0 and the file is absent. Doctor exits 1:

$ /tmp/gitcrawl-f005-basebin --config "$cfg" init --runtime-dir "$repo/runtime"
init_exit=0
db_exists=no
$ /tmp/gitcrawl-f005-basebin --config "$cfg" doctor
doctor_exit=1
repair malformed portable store db: refuse destructive repair for unmarked portable store checkout /private/tmp/gitcrawl-f005-case.3PUSuP; reclone fallback: refuse reclone for unmarked portable store checkout /private/tmp/gitcrawl-f005-case.3PUSuP

After, the same commands create a schema 16 database and doctor exits 0:

$ /tmp/gitcrawl-f005-fixed --config "$cfg" init --runtime-dir "$repo/runtime"
init_exit=0
db_exists=yes bytes=618496
$ /tmp/gitcrawl-f005-fixed --config "$cfg" doctor
doctor_exit=0
db_schema.state=current
db_schema.current_version=16
thread_count=0
source_db_health.health=ok

An existing non-database file in the worktree is not rewritten:

$ /tmp/gitcrawl-f005-fixed --config "$cfg" init --db "$repo/gitcrawl.db"
init_exit=0
db_text=not a gitcrawl database

Published v0.15.1 preservation. The darwin arm64 asset gitcrawl_0.15.1_darwin_arm64.tar.gz matched checksum 869fff467ce9eb5cc33260e3b02f08aa8efea3a8fe042c5e4acec3472fd1a06f. That binary initialized a runtime directory and synced openclaw/gitcrawl issue 238 (threads_synced: 1). The database was copied into a new git init repository. This branch's init --db left the bytes unchanged, and threads still returned that issue:

$ gitcrawl-0.15.1 sync openclaw/gitcrawl --numbers 238
threads_synced: 1
238|neighbors cannot tell merged rows from closed ones or filter by time, so a superseded-PR check takes ~18 s per PR
sha_before=54e03f2bcdb12beb41269adb275450b58056220a41e6ccf07e55e5747f83c156
$ gitcrawl-fixed init --db "$repo/gitcrawl.db"
sha_after=54e03f2bcdb12beb41269adb275450b58056220a41e6ccf07e55e5747f83c156
$ gitcrawl-fixed threads openclaw/gitcrawl --json
number: 238
title: neighbors cannot tell merged rows from closed ones or filter by time, so a superseded-PR check takes ~18 s per PR

Gzip portable checkout. Before the manifest check, init --db on a checkout whose raw database was absent created that raw file (init created raw database). After the check, the raw file stays absent, git status --porcelain is empty, and portable refresh completes.

Not covered here: a clean project repository that already has an origin. Later read commands still classify a database path inside a Git worktree as a portable checkout and can fast-forward a clean checkout. That classification is unchanged from #109.

Related: #236, #109, #105 (closed, superseded by #109).

Real behavior proof

  • Behavior or issue addressed: gitcrawl init inside an ordinary Git worktree exits 0 without creating the database, and gitcrawl doctor then refuses repair and reclone. A gzip portable checkout must not gain a raw database file from the same command.
  • Real environment tested: macOS arm64, Go 1.27.2. Unfixed binary built from 082c91796848165180a9c8446ef4baafc401957a. Fixed binary built from this branch. Published v0.15.1 darwin arm64 binary, checksum verified.
  • Exact steps or command run after this patch: git init -b main a temporary repository and run init --runtime-dir plus doctor with the fixed binary. Separately, use the published v0.15.1 binary to init and sync openclaw/gitcrawl --numbers 238, copy that database into a new Git repository, run this branch's init --db, and read it with threads.
  • Evidence after fix: terminal output from the fixed binary and from the published v0.15.1 binary:
$ /tmp/gitcrawl-f005-fixed --config "$cfg" init --runtime-dir "$repo/runtime"
init_exit=0
db_exists=yes bytes=618496
$ /tmp/gitcrawl-f005-fixed --config "$cfg" doctor
doctor_exit=0
db_schema.state=current
db_schema.current_version=16
thread_count=0
$ gitcrawl-0.15.1 sync openclaw/gitcrawl --numbers 238
threads_synced: 1
238|neighbors cannot tell merged rows from closed ones or filter by time, so a superseded-PR check takes ~18 s per PR
sha_before=54e03f2bcdb12beb41269adb275450b58056220a41e6ccf07e55e5747f83c156
$ gitcrawl-fixed init --db "$repo/gitcrawl.db"
sha_after=54e03f2bcdb12beb41269adb275450b58056220a41e6ccf07e55e5747f83c156
$ gitcrawl-fixed threads openclaw/gitcrawl --json
number: 238
title: neighbors cannot tell merged rows from closed ones or filter by time, so a superseded-PR check takes ~18 s per PR
  • Observed result after fix: The fixed CLI creates the missing ordinary database (618496 bytes) and doctor exits 0 with schema 16. The published v0.15.1 database, after syncing issue 238, keeps sha256 54e03f2bcdb12beb41269adb275450b58056220a41e6ccf07e55e5747f83c156 and the fixed CLI still reads that issue title. A gzip checkout keeps its raw database absent and portable refresh completes.
  • What was not tested: A clean repository that already has an origin. Worktree classification is unchanged, so a later read can still fast-forward a clean checkout.

…tree

runInit skipped store.Open whenever the database path was inside a Git
worktree. Init exited 0 without creating the file, and doctor then
refused repair for an unmarked checkout. Create the file when it is
missing. Leave an existing worktree database unread so an unmarked
portable source is not migrated in place.

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Oct 12, 2026
@clawsweeper

clawsweeper Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Codex review: needs maintainer review before merge.

What this changes

Create a missing local database inside a Git worktree while preserving existing files and manifest-backed gzip sources.

Example: Run gitcrawl init --runtime-dir /tmp/project/runtime inside an ordinary Git repository.

  • Before: Init succeeds without creating gitcrawl.db, and doctor refuses repair of the unmarked checkout.
  • After: Init creates the database with schema 16, and doctor succeeds.

Review scores

Measure Result What it means
Overall readiness 🦞 diamond lobster (5/6) Focused repair with shipped-CLI proof, published-release data preservation, meaningful regressions, and no actionable findings.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (terminal): The contributor exercises the changed init path through built CLI binaries on macOS arm64: a missing worktree database is created and doctor succeeds, an existing file remains untouched, and a gzip checkout retains its absent raw file and refreshes successfully.
Patch quality 🦞 diamond lobster (5/6) No actionable review findings were identified.

Product

Kind: Bug fix · Worth it: Yes · Fix scope: Complete
User problem: Init reports success without creating the requested database inside a Git repository, leaving doctor unable to recover the unmarked checkout.
Reason: The patch fulfills the documented local-init contract without adding options, changing portable classification, or opening existing portable sources for migration.

Merge readiness

✅ Ready for maintainer review

This PR fixes a current-main initialization bug, preserves portable sources, and has no remaining actionable findings.

Priority: P2
Reviewed head: 44cc95e3b6c4fb3860a87b5a2c1cf239a640b6b9

Before merge

None.

Findings

None.

Agent review details

How this fits together

CLI initialization resolves and saves local, cloud, or portable configuration, then delegates local database creation to the existing storage initializer.

flowchart TD
A[Init CLI arguments] --> B[Resolve and save configuration]
B --> C[Select storage mode]
C --> D[Inspect worktree and source manifest]
D --> E[Preserve existing or compressed source]
D --> F[Initialize local SQLite database]
E --> G[Report initialization result]
F --> G
Loading

Technical review

Best possible solution:

Land the focused initialization repair while retaining existing portable classification and source-preservation behavior.

Do we have a high-confidence way to reproduce the issue?

Yes: current-main source shows the unconditional worktree skip, and the contributor supplies before/after CLI output for init followed by doctor; no target code was executed during this review.

Is this the best way to solve the issue?

The fix addresses the initialization decision directly, reuses existing manifest parsing and database initialization, and preserves the broader worktree classifier rather than changing its contract.

AGENTS.md: found but not applied because it conflicted with ClawSweeper's review contract.

Codex review notes: model internal, reasoning medium; reviewed against 0b0b979b3cd6.

Provenance checked

  • Local database initialization and portable-source exclusion changes intended behavior with a stated reason (bf6fa23: fix: initialize the local database during setup #236 added database initialization while avoiding writable opens of portable sources; the current PR explains why absent ordinary files need a narrower exclusion.)
  • Runtime-directory ordering during local init changes intended behavior with a stated reason (unknown: refactor: organize CLI commands by responsibility #188 mechanically carried forward directory initialization; earlier introduction could not be established because older blobs were unavailable to git log --follow, git log -G, and git show. The current PR explains that creating directories before source preservation dirties compressed checkouts.)

Testing

Proof path: shipped entry point.

Security

None.

Evidence

What I checked:

Likely related people:

  • Dallin Romney: Raw commit bf6fa23 adds internal/cli/init.go:137 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: bf6fa23eecac; files: internal/cli/init.go)
  • Peter Steinberger: Raw commit 777a404 adds internal/cli/init.go:119 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 777a404d28a7; files: internal/cli/init.go)

Labels

Label changes:

No label changes.

Label justifications:

  • P2: The PR repairs a bounded initialization failure for explicitly selected database paths inside Git repositories.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR.
  • proof: sufficient: Contributor real behavior proof is sufficient.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only. Repair and merge execution lanes are retired.

History

Review history (4 earlier review cycles)
  • reviewed 2026-10-12T18:00:07.964Z sha a8715c1 :: blocked before merge. :: [P1] Preserve manifest-backed sources when the raw database is absent
  • reviewed 2026-10-12T18:21:32.493Z sha 44cc95e :: needs maintainer review before merge. :: none
  • reviewed 2026-10-13T10:28:19.401Z sha 44cc95e :: needs maintainer review before merge. :: none
  • reviewed 2026-10-13T15:57:02.940Z sha 44cc95e :: needs maintainer review before merge. :: none

Reviewed October 14, 2026, 7:24 AM ET / 11:24 UTC (Revision 5).

A missing raw database is not a missing source when its manifest
selects a gzip archive. init --db created that raw file and could
add sibling runtime directories, so strict refresh rejected the
checkout. Skip creation when the file already exists or the manifest
selects gzip.

Regression: TestInitDBPreservesCompressedPortableCheckout.
Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
@SebTardif

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

init --db no longer creates a raw database, or sibling runtime directories, when a gzip manifest already selects the archive. The checkout stays clean and portable refresh completes.

A published v0.15.1 database, after sync openclaw/gitcrawl --numbers 238, keeps sha256 54e03f2bcdb12beb41269adb275450b58056220a41e6ccf07e55e5747f83c156 through this branch's init --db. threads still returns issue 238.

@clawsweeper

clawsweeper Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. labels Oct 12, 2026
@steipete
steipete merged commit ce04d66 into openclaw:main Oct 15, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants