PR-C: Split user_preferences.json from heartbeat_config.json#15
Merged
Conversation
…PR-C) Per principle audit (PR-C): introduces `user_preferences.json` as the single GUI-surfaceable cadence file. heartbeat_config.json remains, but is now formally documented as developer-only internal calibration — decay rates, GC thresholds, gating thresholds, reflex/research enable flags. The GUI must never read or write that file. Currently `dream_every_hours` is the only field in user_preferences.json, matching the principle: the user picks how often the brain dreams; the brain owns everything else. Resolution order in HeartbeatConfig.load(): 1. heartbeat_config.json's value (or framework default 24.0) 2. user_preferences.json's value WHEN the field is explicitly present The "explicitly present" check via `read_raw_keys()` matters for back-compat: a user_preferences.json that adds a new future field (e.g., growth_every_hours once Phase 2a lands) must not silently shadow a custom dream_every_hours sitting in heartbeat_config.json from before this split. Adds: - `brain/user_preferences.py` — `UserPreferences` dataclass with atomic load/save and a module-level `read_raw_keys()` helper. - 5 new precedence tests on HeartbeatConfig.load (override / missing / present-but-omits-field / only-user-prefs / corrupt-prefs). - 11 new unit tests on UserPreferences and read_raw_keys. Net: 492 tests passing (was 476, +16 new).
hanamorix
added a commit
that referenced
this pull request
May 9, 2026
…PR-C) (#15) Per principle audit (PR-C): introduces `user_preferences.json` as the single GUI-surfaceable cadence file. heartbeat_config.json remains, but is now formally documented as developer-only internal calibration — decay rates, GC thresholds, gating thresholds, reflex/research enable flags. The GUI must never read or write that file. Currently `dream_every_hours` is the only field in user_preferences.json, matching the principle: the user picks how often the brain dreams; the brain owns everything else. Resolution order in HeartbeatConfig.load(): 1. heartbeat_config.json's value (or framework default 24.0) 2. user_preferences.json's value WHEN the field is explicitly present The "explicitly present" check via `read_raw_keys()` matters for back-compat: a user_preferences.json that adds a new future field (e.g., growth_every_hours once Phase 2a lands) must not silently shadow a custom dream_every_hours sitting in heartbeat_config.json from before this split. Adds: - `brain/user_preferences.py` — `UserPreferences` dataclass with atomic load/save and a module-level `read_raw_keys()` helper. - 5 new precedence tests on HeartbeatConfig.load (override / missing / present-but-omits-field / only-user-prefs / corrupt-prefs). - 11 new unit tests on UserPreferences and read_raw_keys. Net: 492 tests passing (was 476, +16 new). Co-authored-by: Hana <hana@nanoclaw.local>
hanamorix
pushed a commit
that referenced
this pull request
Jun 13, 2026
…n gates Seven items in one cut: #13 activation-baseline WAL, #20 events autouse conftest, #6 honest image-auth comment, #32 crystallisation dedup, #33 extractor-scored importance, #18 attunement-emotion closed as intentional decouple, W10 soft body-energy rest gate (fail-open). W4/W5/W8 carved out for own brainstorms; #7/#16/#9/#8/#17/#34 deferred with reason; #15 wontfix. Gate: 3198 backend + 41 frontend files + pnpm build + ruff clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.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
Implements PR-C from the principle alignment audit at
docs/superpowers/audits/2026-04-25-principle-alignment-audit.md.Introduces
user_preferences.jsonas the single GUI-surfaceable cadence file.heartbeat_config.json is now formally documented as developer-only internal
calibration — decay rates, GC thresholds, gating thresholds, reflex/research
enable flags. The GUI must never read or write that file.
Currently
dream_every_hoursis the only field in user_preferences.json,matching the principle: the user picks how often the brain dreams; the brain
owns everything else.
Resolution order
In
HeartbeatConfig.load():The "explicitly present" check (via
read_raw_keys()) matters for back-compat:a future user_preferences.json that adds a new field (e.g.,
growth_every_hoursonce Phase 2a lands) must not silently shadow a custom dream_every_hours
sitting in heartbeat_config.json from before this split.
Changes
brain/user_preferences.py— newUserPreferencesdataclass with atomicload/save (
.new + os.replace). Module-levelread_raw_keys()helper thatreturns the explicit JSON keys, used by HeartbeatConfig.load to do per-field
precedence rather than whole-object precedence.
brain/engines/heartbeat.py—HeartbeatConfig.load()now mergesuser_preferences.json on top after loading heartbeat_config.json. Original
load body extracted to
_load_internal(). Updated docstring documents thetwo-file contract.
Test plan
UserPreferences+read_raw_keys(load/save,corrupt JSON, wrong-type fallback, atomic save)
HeartbeatConfig.load:override / fallback / present-but-omits-field / user-prefs-only / corrupt-prefs
ruff checkcleanCloses
This is the third and final cleanup PR from the principle alignment audit
(PR-A → PR-B → PR-C). After this lands, every routine user surface in the
framework matches the principle: name (persona dir) / cadence
(
user_preferences.json) / face-body (out of scope until GUI work) /generated documents (read-only inspection).