feat(config): minimal config persistence — Overrides user-only + sparse save#161
feat(config): minimal config persistence — Overrides user-only + sparse save#161seeyabye wants to merge 27 commits into
Conversation
…terialization Phase 1 of minimal-config-persistence: - Add ResolvedSettings(name) on ScrapersConfig (complete default clone for absent, override.Clone() + MergeDefaultsFrom for present) - Drop Finalize seeding loop (Overrides no longer pre-materialized) - Drop pipeline.normalize languageDefaults map (redundant with module Defaults) - Switch ScraperRegistryConfigFromApp to accept names + defaults (avoids import cycles), inline resolve via Clone + MergeDefaultsFrom - Update all 4 call sites (dependencies, hot_reload, e2e) - Fix info command to use ResolvedSettings instead of direct Overrides - Update tests assuming old materialization behavior
… snapshot + startup re-decode
…+ empty override skip
…ile to proxy schema
…ecated aliases to schema
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 726e824db2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 20ced4ad1e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
735192e to
994b36b
Compare
|
@codex review |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #161 +/- ##
==========================================
+ Coverage 91.34% 91.86% +0.52%
==========================================
Files 455 457 +2
Lines 40593 41381 +788
==========================================
+ Hits 37078 38013 +935
+ Misses 2281 2184 -97
+ Partials 1234 1184 -50
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 994b36b2ae
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review — these P2 findings are documented limitations in the OpenSpec design: (1) nested map entry deletion for proxy profiles is a known reconciliation edge case; (2) partial-override presence for scraper Enabled is the documented tri-state limitation. Both are accepted for v1 and tracked as follow-up. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 994b36b2ae
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dad30eb286
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 643a15262f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cca16d79c3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ab7177cf12
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4fbc7535e4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. Breezy! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
Implements the
minimal-config-persistenceOpenSpec change: a two-phase plan to fix the structural defect where the first-run flow bakes the full embedded example to disk andSavere-inflates every field on every write, so code-default changes never reach existing installs.Replaces the reverted PR #158 (which used a
defaults_versionpatch chain). No version tracking — future default changes propagate lazily via sparse persistence.Phase 1: Overrides becomes user-only
ResolvedSettings(name)onScrapersConfig— complete default clone for absent overrides,override.Clone()+MergeDefaultsFromfor presentFinalizeseeding loop +pipeline.normalizelanguageDefaultsmapScraperRegistryConfigFromAppacceptsnames []string+defaults map(avoids import cycles)Override(name),ApplyOverride(name, opts...)(no-op when empty),UserOverride(name)non-creating,WithScrapeActress/WithBrowseroption funcsminimalInitStub()as production first-run (sparse stub instead of full ~90-line example)Phase 2: Sparse persistence
diffYAMLDocuments(actual, defaults)— node-diff post-MarshalYAML, emits only non-default leaves +alwaysEmitPaths+nullclear-markers for clearedomitemptymapsreconcileSparse(dst, sparseTarget, schemaDoc, knownScraperNames)— src-authoritative, key-comment-preserving, recursively deletion-safe, schema-gatedConfigStorage.SaveSparse— shares afero fs, lock, atomic replace; handles missing/malformed; unchanged-byte skipSparseSaveContext{Defaults, Schema, KnownScraperNames}with collision rejectionPreparesplit:PrepareForPersistence(excludes translation credentials) +PrepareRuntime(fullValidateConfig)PUT /configuses disk-origin snapshot forpreserveRedactedSecrets,SaveSparsefor persistence,runtimeCfg(post-env) for reloadAPIRuntime.SetInitialConfigs(runtimeCfg, diskCfg)+DiskConfigSnapshot()(cloned on set/get)LoadOrCreateconvergence: all 3 branches (existing-file, first-run, migration) apply env + Prepare before returningNo
defaults_versionNo version tracking. Future default-value changes update the code default; existing configs pick it up on their next API save (lazy propagation). Existing baked values persist until users clear them via WebUI.
Test plan
go test -short ./internal/config/... ./internal/api/...— passgo test -race ./internal/config/...— passgolangci-lint run ./internal/config/... ./internal/api/...— 0 issuesgo build ./...— passKnown limitations (follow-up revisions)
DefaultConfig(nil, nil)(hardcoded priorities) — correct for the standard registry, documented limitation for custom registriesOpenSpec
openspec/changes/minimal-config-persistencecodex-lb/gpt-5.6-sol(medium) — final verdict: PROCEED WITH REVISIONS (0 blockers, 0 majors, 3 minors)