fix(bootstrap): write metadata.json and config.yaml after sync clone#3203
Merged
Conversation
executeSyncAction created .beads/ and cloned remote Dolt data but never
wrote the two files bd needs to open the database afterwards:
- metadata.json (dolt_database, dolt_mode, backend)
- config.yaml (sync.remote and other yaml-backed settings)
Every other bootstrap action path (init, restore, jsonl-import) writes
these via newDoltStore + createConfigYaml. The sync path was a "just
clone the data" shortcut that never received the post-clone setup
steps. The result: bd bootstrap --yes in a fresh clone appeared to
succeed, but bd status / bd where / bd dolt push all failed with
"no beads configuration found" and "Error 1105: no database selected",
leaving the user stuck — bd bootstrap --dry-run then reported
"Database already exists" and refused to retry.
This directly blocks the documented session-close protocol in AGENTS.md:
git pull --rebase → bd dolt push → git push
Add a new finalizeSyncedBootstrap helper that runs after cloneFromRemote
and mirrors what init does: save cfg as metadata.json, create the
config.yaml template, and persist sync.remote. The helper is idempotent
(createConfigYaml skips existing files; metadata.json is a safe rewrite)
so bootstrap retries remain safe.
Regression coverage:
- TestFinalizeSyncedBootstrapWritesConfigFiles — verifies metadata.json
records the cloned dolt_database name, config.yaml exists, and
sync.remote persists.
- TestFinalizeSyncedBootstrapIsIdempotent — verifies re-running the
finalize step over an already-finalized workspace is a no-op,
matching the clone-retry expectation.
Verified end-to-end by building bd-main and bd-fixed binaries, creating
a source project + bare git remote, dolt-pushing issues to it, then
bootstrapping into a fresh clone with each binary. bd-main left the
workspace in the reported broken state; bd-fixed produced a workspace
where bd status, bd list, and bd dolt push all succeed.
Fixes gastownhall/gascity#561
maphew
approved these changes
Apr 12, 2026
maphew
left a comment
Collaborator
There was a problem hiding this comment.
Code Review
Verdict: Clean, well-scoped fix for a real bootstrap gap. Ready to merge.
Strengths
- Correctly mirrors what
bd initdoes: samecfg.Save→createConfigYaml→SetYamlConfig("sync.remote", ...)sequence isEmbeddedMode()usage is correct — reads runtime state rather than stale configcreateConfigYamlnaturally short-circuits on existing files, making the idempotency claim valid- Tests are thorough: proper env isolation via
t.Setenv, regression + idempotency coverage,BEADS_DIRoverride to avoid CWD leakage
Minor nit (I'll fix post-merge)
cfg == nilguard infinalizeSyncedBootstrapis unreachable — the caller chain guarantees non-nil viaDefaultConfig()fallback at bootstrap.go:178-180. Harmless but unnecessary; I'll clean it up.
Thanks @julianknutsen — great fix and thorough testing! 🎯
maphew
added a commit
to maphew/beads
that referenced
this pull request
Apr 12, 2026
…ootstrap The caller chain (bootstrapCmd.Run → executeBootstrapPlan → executeSyncAction) guarantees cfg is non-nil via DefaultConfig() fallback at bootstrap.go:178-180. Follow-up to gastownhall#3203. Amp-Thread-ID: https://ampcode.com/threads/T-019d7fee-1326-74af-a566-9c45ad5b349e Co-authored-by: Amp <amp@ampcode.com>
maphew
added a commit
that referenced
this pull request
Apr 12, 2026
…ootstrap (#3222) The caller chain (bootstrapCmd.Run → executeBootstrapPlan → executeSyncAction) guarantees cfg is non-nil via DefaultConfig() fallback at bootstrap.go:178-180. Follow-up to #3203. Amp-Thread-ID: https://ampcode.com/threads/T-019d7fee-1326-74af-a566-9c45ad5b349e Co-authored-by: Amp <amp@ampcode.com>
maphew
added a commit
that referenced
this pull request
Apr 13, 2026
* chore(bootstrap): remove unreachable nil-cfg guard in finalizeSyncedBootstrap The caller chain (bootstrapCmd.Run → executeBootstrapPlan → executeSyncAction) guarantees cfg is non-nil via DefaultConfig() fallback at bootstrap.go:178-180. Follow-up to #3203. Amp-Thread-ID: https://ampcode.com/threads/T-019d7fee-1326-74af-a566-9c45ad5b349e Co-authored-by: Amp <amp@ampcode.com> * fix(ci): remove Microsoft apt repos before apt-get update GitHub's ubuntu-latest runners include Microsoft package repos (azure-cli, microsoft-prod) that intermittently return 403 Forbidden, causing apt-get update to fail and breaking the Install ICU4C step. Remove these unused repo files before apt-get update in all workflows (ci.yml, cross-version-smoke.yml, nightly.yml). Amp-Thread-ID: https://ampcode.com/threads/T-019d83a9-4273-711e-be59-1ed089de1c65 Co-authored-by: Amp <amp@ampcode.com> --------- Co-authored-by: Amp <amp@ampcode.com>
osamu2001
pushed a commit
to osamu2001/beads
that referenced
this pull request
Apr 13, 2026
…l#3224) * chore(bootstrap): remove unreachable nil-cfg guard in finalizeSyncedBootstrap The caller chain (bootstrapCmd.Run → executeBootstrapPlan → executeSyncAction) guarantees cfg is non-nil via DefaultConfig() fallback at bootstrap.go:178-180. Follow-up to gastownhall#3203. Amp-Thread-ID: https://ampcode.com/threads/T-019d7fee-1326-74af-a566-9c45ad5b349e Co-authored-by: Amp <amp@ampcode.com> * fix(ci): remove Microsoft apt repos before apt-get update GitHub's ubuntu-latest runners include Microsoft package repos (azure-cli, microsoft-prod) that intermittently return 403 Forbidden, causing apt-get update to fail and breaking the Install ICU4C step. Remove these unused repo files before apt-get update in all workflows (ci.yml, cross-version-smoke.yml, nightly.yml). Amp-Thread-ID: https://ampcode.com/threads/T-019d83a9-4273-711e-be59-1ed089de1c65 Co-authored-by: Amp <amp@ampcode.com> --------- Co-authored-by: Amp <amp@ampcode.com>
mzlee
pushed a commit
to mzlee/beads
that referenced
this pull request
Apr 22, 2026
…astownhall#3203) fix(bootstrap): write metadata.json and config.yaml after sync clone executeSyncAction created .beads/ and cloned remote Dolt data but never wrote metadata.json or config.yaml, leaving the workspace in a broken state where bd status, bd where, and bd dolt push all failed. Adds finalizeSyncedBootstrap helper that runs after cloneFromRemote and mirrors what init does: save cfg as metadata.json, create the config.yaml template, and persist sync.remote. The helper is idempotent so bootstrap retries remain safe. Fixes gastownhall/gascity#561 Co-authored-by: Julian Knutsen <julianknutsen@users.noreply.github.com>
mzlee
pushed a commit
to mzlee/beads
that referenced
this pull request
Apr 22, 2026
…ootstrap (gastownhall#3222) The caller chain (bootstrapCmd.Run → executeBootstrapPlan → executeSyncAction) guarantees cfg is non-nil via DefaultConfig() fallback at bootstrap.go:178-180. Follow-up to gastownhall#3203. Amp-Thread-ID: https://ampcode.com/threads/T-019d7fee-1326-74af-a566-9c45ad5b349e Co-authored-by: Amp <amp@ampcode.com>
mzlee
pushed a commit
to mzlee/beads
that referenced
this pull request
Apr 22, 2026
…l#3224) * chore(bootstrap): remove unreachable nil-cfg guard in finalizeSyncedBootstrap The caller chain (bootstrapCmd.Run → executeBootstrapPlan → executeSyncAction) guarantees cfg is non-nil via DefaultConfig() fallback at bootstrap.go:178-180. Follow-up to gastownhall#3203. Amp-Thread-ID: https://ampcode.com/threads/T-019d7fee-1326-74af-a566-9c45ad5b349e Co-authored-by: Amp <amp@ampcode.com> * fix(ci): remove Microsoft apt repos before apt-get update GitHub's ubuntu-latest runners include Microsoft package repos (azure-cli, microsoft-prod) that intermittently return 403 Forbidden, causing apt-get update to fail and breaking the Install ICU4C step. Remove these unused repo files before apt-get update in all workflows (ci.yml, cross-version-smoke.yml, nightly.yml). Amp-Thread-ID: https://ampcode.com/threads/T-019d83a9-4273-711e-be59-1ed089de1c65 Co-authored-by: Amp <amp@ampcode.com> --------- Co-authored-by: Amp <amp@ampcode.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
executeSyncActioncreated.beads/and cloned remote Dolt data but never wrotemetadata.jsonorconfig.yaml, leaving the workspace in a broken state wherebd status,bd where, andbd dolt pushall failed withno beads configuration foundandError 1105: no database selected. This broke the documented session-close protocol (git pull --rebase→bd dolt push→git push) on every fresh clone and worktree.Every other bootstrap action path (init, restore, jsonl-import) writes these files through
newDoltStore+createConfigYaml. The sync path was a "just clone the data" shortcut that never received the post-clone setup steps.This PR adds a
finalizeSyncedBootstraphelper that runs aftercloneFromRemoteand mirrors what init does: save cfg asmetadata.json, create theconfig.yamltemplate, and persistsync.remote. The helper is idempotent so bootstrap retries remain safe.Fixes gastownhall/gascity#561
Root Cause
cmd/bd/bootstrap.go:executeSyncActionpreviously:It returned immediately after
cloneFromRemote, leaving nometadata.jsonorconfig.yaml. On the next command,configfile.Load()returnednil,cfg.GetDoltDatabase()fell back to the default, and opening the embedded database failed.Changes
cmd/bd/bootstrap.go: newfinalizeSyncedBootstraphelper called at the end ofexecuteSyncAction. Writesmetadata.json(withdolt_database,dolt_mode,backend,database), creates theconfig.yamltemplate viacreateConfigYaml, and persistssync.remoteviaconfig.SetYamlConfig.cmd/bd/bootstrap_test.go: two new regression tests:TestFinalizeSyncedBootstrapWritesConfigFiles— verifiesmetadata.jsonrecords the cloned dolt_database name,config.yamlexists, andsync.remotepersists.TestFinalizeSyncedBootstrapIsIdempotent— verifies re-running the finalize step over an already-finalized workspace is a no-op.The helper is idempotent by design:
createConfigYamlskips existing files, andmetadata.jsonis a safe rewrite that preserves upstream cfg fields.Test plan
go test -tags gms_pure_go -run TestFinalizeSyncedBootstrap ./cmd/bd— new tests passgo test -tags gms_pure_go -run 'TestBootstrap|TestDetectBootstrapAction|TestFinalizeSyncedBootstrap' ./cmd/bd— all bootstrap tests passgo test -tags gms_pure_go -short ./cmd/bd— fullcmd/bdshort suite passesgo vet -tags gms_pure_go ./...cleangolangci-lint run --timeout=5m --build-tags=gms_pure_go ./...— 0 issuesbd-mainandbd-fixed, created a source project + bare git remote,dolt push-ed, and bootstrapped into a fresh clone with each binary:bd-main: reproduced the bug —.beads/only containedembeddeddolt/;bd status/bd dolt pushfailed with "no beads configuration found" / "Error 1105".bd-fixed:.beads/containedmetadata.json+config.yaml+embeddeddolt/;bd status,bd list, andbd dolt pushall succeeded.Related
bd bootstrapfails in a fresh second clone even when origin already hasrefs/dolt/data(v0.62.0) #2792 (same class of "fresh clone bootstrap" bug, addressed for the directory-creation side)bd initandbd dolt remote add, but did not cover the sync path)