Repository navigation
OpenConceptLab/ocl_online#465 | AutoMatch dialog: first run includes the OCL AI Assistant, notices in a footer, and a checkpoint - #108
Conversation
…the OCL AI Assistant, notices move to a footer, and a checkpoint - The dialog's top holds only the choices; "Retrieve candidates" and "Recommend matches with the OCL AI Assistant" each get a short note. - Notices (replacing proposals, overwriting approved rows with its tick, AI-only rows, nothing to run) move to a footer above Submit. A notice can ask for a tick or block Submit; changing the selection clears the ticks. - The OCL AI Assistant starts ticked on a project's first AutoMatch; later runs keep the choice of the project's last run. - New checkpoint, src/components/map-projects/autoMatchCheck.js (useAutoMatchCheck and aiOnByDefault), imported as 'ocl-online-mapper'. webpack resolves that name to an installed package when there is one, and to the open stub otherwise; the Dockerfile and build.yml can install one. - New strings in en, es, zh and pt-BR; unused ones removed. The catalog test now understands plural keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
snyaggarwal
left a comment
There was a problem hiding this comment.
Verdict: Request changes
Issue complete: almost, but one accessibility regression should be fixed before merge.
[P2] Keep keyboard focus trapped inside the AutoMatch dialog
AutoMatchDialog.jsx now sets disableEnforceFocus on the MUI Dialog. That allows keyboard focus to move to controls behind the still-open modal, which breaks expected modal keyboard behavior and makes the dialog substantially harder to use with assistive technology. The new Tooltip/Alert content does not require opting out of the focus trap; please remove this prop unless there is a demonstrated nested-focus case and a replacement focus-management strategy.
Cross-repo check: the public/private checkpoint exports and selection contract match the companion package. The public diff keeps the newly moved commercial UI wording and calculations out of the open dialog.
Verification: CI is green; local oclmap test suite passes (535/535). Security blockers: none.
…trapped in the AutoMatch dialog Drops disableEnforceFocus, which let focus move to controls behind the modal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Fixed in 968a45b: removed |
snyaggarwal
left a comment
There was a problem hiding this comment.
Verdict: Approve
Re-review of 968a45b: the prior accessibility blocker is resolved. Removing disableEnforceFocus restores the Dialog's normal keyboard focus trap, and the fix introduces no other code changes.
Cross-repo review remains clean: the public checkpoint contract matches the private companion package and the open-core boundary is preserved. Verification: local oclmap tests pass (535/535), current CI and Snyk checks pass. Security blockers: none.
…ckage the way oclweb3 does PRIVATE_PACKAGES_GIT is the whole npm install spec, so the image build needs no other arguments about where the package lives. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
snyaggarwal
left a comment
There was a problem hiding this comment.
Verdict: Request changes
[P2] Keep the SSH setup conditional on the optional package
The updated Dockerfile now runs mkdir and ssh-keyscan github.com before checking PRIVATE_PACKAGES_GIT. That makes every ordinary build depend on outbound GitHub SSH access even when no optional package is configured; environments with port 22 blocked will fail before reaching the open stub. Move the SSH directory/keyscan setup back inside if [ -n "$PRIVATE_PACKAGES_GIT" ] so an unset build arg leaves the open build independent of the optional integration.
The npm-install-spec simplification otherwise looks correct. Current CI and Snyk checks pass. Security blockers: none.
… a private UI package is configured Without PRIVATE_PACKAGES_GIT the image build no longer runs ssh-keyscan, so it doesn't need outbound SSH to GitHub. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Fixed in 776e6af: |
snyaggarwal
left a comment
There was a problem hiding this comment.
Verdict: Approve
Re-review of 776e6af: the prior Dockerfile blocker is resolved. SSH directory setup and ssh-keyscan now run only when PRIVATE_PACKAGES_GIT is non-empty, so an ordinary open build remains independent of GitHub SSH access while the configured install path is unchanged.
Verification: local oclmap tests pass (535/535); current CI and Snyk checks pass. The cross-repo checkpoint and open-core boundary remain clean. No correctness or security blockers found.
paynejd
left a comment
There was a problem hiding this comment.
Review of 776e6af
The dialog matches the approved design, and the public diff keeps to the open-core line. Two things should change before this merges:
- The open build can wipe proposals. A run the existing row cut empties now gets through and clears statuses.
- The build and deploy changes need more work before the secrets are set. That's in the private review on OpenConceptLab/ocl_online#534, along with everything on OCL Online's side.
Should fix before merging
1. A run cut to zero rows still clears proposals, and autosaves (P1). Codex F1.1 below, which I reproduced.
MapProject.jsxstill cuts a run's rows before running it (L2534-L2539; that code is tracked in OpenConceptLab/ocl_online#531).- On main, the dialog disabled Submit when that cut would leave no rows. This PR moves that guard into the checkpoint, so the open build no longer has it.
- Meanwhile the run clears statuses for the whole scope before the cut (L2513-L2523).
- Reproduced with the real Mapper (open build) against a local mock API, with no production traffic. The case: a user whose cut leaves 0 rows, scope "Unmapped & proposed rows", 8 proposed rows.
- Submit is enabled.
- No run is created and no row is matched.
- The autosave writes all 8 proposed rows back as Unmapped, with no message.
- Fix:
- Work out the rows (after the cut) before touching statuses. If none are left, show
auto_match_nothing_to_runand change nothing. - Clear statuses only for the rows the run will process, as the selected-rows branch already does. That also stops a shortened run from clearing proposals on rows it never reaches, which already happens on main.
- Better still, the cut becomes a checkpoint answer, so the open build never cuts. Details on ocl_online#534.
- Work out the rows (after the cut) before touching statuses. If none are left, show
2. Build and deploy (webpack.config.js, build.yml, Dockerfile). The findings and their fixes are on ocl_online#534. Two of them need fixing before the secrets are set.
Worth fixing
3. AutoMatch opened before the project logs load takes the first-run default (P2). Codex F1.2, reproduced.
- In the mock, the rows showed at 0.6 s and the logs took 8 s. Opening AutoMatch at 1.6 s ticked the OCL AI Assistant, although the last run had it off. Reopening after the logs loaded showed it unticked.
- A failed logs request does the same for the whole session.
- The default is also re-applied every time the dialog opens (L2963-L2964). Unticking it, closing the dialog to select rows and reopening ticks it again.
- Fix: record whether the logs loaded. Apply the default once, from loaded logs (or keep AutoMatch disabled until then), and leave the box alone on later opens.
4. Apply aiOnByDefault() on every open, not only on a project's first run. This is a design decision on OpenConceptLab/ocl_online#465, 2026-10-20.
- At L2964:
setAutoRunAIAnalysis(aiOnByDefault() && getAutoMatchAIDefault(projectLogsRef.current, true)). - In
autoMatchCheck.js, the stub's comment changes to "Whether the OCL AI Assistant may start ticked when the dialog opens". - The open stub returns
true, so the open build doesn't change.
Notes (P3, no change needed unless you want it)
- Codex F1.3 (the AI model or prompt template doesn't clear ticks): no change needed. The ticks confirm row counts and overwrites, which the model doesn't change.
- PR CI (
pr.yml) never runs webpack. A broken path to the stub would only show up in main's Docker build. - The disabled "Selected rows only" tooltip keeps the old "Note:" prefix.
What I checked
- CI-exact checks:
- Lint is clean, 535 unit and 6 integration tests pass.
- Merged onto today's main (4fcd0a3), the merge is clean: lint is clean, 556 unit and 6 integration tests pass.
- Builds:
- A production build without a package has none of the checkpoint's strings; with a package installed, they're there.
- Docker builds with and without
PRIVATE_PACKAGES_GIT. Without the arg, the SSH step doesn't run. With it, npm adds exactly one package.
- The dialog: rendered against the open stub across the design's scenarios. Notices, ticks clearing on selection change, the "Selected rows only" tooltip and the phone layout all match the mockup.
- The first-run default in the real Mapper: a project never auto-matched opens ticked, and a last run without the OCL AI Assistant opens unticked.
- The open-core rule: the added lines, comments, tests, locale files, commit messages and PR text name no plan, quota, cap, limit or allowance.
getAutoMatchBlockerlost its AI-calls branch. - Strings: the 14 new keys are in all four catalogs. zh correctly has only
_otherforms.
Codex review, pass 1 (codex-cli 0.163.0, commit 776e6af)
Verdict: findings (2 × P1, 1 × P2). Severity after my checks: F1.1 P1 (reproduced), F1.2 P2 (reproduced; it needs the dialog opened within the logs request), F1.3 P3 (see above).
- F1.1 P1
AutoMatchDialog.jsx:170: the open stub now permits empty runs that erase existing row statuses. - F1.2 P1
MapProject.jsx:2964: unloaded project logs are treated as proof that this is the first AutoMatch. - F1.3 P2
AutoMatchDialog.jsx:118: changing the AI model or prompt template does not clear confirmation ticks.
findings.json
{
"reviewer": "codex-cli 0.163.0",
"perspective": "defects",
"mode": "full",
"commit": "776e6af7bc6c6dc76e1ab7475aa4a83d4c19b414",
"verdict": "findings",
"prior": [],
"findings": [
{
"id": "F1.1",
"severity": "P1",
"tag": null,
"file": "src/components/map-projects/AutoMatchDialog.jsx",
"line": 170,
"claim": "The open stub now permits empty runs that erase existing row statuses.",
"scenario": "Without the private package, Submit remains enabled when the dialog has eligible rows but MapProject's subsequent truncation produces an empty rowsToProcess list. For 'Unmapped & proposed rows' or 'All rows, including approved', getRowsResults clears the corresponding proposed/approved statuses before applying that truncation, then schedules an autosave despite processing nothing. Those rows are consequently saved as unmapped. The removed Submit guard previously prevented this path.",
"action": "Pass neutral execution eligibility to the dialog and reject empty runs before changing statuses. Restrict status changes to the rows actually processed, and add regression coverage.",
"lines_delta": null,
"confidence": "high"
},
{
"id": "F1.2",
"severity": "P1",
"tag": null,
"file": "src/components/map-projects/MapProject.jsx",
"line": 2964,
"claim": "Unloaded project logs are treated as proof that this is the first AutoMatch.",
"scenario": "Reopen a project whose latest AutoMatch omitted with_ai_analysis. The input file can finish loading before the independent logs request, allowing AutoMatch to open while projectLogsRef.current is still empty. This enables AI using the first-run default. When the logs arrive, the checkbox is never corrected; a failed logs request leaves the same incorrect default. Later runs therefore do not reliably retain their last recorded AI choice.",
"action": "Track whether project logs have loaded successfully and resolve the default from that authoritative result. Do not infer a first run from loading or failed history, and test delayed and failed log requests.",
"lines_delta": null,
"confidence": "high"
},
{
"id": "F1.3",
"severity": "P2",
"tag": null,
"file": "src/components/map-projects/AutoMatchDialog.jsx",
"line": 118,
"claim": "Changing the AI model or prompt template does not clear confirmation ticks.",
"scenario": "A staff user confirms overwriting approved rows, then selects a different AI model or prompt template in the dialog. Neither setting participates in confirmationKey, so the confirmation remains checked and Submit remains enabled for the changed selection, contrary to the acceptance criterion.",
"action": "Include stable model and prompt-template identifiers in the confirmation reset dependencies. Add a lifecycle test that distinguishes selection changes from unrelated rerenders.",
"lines_delta": null,
"confidence": "high"
}
]
}… rows they include, AI default from loaded logs, open image and deploy image built apart
There was a problem hiding this comment.
Verdict: Approve
Re-review of a686d45: the prior blockers are resolved.
- The final run row set is determined before the run mutates state; an empty set is rejected, and only rows actually included in the run lose proposed/approved statuses.
- The AI default waits for loaded project history, applies once, and later dialog opens preserve the user's choice.
- The public Docker Hub image and the deploy image are now built separately. The open image has no optional extension, while the deploy build is isolated to its protected environment and private registry.
- The optional package loader uses the scoped package name, the open stub remains the fallback, and production source maps omit source content.
Cross-repo verification: the checkpoint exports match the companion package; the private package installs and compiles through the public webpack configuration.
Verification: local tests pass (541/541), the open and extension-backed production builds complete, and current PR CI/Snyk checks pass. No correctness, boundary, accessibility, or security blockers found.
Part of OpenConceptLab/ocl_online#465 (with OpenConceptLab/ocl_online#534).
What
Dialog layout (
AutoMatchDialog.jsx)Runs change only the rows they include (
MapProject.jsx,autoMatchRows.js)getMaxRunRowsof them, and for an AI-only run the rows the OCL AI Assistant can analyse.clearRunRowStatuses). Before, a run cleared statuses across its whole scope, including rows it never reached.OCL AI Assistant default (
getAutoMatchAIOnOpen)aiOnByDefault()false opens it unticked every time.Checkpoints (
autoMatchCheck.js)useAutoMatchCheck(selection)returns{summary, notices}: a summary shown beside Submit, and notices that can carryconfirmorblocks.aiOnByDefault(): whether the OCL AI Assistant may start ticked when the dialog opens.getMaxRunRows({matchAlgorithmCount}): the most rows a run may include, ornullfor all of them.trueandnull, so the open build runs every row in scope.@openconceptlab/oclmap-extensions.webpack.config.jsresolves that name to the installed package when there is one, and to the stubs otherwise, and compiles that package's JSX with our.babelrc.getAutoMatchBlockerloses its AI-calls branch, and MapProject no longer works out its own row cut. TheeligibleRowIndexesprop replacespreviewEligibleRowIndexeson the dialog.Build
nosources-source-map: file names and line mappings, no source.Dockerfile: when thePRIVATE_PACKAGES_GITbuild arg (an npm install spec) is set, installs it over SSH with--ignore-scripts, against GitHub's pinned host keys. It logs what it installed and fails if the package didn't install. Without the arg, nothing changes and the build needs no SSH.build.ymlbuilds two images:build: the open image, pushed to Docker Hub as before, with no private package or secrets.build-private: the deploy image with the package, pushed only to ECR, with no Actions cache written. It uses theprivate-packagesenvironment, SHA-pinswebfactory/ssh-agent, and fails if the environment's secrets are missing. The deploy jobs now run this image.pr.ymlis untouched, so PR CI builds the open stubs.Strings
catalogKeys.test.jsnow accepts plural keys (_one/_other), the first in the catalogs.aiAssistantNaming.test.jscovers the new strings that name the assistant.Before merging
private-packagesenvironment in this repo, with deployments allowed only frommain, and putPRIVATE_GIT_PACKAGES_DEPLOY_KEYandPRIVATE_PACKAGES_GITin it (values on OpenConceptLab/ocl_online#534). Until thenbuild-privatefails, and nothing releases or deploys.Testing
eslintclean;npm test541 pass,npm run test:integration6 pass. New unit tests covertakeRunRows,clearRunRowStatusesandgetAutoMatchAIOnOpen.sourcesContent.build-privateand deploy jobs on GitHub.🤖 Generated with Claude Code