Repository navigation
OpenConceptLab/ocl_issues#2872 | auto match should not run when no algos are configured and/or without any existing candidates - #92
Conversation
… are configured without any existing candidates
paynejd
left a comment
There was a problem hiding this comment.
Thanks, Sunny. I reviewed this against the acceptance criteria in OpenConceptLab/ocl_issues#2872, and Codex reviewed it independently; its review follows this one. Lint and all 418 tests pass locally at 6c96eaf, as in CI.
Where it stands: criteria 1–3 are met, and 6 is met in the normal cases. The empty-run guard (4 and 5) covers a project with no algorithm, but not one whose algorithms this user can't run. That's the one change I'd make before merging.
Before merge
- Algorithms the user can't run (inline, on
hasAutoMatchWork): if a project's only algorithm is a bridge or ScispaCy that the person opening it can't run, Auto Match still starts a run that does nothing and records it asfailed, 0/0. That's the ticket's symptom again. Codex's finding 2 is the same issue. - Copy (one-click suggestions on
en): the new strings should name the OCL AI Assistant, as the newer quota strings do ("OCL AI Assistant calls"), and avoid "AI recommendations".esandzhneed the same change; those catalogs already use "asistente de IA de OCL" and "OCL AI 助手". The olderpreview_estimate_ai_*strings (lines 518–520) have the same problem, and AI-only runs now show them too. Fixing those here or in a later PR are both fine.
Smaller
- A rerank throttle shouldn't mark an AI-only run partial (one-click suggestion on
attribution.js): this is Codex's finding 5. - Opening the dialog scans every row (inline, on
onGetCandidates): it takes about 0.25–0.5 s per open on a 2,000-row project, for everyone with AI access. It's also why the count goes stale while the dialog is open (Codex's finding 3). - Codex's findings 1 and 4 are real, but each needs narrow timing. Finding 1 needs a Stop and a restart while an AI call is still in flight, and finding 4 needs a candidate response that lands mid-run and restores an earlier pool. Codex rates 1 as P1; I'd treat both as follow-ups. For 1, the AI step's stage writes could get the same
isCurrentRun()guard thatprocessBatchalready gives algorithm stages throughsetStage.
paynejd
left a comment
There was a problem hiding this comment.
Codex adversarial review, pass 1 (codex-cli 0.160.1, commit 6c96eaf)
Read-only, reasoning effort xhigh, given the acceptance criteria in OpenConceptLab/ocl_issues#2872. Posted verbatim; file references link to this commit. The review above says which findings I'd fix before merge.
The PR fixes the original empty-algorithm case, but does not fully satisfy OpenConceptLab/ocl_issues#2872. Five findings, ranked by severity:
-
[P1] Stopped AI requests can corrupt a later run’s counts —
src/components/map-projects/MapProject.jsx:5802. Stop run A while row 0’s AI request is pending, then start B on rows 0–1. B’s row 0 fails; A’s late success overwrites its sharedrecommendstage while B processes row 1. B then records completed 2 / failed 0, instead of completed 1 / failed 1, partial. Reproduced using the extracted functions with deferred responses. Fix: associate AI stage, failure and quota writes with a captured run ticket, or maintain outcomes per run. -
[P2] Configured but unavailable algorithms still permit empty runs —
src/components/map-projects/MapProject.jsx:2910. Load a project containing only a bridge withcanBridge=false, or ScispaCy withcanScispacy=false. With AI off, the guard accepts Submit and opens an AutomatchRun, but the executor skips retrieval; it closes failed, 0/0. With AI on, successful recommendations still produce failed, 0/0, because the selected algorithm preventsaiOnlyclassification. Fix: use executable algorithms consistently for dialog availability, work detection and run classification. -
[P2] AI eligibility freezes when the dialog opens —
src/components/map-projects/MapProject.jsx:2899. Start a manual AI request, then open Auto Match before it finishes and choose AI only. When the manual request succeeds, the dialog still says analyze 1 / skip 0 and enables Submit. Submit recomputes eligibility and rejects the run. Candidate changes can conversely leave useful work blocked. Fix: derive eligibility from current analysis and candidate state while the dialog is open. -
[P2] Skipped AI rows can count as newly completed analyses —
src/components/map-projects/MapProject.jsx:5842. A row has an earlier analysis for pool A and currently has pool B, so the AI-only prefilter includes it. A pending manual candidate response restores pool A before AI processing.fetchRecommendationskips invocation but writesrecommend=1because analysis history exists. The run records completed 1 despite zero AI invocations; reproduced in memory. Fix: distinguish skipped rows from successful invocations in run accounting. -
[P2] Unrelated rerank outcomes affect AI-only completion —
src/services/attribution.js:175. A background manual rerank finishes throttled during an AI-only run. Every AI invocation succeeds, butstage.rerank === -4makes the run partial. Fix: ignore rerank stages whenaiOnlyis true.
| Acceptance criterion | Verdict |
|---|---|
| 1. No algorithms: warning, Configure, retrieval off/disabled | Met |
| 2. AI-only analyze/skip counts match actual work | Partly met — correct for stable state; eligibility freezes |
| 3. Messages update with scope and checkboxes | Met — recomputed from the cached eligibility set |
| 4. Block only empty runs, with a reason | Partly met — unavailable algorithms bypass blocking; stale eligibility can block work |
| 5. Empty runs open no AutomatchRun | Partly met — original case guarded; unavailable algorithms remain a counterexample |
| 6. AI-only completion reflects AI work | Partly met — straightforward success/error/quota cases work; findings 1, 2, 4 and 5 break accounting |
Ordinary algorithm submission, AI-only preservation of row statuses, scope filtering and preview caps look clean. No new hook violations or missing en/es/zh keys or placeholders found.
Validation: 412 tests passed; ESLint and diff whitespace checks passed. No files modified; no network used.
paynejd
left a comment
There was a problem hiding this comment.
Thanks, Sunny, this covers everything from pass 1. I re-reviewed 87c9775 against those items and OpenConceptLab/ocl_issues#2872, and Codex ran a second pass (posted next). Lint and all 423 tests pass locally, as in CI.
| Pass-1 item | At 87c9775 |
|---|---|
| Algorithms the user can't run | Fixed. canRunAlgorithm drives the dialog, hasAutoMatchWork and _selectedAlgos, so isAIOnly and the run record match what runs. |
| OCL AI Assistant naming | Fixed in en, es and zh, including the older preview_estimate_ai_* strings. |
| Rerank throttle in an AI-only run | Fixed, with a test. |
| Opening scan and frozen count | Fixed. Counted only while the dialog shows an AI-only run, and recounted as analyses or candidates change. One dependency is missing (inline). |
| Codex 1: a late AI result corrupting the next run | Fixed. Superseded calls leave stages and the failure count alone, and an AI-only run is recorded from its own outcomes. |
| Codex 4: skipped rows counted as analysed | Fixed. A skipped row returns null and counts as neither. |
I also checked the riskier parts of the commit. No caller used fetchRecommendation's old boolean return. The new memo sits after getAIAnalysableRows, with no early return before it. Every rowMatchStateRef and conceptCacheRef write is paired with its state setter, so the memo sees candidate changes.
Three small items, all one-click:
- A stopped row can still call the AI (line 5714): Codex pass 2, finding 1.
isSuperseded()already covers it. - The AI-only count misses the target repo loading (line 5676): Codex pass 2, finding 3.
- Spanish register (
es): the new strings switched to usted, while the strings around them use tú, and the preview estimate joins both into one alert.
Codex's pass-2 findings 2 and 4 come from older shared state, and both need narrow timing:
- Finding 2: a stopped run's late quota refusal still sets the page-wide AI quota flag.
- Finding 4: a submit while a single-row AI call is in flight reads the analysis history from before that call lands, so it can analyse the row again.
I'd take both in a follow-up rather than hold this PR. With the three suggestions applied, it's ready from my side.
paynejd
left a comment
There was a problem hiding this comment.
Codex adversarial review, pass 2 (codex-cli 0.160.1, commit 87c9775)
Read-only, reasoning effort xhigh, given the acceptance criteria in OpenConceptLab/ocl_issues#2872 and both pass-1 reviews. Posted verbatim, except that file references link to this commit and its "Your #N" labels read "Pass-1 finding N".
Reviewed both diffs at 87c9775. Most pass-1 fixes work, but OpenConceptLab/ocl_issues#2872 is not fully met.
-
[P1] Stopped AI work can resume under a newer run —
src/components/map-projects/MapProject.jsx:5714. Stop A while it awaits a candidate lookup, then start B. B resetsabortRef; A’s lookup finishes and A sends an AI invocation, consuming quota with B’s current attribution. Reproduced using extracted functions. Fix: check the captured run ticket after awaits, before sending, and in retry cancellation. -
[P2] Late quota responses still corrupt another run’s outcome —
src/components/map-projects/MapProject.jsx:5847. Passingnullas the row ID prevents stage writes, buthandlePreviewLimitErrorstill sets shared quota state. A stopped A’s late quota rejection can make B record completed 2 / failed 0, partial, although both B invocations succeeded. Reproduced. Fix: suppress superseded requests’ run-state writes and retain quota-stop state per run. -
[P2] The eligibility memo misses target-repository changes —
src/components/map-projects/MapProject.jsx:5676. Open AI-only Auto Match before the asynchronous canonical-URL fetch finishes. For a saved candidate identified by its canonical reference, eligibility changes from zero to one when metadata arrives, but the dialog stays analyze 0 / skip 1 and blocks Submit until scope changes. Reproduced with the actual payload builder and memo expression. Fix: include repository/context and other payload inputs in memo dependencies. -
[P2] Execution uses an outdated analysis snapshot —
src/components/map-projects/MapProject.jsx:5705. Submit AI-only while a manual analysis is pending; that analysis succeeds before the delayed bulk invocation. The bulk closure still sees the pre-Submit history and analyses the same candidates again, spending another call. Reproduced. Fix: read current analysis through a synchronized ref when filtering rows and immediately before invocation.
The cancellation and analysis-snapshot races already existed at pass 1. The new memo remains incomplete; I found no separate regression in the other areas checked.
| Pass-1 item | Status at HEAD | Location |
|---|---|---|
| Reviewer: use executable algorithms consistently | Fixed — dialog, guard and executor agree | src/components/map-projects/MapProject.jsx:628, :2439, :2916; AutoMatchDialog.jsx:88 |
| Reviewer: OCL AI Assistant naming in en/es/zh | Fixed | src/i18n/locales/en/translations.json:601; es/translations.json:565; zh/translations.json:590 |
| Reviewer: ignore rerank for AI-only completion | Fixed | src/services/attribution.js:176 |
| Reviewer: avoid full-project opening scan; keep counts live | Partly fixed — scans only the AI-only scope and responds to candidate/analysis changes; finding 3 remains | src/components/map-projects/MapProject.jsx:5671 |
| Pass-1 finding 1: stopped requests corrupt later counts | Partly fixed — original late-success reproduction now correctly records 1 completed / 1 failed, partial; quota isolation remains incomplete | src/components/map-projects/MapProject.jsx:1940, :5847 |
| Pass-1 finding 2: unavailable algorithms permit empty runs | Fixed | src/components/map-projects/MapProject.jsx:2439, :2916 |
| Pass-1 finding 3: eligibility freezes while dialog is open | Partly fixed — manual-success scenario works; repository changes still freeze it | src/components/map-projects/MapProject.jsx:5676 |
| Pass-1 finding 4: skipped rows count as completed analyses | Fixed — skipped calls return null, excluded from run outcomes |
src/components/map-projects/MapProject.jsx:2673, :5865 |
| Pass-1 finding 5: rerank affects AI-only completion | Fixed | src/services/attribution.js:176 |
| Acceptance criterion | Verdict |
|---|---|
| 1. No algorithms: warning, Configure, retrieval off/disabled | Met |
| 2. Accurate AI-only analyse/skip eligibility | Partly met — findings 3–4 |
| 3. Messages update with scope and checkboxes | Met |
| 4. Block only empty runs, showing the reason | Partly met — finding 3 blocks useful work |
| 5. Empty runs open no AutomatchRun | Partly met — finding 4 permits a redundant run after its useful work finishes |
| 6. AI-only completion reflects its AI work | Partly met — finding 2 |
Retrieve Candidates state ownership, runnable-algorithm filtering, AI-only row-status preservation, preview-cap and quota-estimate arithmetic, hooks order and TDZ checks are clean. Changed locale keys and placeholders match across en/es/zh.
Validation: 417 unit tests and 6 integration tests passed; ESLint and both diff whitespace checks passed. Adversarial reproductions ran in memory. No files modified; no network used.
Co-authored-by: Jonathan Payne <paynejd@gmail.com>
Co-authored-by: Jonathan Payne <paynejd@gmail.com>
Linked Issue
Closes OpenConceptLab/ocl_issues#2872