Skip to content

fix(persistence): preserve projectGroupOrder on restart for flat folder-scan groups - #23261

Merged
nwparker merged 3 commits into
stablyai:mainfrom
lurunzi:fix/preserve-folder-scan-project-order
Oct 3, 2026
Merged

nwparker merged 3 commits into
stablyai:mainfrom
lurunzi:fix/preserve-folder-scan-project-order

Conversation

@lurunzi

@lurunzi lurunzi commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

ELI5

If you drag beta above alpha in a folder-scan project group, restarting Orca should keep beta first.

What Changed

Before, loading a flat folder-scan group reset its projects to the order they were originally added. After, saved manual order survives restart. The existing load adapter now assigns a new order only when a project actually moves into a child group; it keeps using the existing nested-group resolver.

The original fix and initial tests are by @lurunzi. This update preserves their commit author, rebases the contribution onto current main, and strengthens the tests around closing and reopening the real Store.

Why

The adapter also runs for groups that need no migration. Limiting its order assignment to actual moves fixes the reset while preserving migration for older nested folder imports. Skipping the whole adapter would lose that migration.

Linked Issue

Related context: #22285, last updated September 23 and treated as stale context. The current production bug was independently reproduced from main adf447d958b2 before applying this recent contributor PR.

Visual Proof

Both runs load the same saved order: alpha has rank 1 and beta has rank 0. Screenshots come from hidden Electron renderers with disposable homes and profiles; their rendered order was also asserted through Playwright CDP.

Before restart loading resets the order:

Before: alpha above beta

After the fix, restart loading keeps the saved order:

After: beta above alpha

Testing

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

On macOS, before production edits the real load operation changed saved [1,0] to [0,1] while both projects stayed in the same group. A real SQLite Store close/restart failed the same way; the nested-migration control passed. The identical probe passes all three checks after the fix. Exact failing command, output, and probe source.

The committed regression checks unchanged membership and order, a closed Store restart with and without a non-Git folder, real child-group migration, preserved root/folder order, and another restart after migration. To run the focused coverage:

ORCA_BACKGROUND_LAUNCH=1 pnpm test src/main/persistence-folder-scan-project-groups.test.ts src/main/persistence-repo-lifecycle.test.ts src/main/persistence-worktree-meta-and-folder-workspaces.test.ts src/main/project-groups/nested-repo-import.test.ts
ORCA_BACKGROUND_LAUNCH=1 pnpm tc:node
ORCA_BACKGROUND_LAUNCH=1 pnpm run check:code-quality:changed

All 72 scoped product tests and 42 CI contract checks pass after integrating current main. Node typecheck, formatting, and changed-code quality pass; the previously verified feature bundle and sidebar proof remain unchanged. The hidden sidebar shows alpha then beta before, and beta then alpha after. The required repository guard and final verification passed on published head 93c2e97545cf70b19b074f9b70c83e4ff0125887. Linux and Windows apps were not launched locally.

AI Disclosure

Original contribution assisted by Antigravity (Google DeepMind). Rebase, expanded restart tests, and verification assisted by Codex.

Review

Independent read-only review found a Windows-only test path-separator mismatch, which was corrected using the existing path utility. Re-review of the final source and tests is clean. The production change remains the contributor's original relocation guard.

Pullfrog's current-head review at 93c2e97545c reports no new issues. After merging current main, both feature files and the entire feature patch still match the independent clean review byte for byte. Its current review confirms the unchanged feature files and passing restart tests after the main merge; its prior review also checked failures with the old guard and the Windows path expectation.

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Merge risk: low; the change is limited to load-time order assignment and retains the existing migration and save path. Negative user-facing tradeoffs: none identified. Scope is local persistence, with no remote/SSH repair or wire-contract change. The branch includes main’s existing correction to two package-list contract assertions (#24785), which caused the prior CI failure; that correction adds no files to this feature diff.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • Scoped tests, node typecheck, formatting and changed-code quality pass locally; hidden Electron proof is attached, and required current-head CI passes

@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: ed587f1c-1b81-4093-85ca-75e1c0e3ef24

📥 Commits

Reviewing files that changed from the base of the PR and between f27f698 and 93c2e97.

📒 Files selected for processing (1)
  • src/main/persistence-folder-scan-project-groups.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The loading adaptation now assigns a project group order only when a repo’s group ID changes. Tests verify that existing orders survive reload and that migration assigns orders to moved repos while preserving the group assignments and orders of other repos and the folder repo.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 93c2e

No actionable merge-blocking issue remains with preserving folder-scan project order across restarts.

Security Architecture Review

Security architecture risk: 🔵 Low · up to f27f6

The change preserves custom ordering without adding a new access path or changing permissions. Remaining uncertainty concerns coverage of interrupted migrations, not an identified security defect.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The observed effect is limited to project-group ownership and ordering in the loaded profile state and its existing save path.

Trust Boundaries and Controls

  • observed — The Store requires a profile-state authority for writable construction and freezes writes for imported serialized state; this change does not alter those checks.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the main change: preserving projectGroupOrder after restart for flat folder-scan groups.
Description check ✅ Passed The description is complete and follows the repository template. It explains the user impact, implementation, reason, linked issue context, visual proof, testing, AI disclosure, review, compatibility …

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.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • Guard narrowed in adaptFlatFolderScanProjectGroups() — assignment/re-indexing now happens only when repo.projectGroupId !== group.id, so repos already in a flat folder-scan root group keep their manual projectGroupOrder instead of being renumbered 0,1,2… on every load.
  • New tests in src/main/persistence-folder-scan-project-groups.test.ts pin both the preservation path and the migration path (root orders kept, child repos indexed from 0).

The change is correct and minimal. The candidate set is filtered to repo.projectGroupId === rootGroup.id, and getGroupForRepo returns either the root group or a freshly created child, so the new condition is exactly "migrating into a new child group". I also verified the tests are not tautological: reverting the source hunk to the old guard makes both fail (r1 5 → 0, api 10 → 0). Downstream order consumers (getEffectiveProjectGroupManualRank, getNextProjectGroupOrder, the renderer project-group-sections.ts) tolerate sparse and undefined orders via the documented global-repo-order fallback, so nothing depends on contiguity.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

lurunzi added a commit to lurunzi/orca that referenced this pull request Sep 27, 2026
lurunzi and others added 2 commits October 2, 2026 04:48
…er-scan groups

When repositories inside a flat folder-scan project group (without nested sub-groups) were manually reordered in the sidebar, adaptFlatFolderScanProjectGroups re-assigned sequential orders based on raw array index on every launch because childGroupIds.has(rootGroup.id) evaluated to false.

Only re-assign and re-index projectGroupOrder when a repository actually migrates into a newly created child group. Repositories staying in the group retain their manual ordering.
@nwparker
nwparker force-pushed the fix/preserve-folder-scan-project-order branch from f27f698 to cf77dfa Compare October 2, 2026 12:00

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • Expanded flat-group restart coverage — replaced the single reload check with a unit-level test (leaves unchanged group membership and manual order clean on load) plus an it.each([false, true]) test that closes and reopens a real Store and asserts both the persisted JSON and the reloaded repos keep the saved [1, 0] order, with and without a non-Git folder repo.
  • Hardened the migration test's cross-platform paths — switched from hard-coded /workspace/... to join(parentPath, …) and wrapped the expected child-group parentPath in normalizeRuntimePathSeparators, matching the forward-slash normalization the resolver already applies.
  • Added a folder-repo assertion to the migration path — a kind: 'folder' repo in the root group now asserts it stays in the root group with its projectGroupOrder untouched, pinning that folder repos are excluded from migration candidates.

The source change is unchanged since the prior review. I re-ran the focused suite on head and confirmed the expanded tests still fail when the source hunk is reverted to the old guard (adaptFlatFolderScanProjectGroups() returns true, r1 1→0 / r2 0→1, api 10→0), so they pin the bug rather than passing tautologically. Child-group parentPath normalization was verified against resolveFolderPath → trimPathSeparators, so the Windows path expectation is sound.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

The delta since Pullfrog's last review (cf77dfaa) is a single merge commit (93c2e97) that brings current main (f2257ffa) into the branch. The PR's two feature files are byte-identical to the previously reviewed state — the diff against the merge-base remains the one guard hunk in adaptFlatFolderScanProjectGroups() plus the test file.

  • Merged main into the branch — 93c2e97 syncs 188 upstream files into the branch, but leaves the feature patch untouched; the load-order guard and its tests are unchanged from the cf77dfaa review.
  • Re-verified the focused suite on the merged head — pnpm test src/main/persistence-folder-scan-project-groups.test.ts still passes all 4 tests, so the main sync introduced no semantic conflict with the migration guard or its assertions.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@nwparker

nwparker commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Final merge review at 93c2e97545cf70b19b074f9b70c83e4ff0125887: the complete changed source matches the independently reviewed commit, and the documented required repository checks pass: detect changes and check repository guards, verify.

Retain saved project ranks when the project remains in its folder-scan group.

Merge risk and retained limits: Low: persisted ordering and nested-group migration.

Contributor authors and existing co-author credit will be preserved explicitly in the squash commit.

@nwparker
nwparker merged commit 81e69f3 into stablyai:main Oct 3, 2026
25 checks passed
@lurunzi
lurunzi deleted the fix/preserve-folder-scan-project-order branch November 8, 2026 23:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants