Skip to content

fix(app): add non-creating child-store peek for sidebar timestamps (closes #475)#552

Merged
Astro-Han merged 1 commit into
devfrom
fix/peek-existing-child-store
May 11, 2026
Merged

fix(app): add non-creating child-store peek for sidebar timestamps (closes #475)#552
Astro-Han merged 1 commit into
devfrom
fix/peek-existing-child-store

Conversation

@Astro-Han

@Astro-Han Astro-Han commented May 11, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add peekExisting(directory) as a cache-only child-store accessor.
  • Switch sidebar timestamp message and part reads to peekExisting so missing directory caches are not materialized during sidebar row building.
  • Add child-store and layout source-level tests that lock the non-creating behavior.

Why

Sidebar timestamp reads only need cached messages and parts when a child store already exists. Calling globalSync.child(..., { bootstrap: false, pin: false }) still creates a child store and its persisted vcs/project/icon caches just to discover absence.

Related Issue

Closes #475.

Human Review Status

Pending. A human should make the final merge decision after reviewing the final diff and verification evidence.

Review Focus

  • peekExisting must stay read-only: validate the directory, then return children[directory] without calling ensureChild, pinning, bootstrapping, marking, or evicting.
  • Existing child() and peek() semantics should remain unchanged.
  • Sidebar timestamp messagesForSession and partsForMessage should both use the non-creating accessor.

peekExisting semantics

peekExisting(directory) returns the existing ChildStoreTuple if present in children, otherwise undefined. It does not call ensureChild, does not pin for the current owner, does not bootstrap loading, and does not run eviction. It is intentionally a non-reactive read: if the child store does not yet exist, peekExisting does not subscribe to its eventual creation. Sidebar timestamp reads use this to avoid materializing per-directory caches just to discover absence.

If a future caller needs absent-to-present reactivity, that is a separate reactive-registry design and out of scope for this PR.

Risk Notes

Low. The new accessor is only used by sidebar timestamp cache reads. Missing caches now return undefined, which preserves the existing row-builder fallback to session creation time. Existing child() and peek() callers keep their current ensure/create behavior.

How To Verify

Targeted app tests: 1048 passed, 0 failed
Command: bun --cwd packages/app test --preload ./happydom.ts src/context/global-sync/child-store.test.ts src/pages/layout/pawwork-sidebar-session-rows.test.ts

App typecheck: passed
Command: bun --cwd packages/app typecheck

Diff check: passed
Command: git diff --check

Screenshots or Recordings

Not applicable. This is a cache access behavior change with no intended visible UI change.

Checklist

  • Human review status is stated above as pending, approved, or not required
  • I linked the related issue, or stated why there is no issue
  • This PR has type, primary area, and priority labels, or I requested maintainer labeling
  • I described the review focus and any meaningful risks
  • I listed the relevant verification steps and the key result for each
  • I did not introduce unrelated refactors, dependencies, generated files, or file changes beyond the stated scope
  • I manually checked visible UI or copy changes when needed, with screenshots or recordings
  • I considered macOS and Windows impact for platform, packaging, updater, signing, paths, shell, or permissions changes
  • I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or local file changes when relevant
  • I reviewed the final diff for unrelated changes and suspicious dependency changes
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English

Summary by CodeRabbit

  • New Features

    • Added optimized data access method for existing application state, allowing more efficient queries without triggering unnecessary initialization.
  • Improvements

    • Enhanced sidebar rendering performance by streamlining how session data is accessed and displayed.

Review Change Stack

@Astro-Han Astro-Han added enhancement New feature or request P3 Low priority app Application behavior and product flows task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work labels May 11, 2026

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opus second-pass review (product layer / three questions / sidebar timestamp path)

Conclusion: approve

Diff matches the brief shape; both call sites are switched; tests lock the contract.

Three questions

Could this be even less? peekExisting is 5 lines of implementation, the type alias is a 1-liner extracted from the previously inline tuple shape, plus 2 child-store tests and 1 source-level layout invariant. Skipping the type alias would force [Store<State>, SetStoreFunction<State>] to be repeated inline; not worth the saving. Check.

Is what remains good enough?

  • peekExisting does exactly validateChildStoreDirectory + return children[directory] — no ensure, no pin, no bootstrap, no mark, no eviction.
  • Both messagesForSession and partsForMessage switched; the per-call tuple?.[0].message[session.id] keeps the existing fallback contract intact.
  • Source-level invariant test locks layout.tsx against drifting back to globalSync.child(session.directory, { bootstrap: false, pin: false }).
  • Check.

Is it reassuring? Sidebar timestamp user path traced:

  • First boot, no cache yet: peekExisting(dir) returns undefinedtuple?.[0]... short-circuits to undefinedbuildPawworkSidebarSessionRows falls back to session.time.created (covered by existing row-builder tests at line 138-143 in the same test file).
  • After directory has been visited: peekExisting(dir) returns the existing tuple → cache hit, identical to the old child(dir, { bootstrap: false, pin: false }) behavior except we no longer materialize vcs/meta/icon caches on the side.
  • Disk persistence layer untouched; no new I/O introduced.
  • Check.

Findings

No P0/P1/P2.

P3 note (not blocking): child() and peek() are now indistinguishable in semantics (both ensure + optional bootstrap; only child pins). That equivalence pre-dates this PR and is out of scope, but worth a follow-up issue if the team wants the manager surface to be smaller.

Approve

@coderabbitai

coderabbitai Bot commented May 11, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: dd19fd31-7559-45e8-9849-c8572ed335c9

📥 Commits

Reviewing files that changed from the base of the PR and between 7ac9d47 and 7f97886.

📒 Files selected for processing (6)
  • packages/app/src/context/global-sync.tsx
  • packages/app/src/context/global-sync/child-store.test.ts
  • packages/app/src/context/global-sync/child-store.ts
  • packages/app/src/context/global-sync/types.ts
  • packages/app/src/pages/layout.tsx
  • packages/app/src/pages/layout/pawwork-sidebar-session-rows.test.ts

📝 Walkthrough

Walkthrough

This PR adds a non-creating child-store peek accessor (peekExisting) to enable cache-only reads without creating, bootstrapping, or pinning directory stores. The method is wired through global-sync context to sidebar timestamp reads, reducing lifecycle side effects for cache lookups.

Changes

Non-creating Child Store Accessor

Layer / File(s) Summary
Type Definition
packages/app/src/context/global-sync/types.ts
ChildStoreTuple type alias added to represent a SolidJS store and setter tuple pair.
Child Store Manager
packages/app/src/context/global-sync/child-store.ts
Imports and uses ChildStoreTuple for internal registry; adds peekExisting(directory) method returning existing child store tuple or undefined without calling ensureChild(...); exposes peekExisting in public API.
Global Sync Context
packages/app/src/context/global-sync.tsx
Exposes peekExisting on GlobalSyncProvider context value by forwarding to children.peekExisting.
Sidebar Cache Reads
packages/app/src/pages/layout.tsx
Updates buildPawworkSidebarSessionRows to read message/part data via globalSync.peekExisting(session.directory) instead of globalSync.child(..., { bootstrap: false, pin: false }).
Child Store Tests
packages/app/src/context/global-sync/child-store.test.ts
Enhances createManager test helper to accept overrides parameter; adds test verifying peekExisting(missingDir) returns undefined without creating caches or triggering bootstrap; adds test verifying peekExisting(existingDir) returns the created store tuple.
Layout Sidebar Integration Test
packages/app/src/pages/layout/pawwork-sidebar-session-rows.test.ts
Adds test reading layout.tsx source and asserting cache reads use globalSync.peekExisting(...) without calling globalSync.child(...).

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • Astro-Han/pawwork#161: Both modify createChildStoreManager and its tests; the main PR adds peekExisting API and tuple type while this PR adds directory validation and persisted-cache error handling.
  • Astro-Han/pawwork#101: Both address child-store access patterns and lifecycle concerns; the main PR adds non-creating peekExisting accessor while this PR changes how current child is resolved to avoid provider-owned caching.

Suggested labels

bug, ui

Poem

🐰 A peek without the crashing sound,
No bootstrap stores to spin around,
Just read the cache that's waiting there,
Sidebar stats with lighter care!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding a non-creating child-store peek for sidebar timestamps, with issue reference.
Description check ✅ Passed The description is comprehensive and follows the template structure with all key sections completed: summary, why, related issue, review focus, risks, verification steps, and completed checklist.
Linked Issues check ✅ Passed The PR implements all coding requirements from #475: adds peekExisting accessor with correct semantics (no ensureChild/bootstrap/pin), integrates into sidebar timestamp reads, and includes focused tests validating non-creating behavior.
Out of Scope Changes check ✅ Passed All changes are scoped to #475 requirements: new accessor implementation, type definitions, sidebar integration, and targeted tests. No unrelated refactors, dependency changes, or broad call-site replacements introduced.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/peek-existing-child-store

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Astro-Han

Copy link
Copy Markdown
Owner Author

GPT-X engineering final review

Result: pass. I found no P0/P1/P2 issues.

Engineering checks

  • peekExisting(directory) is a true non-creating accessor: it validates the directory and returns children[directory]; it does not call ensureChild, mark, pin, pinForOwner, onBootstrap, or runEviction.
  • Existing child() and peek() semantics are unchanged. This keeps retainDirectory and the route-resolution call site working with their current tuple-return assumptions.
  • Both sidebar timestamp cache reads were switched: messagesForSession and partsForMessage now use globalSync.peekExisting(session.directory).
  • The tests cover the important invariant: missing child stores return undefined without creating children, vcsCache, metaCache, or iconCache, and an existing child tuple is still returned after normal creation.
  • The layout source-level test locks the sidebar timestamp path against regressing back to globalSync.child(session.directory, { bootstrap: false, pin: false }).

Binary check

v1 would not crash without this PR, but the previous sidebar timestamp path could still materialize per-directory child stores and persisted caches during row building. This is a focused memory/lifecycle cleanup at the correct layer: cache-only reads get a cache-only accessor, while normal create/bootstrap/pin callers keep their existing APIs.

Notes

peekExisting is intentionally non-reactive. If a future caller needs absent-to-present reactivity, that should be designed separately as a reactive registry rather than added to this cache peek API.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a peekExisting method to the globalSync context and childStoreManager, allowing for the retrieval of existing child stores without triggering new store creation or side effects. The Layout component was updated to utilize this method for session data lookups, and new tests were added to ensure correct behavior and prevent regressions. I have no feedback to provide.

@Astro-Han Astro-Han merged commit 3c15b37 into dev May 11, 2026
23 checks passed
@Astro-Han Astro-Han deleted the fix/peek-existing-child-store branch May 11, 2026 11:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app Application behavior and product flows enhancement New feature or request P3 Low priority task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Task] Add non-creating child-store cache peek for sidebar timestamp reads

1 participant