Release 0.5.0+11 - #548
Open
kipyin wants to merge 58 commits into
Open
Conversation
…#493) ## What changed `grace sentry start` accepts `--main-branch <name>` so you can point sentry at a non-`main` base for that run without editing config. The value is applied after TOML and `SENTRY_MAIN_BRANCH` are loaded, so the flag overrides both for that process. Documentation now describes the three ways to set the base branch: `[sentry] main_branch` in `gracenotes-dev.toml`, `SENTRY_MAIN_BRANCH`, and `--main-branch`. A commented example was added under `[sentry]` in the repo TOML. ## Tests `uv run --project Scripts/gracenotes-dev python -m unittest discover -s Scripts/gracenotes-dev/tests` (196 tests, OK).
## Headline Onboarding reset now truly starts the guided journal path from a clean slate. ## User impact If someone reset journal onboarding (for example from Settings or support flows), leftover tutorial milestone flags could still make the app treat the install as already onboarded. That could skip or confuse the guided journal experience right after a reset. Clearing those keys prevents the completion flag from being immediately inferred again from old tutorial state. ## What changed The journal onboarding reset path now removes all stored journal tutorial keys up front, using the existing helper on `JournalTutorialStorageKeys`, before clearing the onboarding-specific `UserDefaults` entries and launch tracking. A short doc comment was added on `resetAll` to explain that this avoids re-deriving “guided journal complete” from leftover tutorial presence when the explicit completion key is gone. ## Verification On a Mac with Xcode and the project’s `grace` CLI installed, run `grace ci` (or `grace test` with the usual simulator destination from `gracenotes-dev.toml`) to confirm the app still builds and tests pass. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
…st (#497) ## Headline Past statistics no longer sorts every journal before applying the selected history window, which keeps large libraries responsive. ## User impact Users with many entries outside the chosen Past range should see the same charts and lists as before, with less wasted work when opening Past statistics. Reliability improves indirectly by reducing unnecessary sorting on the main thread during those updates. ## What changed The history window helper used to sort the entire journal list, then drop entries outside the range. That meant the cost of sorting grew with total library size even when only a small slice was needed. It now filters to the validated date range first and sorts only that subset, using the same ordering rules as before. ## Verification On a Mac with Xcode and the iOS Simulator, run `grace ci` (or `grace test` with the project’s usual destination) to confirm the app still builds and tests pass. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Resetting journal onboarding now leaves users in a true fresh state instead of silently re-marking the guided journal as complete. ## User impact When support or developers reset onboarding, people should see the full guided journal flow again. Before this fix, clearing stored keys could let the app infer “already completed” from reminders, first-run, or other signals, so the journal could still behave like a finished onboarding even right after a reset. ## What changed The journal onboarding reset path clears the usual UserDefaults keys and tutorial milestones, then explicitly stores guided journal completion as false. That stops the resolver from treating a missing key as a signal to run the migration heuristics again and immediately write completion back to true. Documentation on the reset helper was updated to explain why removing the key alone was not enough. ## Verification On a Mac with Xcode, run `grace test` or `grace ci` from the repo root (or the project’s usual CI profile) to lint, build, and exercise tests against the configured simulator destinations. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Share card style picks and the busy overlay behave more predictably when you customize and export a journal image. ## User impact Style chip taps should refresh the live preview the same way other share options do. After you tap Share, the screen should not stay frozen if image creation fails or if future code paths are added, because the in-progress lock is cleared in one place. ## What changed The style preset buttons no longer mutate the share draft in place. They copy the draft, change the selected style, and assign it back, matching how redaction, section visibility, and toggles already update state so SwiftUI reliably notices changes to the struct-backed draft. Share now uses a single defer to clear the in-progress flag when rendering finishes, instead of repeating that reset on the success and error paths. That keeps the UI from staying disabled if a new early exit slips in later and makes the intent obvious in one spot. ## Verification On a Mac with Xcode and the project’s grace CLI, run `grace ci` (or `grace test` with the repo’s default simulator destination). In the app, open the journal share composer, tap different style chips and confirm the preview updates, tap Share, and confirm controls re-enable after the sheet flow; trigger a render failure path if you can and confirm the composer is not stuck disabled. ## Risk Medium ## Touch class `ui-ux` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
…#503) ## Headline Keeps the completion pill’s morph animation stable when progress math goes bad. ## User impact If bloom progress ever became NaN or infinite (for example from a bad animation handoff or edge-case math), the outline and scale around the completion pill could behave unpredictably or disappear. This change treats those values as zero so the pill stays visible and predictable instead of glitching. ## What changed The completion pill already clamped morph bloom progress to the 0–1 range for normal values. That clamp did not protect against non-finite floats, which can still flow through min/max and break opacity and scale. The morph bloom progress path now checks finiteness first and falls back to a safe value, then applies the same 0–1 clamp. The comment was updated to describe that behavior in plain terms. ## Verification On a Mac with Xcode and the project’s grace CLI installed, run `grace ci` (or `grace test` with the usual simulator destination from gracenotes-dev.toml) to confirm the app builds and tests pass. Manually spot-check the journal header completion pill during any morph/celebration transition if you want extra confidence in the visual path. ## Risk Medium ## Touch class `ui-ux` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Journal import now deletes extra same-day journal rows so each day stays a single source of truth. ## User impact If the database ever had more than one journal row for the same calendar day (for example from earlier bugs or edge cases), importing could update one row while leaving stale duplicates behind. That could make the timeline or day views confusing or show outdated content. After this change, import removes those extras so each day matches the imported backup cleanly. ## What changed The import path already deduplicates entries in the backup file by calendar day. On disk, `fetchEntry` returns one canonical journal per day, but other rows for that day could still exist. When updating an existing day, the service now fetches all journals whose `entryDate` falls in that calendar day and deletes every row except the one being updated. The per-day deduplication helper was moved into an extension for organization, and a small doc comment was wrapped for line length. Behavior for merge conflict detection and file-side deduplication is unchanged except for this cleanup of duplicate persisted rows during apply. ## Verification On a Mac with Xcode and the project’s `grace` CLI installed, run `grace ci` (or `grace test` with the default simulator destination from `gracenotes-dev.toml`) so lint and simulator build/tests cover this path. Manually, import a backup on a store that has duplicate rows for one day and confirm only one journal remains for that day after import. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override.
Move default loading/reassurance strings to a nonisolated enum so init defaults are valid under strict concurrency. Extend StartupCoordinator async test waits to tolerate slow first ModelContainer on CI simulators. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Stops leftover CloudKit account-status work when Settings no longer needs it. ## User impact If someone opens Settings and leaves before iCloud status finishes loading, the app no longer keeps that fetch running in the background. That trims unnecessary work and avoids odd edge cases around a view model that is already gone. ## What changed The iCloud account status helper already cancels superseded refreshes and ignores stale results. This adds the same cleanup when the observable object is destroyed: any in-flight refresh task is cancelled on teardown so work tied to a dismissed screen does not continue. ## Verification On a Mac with Xcode and the repo’s grace CLI installed, run `grace ci` from the repository root (or `grace test` with the project’s default simulator destination) to confirm the app still builds and tests pass. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Keeps the guided tour on valid pages and measures path titles more reliably. ## User impact Users who skip the congratulations screen or swipe through the tour are less likely to land on a missing page or see a blank pager state. The growth-path strip should align dots with titles more consistently when layout updates. ## What changed The tour now clamps the selected page whenever it changes, not only on first appearance, so the pager stays within the first and last visible tabs when the congratulations page is omitted or SwiftUI tries to select an invalid index. A small helper centralizes that range logic for clarity and reuse. The preference key that records each step’s title line height now merges child measurements with the maximum instead of the last value, which better matches multi-line or updating title layout. ## Verification On a Mac with Xcode, run `grace ci` (or `grace test` with the project’s default simulator destination). Manually open the App Tour with congratulations both shown and skipped; swipe between pages and confirm paging, indicators, and path-strip alignment look correct. ## Risk Medium ## Touch class `ui-ux` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Info card accent colors now follow the completion badge cases directly instead of an extra mapping hop. ## User impact Completion badge help text should look the same as before, with tint colors still matching each growth stage. The change makes styling easier to reason about and safer to maintain if completion levels or mappings evolve. ## What changed The info card tint helper used to branch on the mapped `JournalCompletionLevel` (soil through bloom). It now switches on `CompletionBadgeInfo` itself (empty through full), which matches how titles and descriptions are already expressed. The color choices stay aligned with the previous mapping: earliest stage muted, light check-in accent, middle stages standard text, and full completion using the full-stage text color. ## Verification On a Mac with Xcode, run `grace ci` (or `grace test` per project docs) to confirm the GraceNotes scheme builds and tests pass; spot-check the journal completion badge info card in the simulator to confirm tint still matches each stage. ## Risk Medium ## Touch class `ui-ux` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
…es (#509) ## Headline Weekly review insight generation does less redundant work when scanning your journal history. ## User impact Faster, more efficient insight generation when you have many entries, with the same weekly review behavior. You should see snappier review screens and less unnecessary CPU work on device. ## What changed Building the current- and previous-week entry lists used two full scans of every journal entry—one filter for this week and another for last week. That duplicated work for large libraries. The generator now walks the entry list once, assigns each entry to this week, last week, or neither, and passes those lists into the same analysis as before. Logic for which entries belong to which period is unchanged; only how we collect them is streamlined. ## Verification On a Mac with the repo and Xcode, run `grace ci` (or `grace test` with the project’s default simulator destination) to confirm the app builds and tests pass after the change. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Journal share preview stubs now speak their on-screen message instead of a separate generic label. ## User impact People using VoiceOver hear the same italic preview line that sighted users read, which is clearer than a second, generic announcement. It also avoids overriding the real stub copy with a redundant accessibility label. ## What changed In the journal share card, preview stub rows are plain text lines with italic styling. The view had an explicit accessibility label on those rows, which could cause VoiceOver to announce a generic string instead of (or in addition to) the visible stub message. That custom label was removed so accessibility falls back to the line’s text content, matching the visual copy and reducing confusing or duplicate speech. ## Verification On a Mac with Xcode, run `grace ci` (or `grace test` with the project’s usual simulator destination). For a manual check, open the share card with VoiceOver enabled and move to a preview stub line; it should read the full stub message as shown on screen. ## Risk Medium ## Touch class `ui-ux` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Scheduled folder backups now use the same timestamp rules as the rest of journal export naming. ## User impact Backup file names stay aligned with exports you trigger elsewhere in the app, so files sort and read consistently in the chosen folder. One shared implementation also means future timestamp tweaks cannot silently diverge between flows. ## What changed Scheduled backup filenames no longer configure their own DateFormatter for the time stamp. The runner asks JournalDataExportService for the stamp via exportFilenameTimestamp(for:) and keeps the existing grace-notes-scheduled prefix, UUID suffix, and .json extension. Behavior stays the same idea—sortable, unique names—while centralizing how the stamp is produced. ## Verification On macOS with Xcode and the iOS Simulator available, run grace ci from the repository root (or grace test with your usual destination from gracenotes-dev.toml) to confirm the GraceNotes scheme builds and automated checks pass. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
) ## Headline Growth-stage skyline glyphs now compute Dynamic Type scaling in one place instead of two parallel switches. ## User impact The Past skyline and calendar teaser growth icons should look the same as before. The change mainly improves maintainability so future tweaks to size or scaling are less likely to drift or get out of sync. ## What changed The internal `Metrics` helper was replaced from an enum with duplicated `switch` logic in `glyphSize` and `glyphChrome` to a lightweight struct that holds both numbers together. Skyline sizing uses a single `skyline(dynamicTypeSize:)` factory that applies the existing layout scale once; the calendar day teaser keeps fixed dimensions as a static preset. The public initializers and the view body are unchanged in behavior. ## Verification On a Mac with Xcode and the project’s `grace` CLI, run `grace ci` (or `grace test` per your usual workflow) to confirm the app builds and tests pass; spot-check the Review Past skyline and calendar day cells to confirm growth glyphs still align and scale as expected at a few Dynamic Type sizes. ## Risk Medium ## Touch class `ui-ux` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
#521) ## Headline When one save crosses several first-time milestones, the app now shows the strongest growth toast instead of the earliest rule in the list. ## User impact Users who fill out their journal in one go can see a celebration that matches their biggest step forward (Bloom over Leaf over 1/1/1) instead of a weaker or misleading first toast. Behind the scenes, first-time flags still record each milestone so nothing is silently skipped. ## What changed The journal tutorial unlock evaluator already detects when someone crosses 1/1/1, reaches Leaf (balanced), or reaches Bloom for the first time. When more than one of those happens in a single update, only one highlight drives the toast. The logic was reordered so Bloom is preferred, then Leaf, then the 1/1/1 milestone. A short comment documents that behavior and that the separate recording booleans still mark each first-time achievement. ## Verification On a Mac with the repo’s dev setup, run `grace test` (or `grace ci` for lint plus simulator build) to confirm unit tests and the GraceNotes scheme still pass. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
…status (#522) ## Headline Stop flagging normal CloudKit or URL cancellations as iCloud status failures in logs. ## User impact When iCloud work is cancelled or interrupted in ways CloudKit reports as operation cancelled (not only Swift task cancellation), Settings and diagnostics see fewer scary “failed to fetch iCloud account status” messages. That makes real sync or account problems easier to spot and reduces noise during normal navigation or teardown. ## What changed The iCloud account status fetch already had a helper that recognizes several cancellation shapes (Swift cancellation, CloudKit operation cancelled, URL cancelled, and nested underlying errors). The catch path only skipped logging for plain Swift CancellationError, so other cancellation forms were still logged as errors even though the code already treated any failure the same for the user-facing bucket. The catch path now uses the same cancellation detection before logging, so benign cancellations are not reported as failures. ## Verification On a Mac with Xcode and the repo’s grace CLI installed, run `grace ci` (or `grace test` with the project’s default simulator destination) to confirm the GraceNotes scheme still builds and tests pass. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
…523) ## Headline Daily reminder rescheduling now relies on one shared, validated clock-time reader. ## User impact Reminder scheduling behavior stays the same for people who use daily reminders, but the app no longer carries two different ways to interpret the saved time from UserDefaults. That reduces the risk of future edits accidentally changing behavior in one path but not the other. ## What changed `DailyReminderNotificationSync` already used `ReminderSettings.coercedTimeInterval(fromUserDefaults:)` when computing the next reminder time. A private helper that duplicated the same UserDefaults parsing and validation was left in the file but never called, so it was removed. Reminder time coercion and non-finite value handling remain centralized in `ReminderSettings`, which is the single place reviewers should look for that logic. ## Verification On a Mac with Xcode and the project’s `grace` CLI installed, run `grace ci` (or `grace test` with the repo’s default simulator destination) to confirm the GraceNotes scheme still builds and tests pass. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Separates SwiftUI row identity from UI-test identifiers so recurring-theme rows update reliably when labels collide. ## User impact When two recurring themes looked the same by label, list updates could behave oddly and automation could target the wrong row. The card now keys rows in a way that matches the theme value while still using a composite key for accessibility identifiers when labels are not unique. ## What changed The most recurring themes list no longer uses a custom string property as the ForEach identity. Rows are keyed by the theme value itself, which is appropriate when the model differentiates themes beyond the display label. The old composite string used for stable differentiation was moved into a small helper used only for accessibility and UI-test identifiers, so test IDs stay stable where labels can collide without tying that logic to list animation and updates. ## Verification On a Mac with Xcode, run `grace ci` (or `grace test` with the project’s default destination) to lint and build. Manually open Review insights with overlapping or similarly labeled recurring themes and confirm rows update; if you have UI tests that hit `MostRecurringThemeRow.*` identifiers, re-run those to confirm they still resolve distinct rows. ## Risk Medium ## Touch class `ui-ux` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Weekly review rhythm stats compute the earliest entry day without materializing a full day array. ## User impact Users with large journals get snappier weekly review and past-statistics aggregation with less transient memory use while scrolling or refreshing review screens. Behavior stays the same: the code still finds the minimum calendar day the same way, just without building every intermediate date upfront. ## What changed Computing the earliest calendar day across all entries used a non-lazy map, which built a full array of normalized day values before taking the minimum. That extra allocation scales with total entries and is unnecessary for a min scan. The path now uses a lazy map so only one day at a time is produced while the minimum is computed, cutting peak allocation for the same logical result. ## Verification On a Mac with Xcode, run `swiftlint lint` on the touched file or repo, then `grace ci` (or `grace test`) from the project root to confirm the GraceNotes scheme still builds and tests pass. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
…#531) ## Headline Today tab journal appearance now migrates and normalizes even when the saved preference is not a string. ## User impact If the journal appearance key was ever stored as a non-string (or otherwise read as nil by `string(forKey:)`), the app could skip cleanup and leave `@AppStorage` out of sync with what you see. After this change, those cases are treated as empty, resolved to the correct mode, and rewritten to a canonical string so the Today tab stays predictable and settings stay consistent. ## What changed The migration helper for journal appearance no longer exits early whenever `UserDefaults.string(forKey:)` is nil. It now checks whether anything is stored under the key at all: real strings are used as before; if a value exists but is not a string, it is treated as an empty string so the existing normalization path can pick a valid mode and persist the canonical raw value. If the key is absent entirely, the function still returns without writing. ## Verification On a Mac with Xcode and the project’s `grace` CLI, run `grace ci` (or `grace test` per your usual profile) to confirm lint and simulator builds pass. Optionally reset or seed `UserDefaults` with a non-string for `journalTodayAppearanceMode`, launch the app, and confirm Today appearance and migration behave as expected. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Canceling a JSON merge conflict now abandons the import cleanly instead of leaving stale state behind. ## User impact If you backed out of resolving merge conflicts, the app could still hold onto the pending file and conflict list. That could make a later import confusing or behave as if an old import was still in flight. Cancel now clears that state so Settings reflects what you actually chose. ## What changed The merge-conflict alert’s Cancel action used to do nothing beyond dismissing the sheet. It now clears the pending import URL and empties the list of conflicting days so abandoned imports do not linger in memory. This is a small state-management fix in Import & Export settings; no change to how merge, keep-device, or keep-backup resolution works when you confirm a choice. ## Verification On a Mac with Xcode and the repo’s dev tooling, run `grace ci` (or `grace test` with the project’s default simulator destination) after reproducing merge conflicts during JSON import and tapping Cancel; confirm a new import can start without odd carryover from the canceled flow. ## Risk Medium ## Touch class `ui-ux` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Weekly review reflection days now follow the same meaningful-entry bar everywhere. ## User impact Reflection-day totals and the week’s day activity strip stay consistent with how Grace Notes already scores a day as meaningful, so insights and completion signals are not inflated by notes-only or reflections-only stubs. Reviewers see fewer mismatches between “reflection days” and other weekly stats. ## What changed Reflection day counting and the per-day activity set previously treated a day as active if an entry had meaningful content or only non-empty trimmed reading notes or reflections. That second path could bump reflection totals and disagree with `meaningfulEntryCount` and the rest of the weekly aggregates. The builder now counts those days only when `hasMeaningfulContent` is true, matching the single definition used elsewhere, and removes the helper that only looked at notes and reflections text. ## Verification On a Mac with Xcode and the project’s `grace` CLI, run `grace ci` (or `grace test` with your usual simulator destination). Optionally open Weekly Review for a week where some days have only notes or reflections and confirm reflection-day counts match expectations for meaningful entries. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
…537) ## Headline Past-tab review insights now refresh on a consistent day calendar, not mixed timestamps. ## User impact Entries saved at different times on the same day could be treated inconsistently when deciding which journals affect Past insights and trend weeks. That could cause insights to update too often, too little, or feel out of sync with what you actually wrote. This change makes that logic line up with how the rest of the window uses calendar days. ## What changed The code that picks which journal entries belong in the current and previous review weeks no longer uses raw date containment on the entry timestamp. It compares the entry’s calendar day (start of day) to each week range’s lower and upper bounds, the same way the past-statistics history window already works. Snapshot ordering for the refresh key now sorts entry IDs as UUIDs instead of stringifying them first, which keeps ordering stable with less overhead. ## Verification On a Mac with the repo’s Xcode setup, run `grace ci` (or at least `grace test`) to confirm the GraceNotes scheme still builds and tests pass. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Growth-stage labels for your journal now derive from one consistent, defensive count model. ## User impact Chip-section completion (Soil through Bloom) drives progress cues and history; inconsistent or edge-case counts could skew that story. Clamping counts to zero and expressing bloom, leaf, and twig rules through min/max across sections keeps the stage fair and predictable. ## What changed Completion and bloom checks used repeated comparisons on raw integers, and twig used easy-to-misread OR/AND logic. The change introduces a small private helper that treats each section count as non-negative, then derives the weakest and strongest section sizes from those values. Bloom and leaf tiers now key off that shared minimum (with a named threshold for the pre-bloom “balanced” bar), and the twig case uses max versus min so “mixed progress” is expressed in plain language. Bloom detection and “minimum across sections” reuse the same path so the app does not drift between call sites. ## Verification On a Mac with Xcode and the project’s default simulator setup, run `grace ci` (or `grace test` with the usual GraceNotes destination) to lint, build, and exercise automated tests. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override.
…539) ## Headline Past search line items now always reflect the entry’s stored text, and long-field IDs hash UTF-8 with less overhead. ## User impact Search results for line-based matches stay aligned with what is actually saved in the journal, so highlights and snippets are less likely to drift from the source. For whole-field matches (for example reading notes or reflections), computing stable IDs should be a bit lighter on memory when hashing large text. ## What changed The initializer that builds a match from an `Entry` no longer takes a separate `content` argument. It always fills the match’s text from the entry’s full text, so callers cannot accidentally pass a different string than what is stored. For fingerprinting whole-field matches, SHA-256 now prefers hashing the string’s UTF-8 bytes in place when the backing storage allows it, and only falls back to building a `Data` buffer when it must. The public shape of `JournalSearchMatch` and the meaning of its `id` for field matches are unchanged. ## Verification On a Mac with Xcode and the project’s `grace` CLI installed, run `grace ci` (or `grace test` with the usual simulator destination) to confirm the app builds and tests pass. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
## Headline Share images only honor redactions for lines that actually exist, and toggles cannot store invalid indices. ## User impact Stale or out-of-range redaction indices (for example after editing or shortening journal text) could hide the wrong lines or leave privacy expectations unclear. Negative indices could also pollute stored state. The share card now treats redactions as valid only for the current line count and ignores invalid toggles. ## What changed The redaction toggle helper now ignores negative indices so the draft never records impossible line numbers. When building list and prose lines for the share preview, redaction is applied using only indices that fall within the current number of lines. Indices that are out of range are ignored, so the rendered card stays consistent with what is on screen and avoids mis-applying redaction across edits. ## Verification From the repo root on macOS: run `swiftlint lint` (style). For a full simulator build aligned with CI, run `grace ci` (or `grace test` with your usual destination). Exercise the share composer: toggle redactions, edit entries so line counts change, and confirm only intended lines are hidden on the share preview. ## Risk Medium ## Touch class `business-logic` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. Co-authored-by: Kip <kipyin@users.noreply.github.com>
… thread (#504) ## Headline Smoother, more reliable manual imports when merge conflicts appear or files are large. ## User impact Dismissing the merge-conflict alert with Cancel no longer leaves a half-finished import hanging in memory, so you are less likely to see odd follow-up behavior. Reading the chosen JSON off the main thread keeps Settings responsive while a big backup file is loaded. ## What changed The merge-conflict alert’s Cancel action now clears the pending import URL and the list of conflicting days so abandoned flows do not retain stale state. Manual import now loads file data in a user-initiated background task (with helpers made static so the work can run without capturing the view), matching the existing pattern for the heavier import step and reducing main-thread stalls when reading large files or resolving security-scoped backup paths. ## Verification On a Mac with Xcode and the project’s grace CLI installed, run `swiftlint lint` from the repo root and `grace ci` (or `grace test` with the usual simulator destination) to confirm the GraceNotes scheme still builds and tests pass. ## Risk Medium ## Touch class `ui-ux` --- *Automated by `grace sentry`.* Merge is normally unblocked by CI and review resolution; if stuck, an allowlisted account may post `/sentry-approve` as an emergency override. --------- Co-authored-by: Kip <kipyin@users.noreply.github.com>
Owner
Author
|
@cursor resolve merge conflict |
Contributor
|
Here’s what was done: Merge conflictMerging
Resolution: Kept the release branch’s Git
The PR body wasn’t updated automatically (PR description isn’t agent-managed). Your GitHub conflict should clear now that the merged branch is pushed; if the UI still shows conflict, refresh or reopen the PR compare view. |
Resolve PersistenceController conflict: keep removeUITestStoreFileIfPresent(at:) for UI test store reset (retry + explicit storeURL) alongside main updates. Co-authored-by: Kip <kipyin@users.noreply.github.com>
Co-authored-by: Kip <kipyin@users.noreply.github.com>
…ter import Past journal sheets and backgrounding could dismiss before the 400ms debounce completed, dropping unsaved edits. Settings import wrote on a background ModelContext while Today kept stale in-memory state; a queued autosave could overwrite imported rows for the current day. - persistImmediately on JournalScreen disappear and scene background - Import on the main ModelContext and post journalStoreDidChangeExternally - Reload Today from store with autosave epoch to drop stale debounced saves - Commit inline chip drafts before midnight day rollover Co-authored-by: Kip <kipyin@users.noreply.github.com>
Midnight or resume calls refreshTodayIfStale, which persisted then loaded today even when context.save() failed. That replaced in-memory edits with a new day and could discard unsaved work. Gate loadEntry on a successful persist and add a regression test. Co-authored-by: Kip <kipyin@users.noreply.github.com>
#468 fixed JournalItem decoding but the Settings import path still dropped chip lines whose fullText was empty while entryLabel/chipLabel held the text. mapItems now uses importableFullText so legacy backups restore those lines. Co-authored-by: Kip <kipyin@users.noreply.github.com>
…al rows Added `.accessibilityHidden(true)` to decorative SF Symbols (like chevrons and clear marks) in `SettingsScreen`, `ImportExportSettingsScreen`, and `SequentialEntryRowView`. This removes redundant VoiceOver announcements since the text or button accessibility label already provides full context. Co-authored-by: Kip <kipyin@users.noreply.github.com>
Replace the single welcome screen with paged onboarding copy and SVG art, and drop the redundant search-match content argument now derived from Entry. Co-authored-by: Kip <kipyin@users.noreply.github.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.


No description provided.