Repository navigation
OpenConceptLab/ocl_issues#2929 | Repo panels ask only the version the URL names after Back, Forward or a version change - #95
Merged
snyaggarwal merged 4 commits intoNov 5, 2026
Conversation
… version the route asks for After Back, Forward or a version change, RepoHome keeps the previous route's repo in state until the new one loads. The concept and mapping panels built their requests from it and load once per URL, so they asked the version the page had left and kept showing its answer, or a 404 when the resource isn't in that version. Gate the panels on the check the concept list already uses (#68), in a pure helper with tests. The reference panel gets the same gate: its Expansion Results tab asked the wrong version too. RESERVED_ROUTE_KEYWORDS moves into repoRoute.js, its only user, so the helper's tests can run real route parsing under node:test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AaZ4qTkzts4TQWehztSkyg
…es for a version the page has left Press Back while the picked version is still loading, and its late response replaced the repo and route marker in state. The list and panel then waited for a route that was gone: a blank page under the wrong version chip. A late expansions response did the same on a collection, after pointing the panel at the version the page had left. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AaZ4qTkzts4TQWehztSkyg
…asking its version for more A concept panel that closed with a request still out carried on when the answer came: it asked $cascade of the version the page had just left, and the first $cascade's answer started a second one. The panel now closes on every version change, so these were the last requests against the wrong version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AaZ4qTkzts4TQWehztSkyg
paynejd
commented
Nov 4, 2026
paynejd
left a comment
Member
Author
There was a problem hiding this comment.
Codex review, pass 1 (codex-cli 0.166.0, commit 37c4406)
Clean.
findings.json
{
"reviewer": "codex-cli 0.166.0",
"perspective": "defects",
"mode": "full",
"commit": "37c440666e54847768ba798b7facb70fde50a4ca",
"verdict": "clean",
"prior": [],
"findings": []
}…review Drop test lines that repeat others, a renaming wrapper and defaults that change nothing. Guard only the follow-up request in getMappings, and shorten the helper's comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AaZ4qTkzts4TQWehztSkyg
paynejd
commented
Nov 4, 2026
paynejd
left a comment
Member
Author
There was a problem hiding this comment.
Simplification review (commit 37c4406)
9 items.
- S1 · dup-test · src/components/repos/tests/panelReady.test.js:25 · lines 25-26 repeat line 24: the helper never reads the tab → nothing replaces them (-2)
- S2 · dup-test · src/components/repos/tests/panelReady.test.js:31 · lines 31-32 are weaker forms of lines 45-47 → nothing replaces them; line 30 and lines 46-47 cover the ready path (-2)
- S3 · dup-test · src/components/repos/tests/panelReady.test.js:45 · line 45 repeats line 46, which also varies the resource → nothing replaces it (-1)
- S4 · dup-test · src/components/repos/tests/panelReady.test.js:41 · line 41 mirrors line 40, though it alone catches a one-way change → nothing replaces it; keep it to pin both directions (-1)
- S5 · yagni · src/components/repos/tests/panelReady.test.js:9 · a wrapper that only renames parseRepoPath → call parseRepoPath directly (-1)
- S6 · shrink · src/components/repos/tests/panelReady.test.js:13 · three falsy defaults in the test helper change nothing → leave them out (-3)
- S7 · shrink · src/components/concepts/ConceptHome.jsx:186 · the early return in getMappings only needs to stop the follow-up → guard just the getInverseMappings call (-2)
- S8 · delete · src/components/concepts/ConceptHome.jsx:67 · setting aliveRef true in the effect guards a case that needs StrictMode or Fast Refresh → drop it; if it stays, one-line the cleanup (-5)
- S9 · shrink · src/components/repos/panelReady.js:3 · the header comment restates the function name and repeats itself → a two-line comment (-1)
findings.json
{"reviewer":"claude subagent","perspective":"simplify","mode":"full","commit":"37c440666e54847768ba798b7facb70fde50a4ca","verdict":"findings","prior":[],"findings":[{"id":"S1","severity":null,"tag":"dup-test","file":"src/components/repos/__tests__/panelReady.test.js","line":25,"claim":"Cut lines 25-26. They repeat line 24: isPanelReady never receives the tab and isSameRepoScope compares only repo identity and version, so the mappings and references variants take the same branch and do not show that those panels wait. In a mutation check against 13 variants of isPanelReady, every variant these two lines catch is also caught by lines 20, 24, 36 or 40.","scenario":null,"action":"Nothing replaces them; line 24 stays.","lines_delta":-2,"confidence":"high"},{"id":"S2","severity":null,"tag":"dup-test","file":"src/components/repos/__tests__/panelReady.test.js","line":31,"claim":"Cut lines 31-32. Each compares a versioned route with an identical versioned repo route, which is a weaker form of lines 45-47, where the resource, tab or expansion also differs. Line 32 changes only the tab and version strings, and the tab is never read. Line 30 stays as the no-version case. The mutation check found nothing only these lines catch.","scenario":null,"action":"Nothing replaces them; line 30 and lines 46-47 cover the ready path.","lines_delta":-2,"confidence":"high"},{"id":"S3","severity":null,"tag":"dup-test","file":"src/components/repos/__tests__/panelReady.test.js","line":45,"claim":"Cut line 45. Line 46 already varies the resource (456 against none) and the tab, so a scope check that wrongly compared resources fails on line 46 as well. Line 45's only extra is that it names the resource case alone.","scenario":null,"action":"Nothing replaces it; line 46 stays and the test title still holds.","lines_delta":-1,"confidence":"medium"},{"id":"S4","severity":null,"tag":"dup-test","file":"src/components/repos/__tests__/panelReady.test.js","line":41,"claim":"Line 41 mirrors line 40 through the same symmetric version ===, so it could go. It is not a pure duplicate: it is the only line that catches a one-way change where a no-version route accepts a HEAD repo. Nothing in the repo does that today; line 40 still catches the two-way version of that change. Keep it if the HEAD and no-version pair is meant to be pinned in both directions.","scenario":null,"action":"Nothing replaces it; line 40 stays, and the test title loses 'each'.","lines_delta":-1,"confidence":"low"},{"id":"S5","severity":null,"tag":"yagni","file":"src/components/repos/__tests__/panelReady.test.js","line":9,"claim":"const route = path => parseRepoPath(path) is a renaming wrapper used only inside isReady.","scenario":null,"action":"Call parseRepoPath directly on lines 11-12.","lines_delta":-1,"confidence":"high"},{"id":"S6","severity":null,"tag":"shrink","file":"src/components/repos/__tests__/panelReady.test.js","line":13,"claim":"The three falsy defaults in isReady change nothing: isPanelReady treats undefined the same as false for all three. All 16 assertions gave their expected results with the defaults removed, run by a scratch script that re-encodes them against the real module.","scenario":null,"action":"const isReady = (path, repoPath, overrides = {}) => isPanelReady({route: parseRepoPath(path), repoRoute: repoPath ? parseRepoPath(repoPath) : null, ...overrides}), keeping the existing line breaks.","lines_delta":-3,"confidence":"medium"},{"id":"S7","severity":null,"tag":"shrink","file":"src/components/concepts/ConceptHome.jsx","line":186,"claim":"The early return in getMappings' .then only needs to stop the follow-up request, as the comment on line 64 says. The other work in that handler is state setters, which do nothing after unmount on React 18, plus a pure filter. Trade-off: this differs from the early-return form on line 81, which has to stay because it stops several follow-ups.","scenario":null,"action":"Remove lines 186-187 and change the last line of the handler to: !directOnly && aliveRef.current && getInverseMappings(concept, includeRetired)","lines_delta":-2,"confidence":"medium"},{"id":"S8","severity":null,"tag":"delete","file":"src/components/concepts/ConceptHome.jsx","line":67,"claim":"aliveRef.current = true guards a case that can't happen here. useRef(true) already starts true, and the cleanup runs only at unmount. A re-run of the effect with the ref preserved would need StrictMode or React Fast Refresh, and grep finds neither in src, public, package.json, .babelrc or webpack.config.js. Trade-off: this diverges from RepoHome's copy of the pattern (line 344), and whoever turns on StrictMode later would have to restore the line, so if it stays, one-lining the cleanup still saves 2 lines.","scenario":null,"action":"Nothing replaces the line; lines 66-71 become React.useEffect(() => () => { aliveRef.current = false }, []). If the line stays: return () => { aliveRef.current = false }, the form used in src/hooks/useMapProjectCount.js.","lines_delta":-5,"confidence":"medium"},{"id":"S9","severity":null,"tag":"shrink","file":"src/components/repos/panelReady.js","line":3,"claim":"The first sentence of the header comment restates the function name, and the last two sentences each describe the repo the previous route left in state.","scenario":null,"action":"// A panel builds its requests from the repo it's given and loads once per URL. Back and Forward leave the\n// previous route's repo in state until the route's own has loaded, and a panel opened on it asks that version.","lines_delta":-1,"confidence":"medium"}]}
Member
Author
Response to the simplification review
|
paynejd
commented
Nov 4, 2026
paynejd
marked this pull request as ready for review
November 4, 2026 18:08
1 task
snyaggarwal
approved these changes
Nov 5, 2026
snyaggarwal
deleted the
OpenConceptLab/ocl_issues#2929-panel-version-gate
branch
November 5, 2026 02:31
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.
What changed and why
On a repository page, after Back, Forward or a version change, the concept and mapping panels could ask the version the page had just left. RepoHome keeps the previous route's
repoin state until the new one loads, and the panels build their request URLs from it.The ticket asks whether that's one wasted request or wrong data. It's wrong data. A panel loads once per URL, so when the right repo arrives it doesn't ask again. On
main, after the ticket's steps, the panel keeps showing the version just left while the URL and the version chip name another. When the resource isn't in the version just left, the panel says "this mapping could not be found" about a mapping that exists.Three changes, one commit each, then a fourth with the cuts from the simplification review:
panelReady.js,RepoHome.jsx). Panels open only whenisSameRepoScope(repoRoute, route), the check the concept list got in OpenConceptLab/ocl_issues#2910 | Repository default view; the Hierarchy view ignores filters #68. A version change now always closes the panel for a render, so it remounts with the right repo.RepoHome.jsx). The gate alone leaves two races, both already onmain. Press Back while a picked version is still loading, and its late response replaced the repo in state: a blank list and panel under the wrong version chip. On a collection, a late expansions response first pointed the panel at the wrong version, then blanked the page. Responses for a version the page has left are now dropped.ConceptHome.jsx). A panel closed with a request still out carried on when the answer came, and asked$cascadeof the version just left. That's the request the ticket describes. It now stops.Two things beyond the letter of the ticket:
main: with Expansion Results open, reload, then go Back to a version that has to load, and its list asks the version just left.RESERVED_ROUTE_KEYWORDSmoves fromconstants.jsintorepoRoute.js, its only user.constants.jsimportspackage.json, which keptrepoRoute.jsfrom loading undernode:test.Behavior to check in review:
How I tested
The
pr.ymlgate, every step as written, on Node 22, from a clean export of the commit: secret-variable check passes,npm cipasses,./node_modules/eslint/bin/eslint.js src --ext .jsx,.jspasses,npm testpasses 122 of 122. The eslint step ran from an export because inside a worktree nested in a checkout, ESLint also loads the outer checkout's config. In the worktree itself,--no-eslintrc -c .eslintrc.jsonalso passes. PR checks pass on the same commit.Unit tests:
src/components/repos/__tests__/panelReady.test.js, 8 tests on real route parsing. Removing the scope check from the helper fails 4 of them. They cover the decision only: this repo can't render components in a test, so the browser check covers RepoHome and the panels.Browser check: headless Chromium, fresh context, 1440x900,
npm startagainst the staging API, anonymous and read-only, on a public source and a public collection with released versions. The script records every concept and mapping request with the version it targets, and stamps each detail response with that version, so the panel's header says whose data it shows. Slow-response scenarios delay one request in the browser. The same script ran on the base commit and on this branch's last commit, and I looked at the screenshots from both. 14 of 18 scenarios fail onmain, with 30 requests to the wrong version. On this branch none fail, and no request goes to the wrong version.main(d6c42b3)$cascadeto the version just left$cascadeto the version just left$cascadeis out$cascadeto the version just leftI also sampled every animation frame during a Back and a Forward between two cached versions with a panel open. No frame loses the split layout: the panel shows its skeleton, then the right version.
No UI strings or components changed, so there's no locale or Design System work.
Review
Codex pass 1 and its final check on the cuts were both clean. The simplification review listed 9 items: 6 applied, 2 applied in part and 1 kept, each answered in the comments below. Nothing is open.
Acceptance criteria
panelReady.test.jspins the gate.Docs
None changed. No doc describes this behavior (README, AGENTS.md). New comments say why the gate and the guards exist.
Chose not to do
Noticed, not fixed
Both checked in the browser on this branch. This PR doesn't touch either path.
latest/response overrides a pick. On a bare repo URL, pick a version while the latest one is still resolving: the page moves to your pick, then jumps to the latest version.closes OpenConceptLab/ocl_issues#2929
🤖 Generated with Claude Code
https://claude.ai/code/session_01AaZ4qTkzts4TQWehztSkyg
Written by an Octoad session worker (
worker-v0.17, recipelean-loop, flowpublic>public, runopenconceptlab-ocl-issues-2929-20261104-114900).