Skip to content

feat(studio): make source configuration usable and deduplicated - #51

Merged
2233admin merged 3 commits into
mainfrom
codex/source-card-config-20260728
Jul 28, 2026
Merged

feat(studio): make source configuration usable and deduplicated#51
2233admin merged 3 commits into
mainfrom
codex/source-card-config-20260728

Conversation

@2233admin

@2233admin 2233admin commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Outcome

  • turn each configured source into an expandable settings card with undoable removal
  • classify market, official disclosure, financial media, social, and video sources without treating A-shares as a source type
  • reuse the live OpenCLI catalog, including Tongdaxin, SZSE, Douyin, and Bilibili capabilities
  • separate capability identity from configured source instances so different queries are not collapsed as duplicates
  • preserve positional command arguments and add bilingual presentation/search aliases

Duplicate audit

  • live OpenCLI catalog: no duplicate capability IDs or duplicate site/command/access tuples
  • curated source groups: no repeated capability IDs
  • same command with different arguments remains a distinct configured source instance
  • Gelonghui remains an explicit unavailable gap; no fake runnable node was added

Verification

  • node capability/tool catalog: 15/15
  • OpenCLI business workflows: 6/6
  • workflow regressions: 51/51
  • TypeScript: passed
  • targeted ESLint: passed
  • git diff check: passed
  • independent verifier: PASS

No backend contract changes.

@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@repowise-bot

repowise-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown

✅ Health: 8.9

📋 At a glance
5 new findings introduced.

🚨 Change risk: 9.3/10 (high)
This change's risk is driven by:

  • more lines added than baseline
  • more scattered than baseline

📊 Full report · ⭐ Star Repowise · 📥 Install bot · Last updated 2026-07-28 03:41 UTC
Silence on a single PR with [skip repowise] in the title · Per-repo toggle on repowise.dev/settings?tab=bot

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added site-directory browsing, featured results, category navigation, and back navigation to the OpenCLI command palette.
    • Added grouped content-type selection for OpenCLI sources, including video sources.
    • Added new market, financial-report, short-video, and video discovery sources.
    • Added bilingual labels and descriptions for the updated navigation experience.
  • Bug Fixes

    • Source removal can now be undone.
    • Improved search selection and prevented unrelated market settings from being changed.

Walkthrough

OpenCLI now supports site-directory navigation, selected-site command browsing, grouped source presets, undoable removal, expanded adapter catalogs, positional-argument-aware source identity, scoped market updates, stricter catalog decoding, and updated workflow and regression coverage.

Changes

OpenCLI catalog navigation

Layer / File(s) Summary
Directory browsing and keyboard selection
frontend/components/flow/command-palette.tsx, frontend/lib/plugins/opencli-adapter-catalog.ts
The palette supports categorized site browsing, selected-site command lists, back navigation, reset behavior, revised limits, localized copy, and site-aware keyboard candidates.
Adapter catalog and workflow sources
frontend/lib/workflow/backend-opencli-adapter-nodes.ts, frontend/lib/workflow/opencli-business-workflows.ts, frontend/lib/workflow/studio-templates.ts
Featured market, social, and video capabilities are expanded, duplicate nodes are removed, bilingual search text is improved, and workflow source labels, domains, presets, and template text are updated.

OpenCLI source management

Layer / File(s) Summary
Source editor presets and removal flow
frontend/components/flow/inspector.tsx
The inspector adds grouped preset selection, acronym labels, keyed remounting, conditional business parameters, and undoable removal.
Source identity and market scoping
frontend/lib/workflow/source-business-config.ts
Source conversion preserves validated positional arguments, source keys include them, and market values are read or updated only for market-group sources.
Catalog decoding and regression coverage
backend/workflow/opencli_adapter_nodes.py, tests/integration/test_workflow_capabilities_api.py, frontend/scripts/check-node-capability-catalog-regressions.mjs
Catalog decoding no longer replaces invalid UTF-8, and integration and fixture-driven regressions cover decoding, source scoping, expanded capabilities, palette behavior, and inspector wiring.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CommandPalette
  participant OpenCLICatalog
  User->>CommandPalette: Open tools view
  CommandPalette->>OpenCLICatalog: Group sites and categories
  OpenCLICatalog-->>CommandPalette: Return directory entries
  User->>CommandPalette: Select a site
  CommandPalette->>OpenCLICatalog: Read site commands
  OpenCLICatalog-->>CommandPalette: Return grouped commands
Loading

Possibly related PRs

Poem

A rabbit browsed sites in a bright little den,
Found commands grouped neatly, then searched them again.
Sources can return when removed from the floor,
While new market tools hop through the door.
Catalogs and workflows now sing in a row—
With safer text paths wherever they go.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main Studio change: making source configuration usable and deduplicated.
Description check ✅ Passed The description matches the changeset and covers the main UI, catalog, deduplication, and argument-preservation updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/components/flow/inspector.tsx`:
- Around line 128-133: Update sourceCardLabel so English output preserves
customized source.label values for built-in sources; derive the ID-based label
only when source.label still matches that source’s preset default. Keep the
existing Chinese behavior and non-built-in label handling unchanged, using the
established built-in source defaults for comparison.
- Around line 1959-1985: Update addContentSources and restoreSource to compare
sources by immutable source.id rather than sourceSlotKey(), so preset additions
and undo cannot introduce duplicate source IDs after mutable args change. Keep
the existing ordering, removal, and restoration behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 87d725c1-fb8a-4f10-8b86-78632808249e

📥 Commits

Reviewing files that changed from the base of the PR and between 2076a20 and 7a4e2f3.

📒 Files selected for processing (6)
  • frontend/components/flow/command-palette.tsx
  • frontend/components/flow/inspector.tsx
  • frontend/lib/workflow/opencli-business-workflows.ts
  • frontend/lib/workflow/source-business-config.ts
  • frontend/lib/workflow/studio-templates.ts
  • frontend/scripts/check-node-capability-catalog-regressions.mjs

Comment on lines +128 to +133
function sourceCardLabel(source: OpenCLISourceSlot, language: WorkflowLanguage): string {
if (language === "zh-CN" || !BUILT_IN_SOURCE_IDS.has(source.id)) return source.label
return source.id
.split("-")
.map((part) => SOURCE_ID_ACRONYMS[part] ?? `${part.charAt(0).toUpperCase()}${part.slice(1)}`)
.join(" ")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve customized built-in source names in English.

The advanced editor permits changing source.label, but this function always replaces built-in labels with an ID-derived value in English. Only derive an English default when the label still matches the preset default.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/components/flow/inspector.tsx` around lines 128 - 133, Update
sourceCardLabel so English output preserves customized source.label values for
built-in sources; derive the ID-based label only when source.label still matches
that source’s preset default. Keep the existing Chinese behavior and
non-built-in label handling unchanged, using the established built-in source
defaults for comparison.

Comment on lines +1959 to +1985
const addContentSources = (contentType: string | null) => {
if (!contentType) return
const presets = contentType === "video"
? OPENCLI_SITUATION_SOURCES.filter((source) => source.sourceGroup?.startsWith("video-"))
: ASHARE_OPENCLI_SOURCES.filter((source) => source.sourceGroup === contentType)
const selectedKeys = new Set(sources.map(sourceSlotKey))
const additions = presets.filter((source) => !selectedKeys.has(sourceSlotKey(source)))
if (additions.length > 0) onChange([...sources, ...additions])
}

const removeSource = (index: number) => {
setRemovedSource({ source: sources[index], index })
onChange(sources.filter((_, sourceIndex) => sourceIndex !== index))
}

const restoreSource = () => {
if (!removedSource) return
const removedKey = sourceSlotKey(removedSource.source)
if (sources.some((source) => sourceSlotKey(source) === removedKey)) {
setRemovedSource(null)
return
}
const restored = [...sources]
restored.splice(Math.min(removedSource.index, restored.length), 0, removedSource.source)
onChange(restored)
setRemovedSource(null)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Deduplicate preset additions and undo by immutable source ID.

sourceSlotKey() includes mutable args. After changing a preset’s market, re-adding its group treats the original preset as new; undo can likewise restore a second slot with the same id. This duplicates collection and produces duplicate React card keys. Compare source.id for these preset/undo operations.

Proposed fix
-    const selectedKeys = new Set(sources.map(sourceSlotKey))
-    const additions = presets.filter((source) => !selectedKeys.has(sourceSlotKey(source)))
+    const selectedIds = new Set(sources.map((source) => source.id))
+    const additions = presets.filter((source) => !selectedIds.has(source.id))
@@
-    const removedKey = sourceSlotKey(removedSource.source)
-    if (sources.some((source) => sourceSlotKey(source) === removedKey)) {
+    if (sources.some((source) => source.id === removedSource.source.id)) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const addContentSources = (contentType: string | null) => {
if (!contentType) return
const presets = contentType === "video"
? OPENCLI_SITUATION_SOURCES.filter((source) => source.sourceGroup?.startsWith("video-"))
: ASHARE_OPENCLI_SOURCES.filter((source) => source.sourceGroup === contentType)
const selectedKeys = new Set(sources.map(sourceSlotKey))
const additions = presets.filter((source) => !selectedKeys.has(sourceSlotKey(source)))
if (additions.length > 0) onChange([...sources, ...additions])
}
const removeSource = (index: number) => {
setRemovedSource({ source: sources[index], index })
onChange(sources.filter((_, sourceIndex) => sourceIndex !== index))
}
const restoreSource = () => {
if (!removedSource) return
const removedKey = sourceSlotKey(removedSource.source)
if (sources.some((source) => sourceSlotKey(source) === removedKey)) {
setRemovedSource(null)
return
}
const restored = [...sources]
restored.splice(Math.min(removedSource.index, restored.length), 0, removedSource.source)
onChange(restored)
setRemovedSource(null)
}
const addContentSources = (contentType: string | null) => {
if (!contentType) return
const presets = contentType === "video"
? OPENCLI_SITUATION_SOURCES.filter((source) => source.sourceGroup?.startsWith("video-"))
: ASHARE_OPENCLI_SOURCES.filter((source) => source.sourceGroup === contentType)
const selectedIds = new Set(sources.map((source) => source.id))
const additions = presets.filter((source) => !selectedIds.has(source.id))
if (additions.length > 0) onChange([...sources, ...additions])
}
const removeSource = (index: number) => {
setRemovedSource({ source: sources[index], index })
onChange(sources.filter((_, sourceIndex) => sourceIndex !== index))
}
const restoreSource = () => {
if (!removedSource) return
if (sources.some((source) => source.id === removedSource.source.id)) {
setRemovedSource(null)
return
}
const restored = [...sources]
restored.splice(Math.min(removedSource.index, restored.length), 0, removedSource.source)
onChange(restored)
setRemovedSource(null)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/components/flow/inspector.tsx` around lines 1959 - 1985, Update
addContentSources and restoreSource to compare sources by immutable source.id
rather than sourceSlotKey(), so preset additions and undo cannot introduce
duplicate source IDs after mutable args change. Keep the existing ordering,
removal, and restoration behavior unchanged.

@2233admin 2233admin changed the title feat(studio): make source configuration card-based feat(studio): make source configuration usable and deduplicated Jul 28, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
frontend/components/flow/command-palette.tsx (1)

1040-1134: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Three near-identical group-rendering blocks (featured / selected-site / more-presets).

Each of these sections repeats the same <section><SectionLabel count={...}>…</SectionLabel><div className="grid gap-2 lg:grid-cols-2">{items.map(item => <OpenCLIPickerRow .../>)}</div></section> shape, differing only in header/label logic. Extracting a small local helper (e.g. renderOpenCLIGroup(key, label, items)) would remove the duplication and reduce the risk of the three blocks drifting apart on future edits.

♻️ Sketch of a shared helper
function renderOpenCLIGroup(
  key: string,
  label: string,
  items: WorkflowOpenCLIAdapterNode[],
  language: WorkflowLanguage,
  onSelect: (item: WorkflowOpenCLIAdapterNode) => void,
) {
  return (
    <section key={key}>
      <SectionLabel count={items.length}>{label}</SectionLabel>
      <div className="grid gap-2 lg:grid-cols-2">
        {items.map((item) => (
          <OpenCLIPickerRow key={item.id} item={item} language={language} onClick={() => onSelect(item)} />
        ))}
      </div>
    </section>
  )
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/components/flow/command-palette.tsx` around lines 1040 - 1134,
Extract the repeated OpenCLI group markup into a shared local helper near the
command-palette rendering logic, such as renderOpenCLIGroup, accepting the group
key, label, items, language, and selection callback. Replace the featured,
selected-site, and more-presets group-rendering blocks with this helper while
preserving each block’s existing label logic, keys, item ordering, and
addOpenCLIAdapter behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/lib/plugins/opencli-adapter-catalog.ts`:
- Around line 475-483: Update openCLIKeyboardCandidates to match the
featured-first ordering used by matchingOpenCLINodes: when no selectedSite is
provided, derive candidates from featuredOpenCLIAdapterNodes(matchingNodes),
then append remaining matching nodes while deduplicating them. Preserve the
selectedSite?.commands result and the empty-query/no-selection behavior.

In `@tests/integration/test_workflow_capabilities_api.py`:
- Around line 661-663: Update the test after refresh_opencli_adapter_catalog()
to call the catalog-listing operation again and assert that it still returns an
empty response for the invalid catalog. Ensure the second refresh result is
observed rather than ending immediately after cache refresh.

---

Nitpick comments:
In `@frontend/components/flow/command-palette.tsx`:
- Around line 1040-1134: Extract the repeated OpenCLI group markup into a shared
local helper near the command-palette rendering logic, such as
renderOpenCLIGroup, accepting the group key, label, items, language, and
selection callback. Replace the featured, selected-site, and more-presets
group-rendering blocks with this helper while preserving each block’s existing
label logic, keys, item ordering, and addOpenCLIAdapter behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ff3429d5-2ce4-4c23-9727-d39f96b4db41

📥 Commits

Reviewing files that changed from the base of the PR and between 7a4e2f3 and 6b82ce9.

📒 Files selected for processing (9)
  • backend/workflow/opencli_adapter_nodes.py
  • frontend/components/flow/command-palette.tsx
  • frontend/lib/plugins/opencli-adapter-catalog.ts
  • frontend/lib/workflow/backend-opencli-adapter-nodes.ts
  • frontend/lib/workflow/opencli-business-workflows.ts
  • frontend/lib/workflow/source-business-config.ts
  • frontend/lib/workflow/studio-templates.ts
  • frontend/scripts/check-node-capability-catalog-regressions.mjs
  • tests/integration/test_workflow_capabilities_api.py
💤 Files with no reviewable changes (1)
  • backend/workflow/opencli_adapter_nodes.py

Comment on lines +475 to +483
export function openCLIKeyboardCandidates(
queryText: string,
selectedSite: OpenCLIAdapterPlugin | null,
matchingNodes: WorkflowOpenCLIAdapterNode[],
): WorkflowOpenCLIAdapterNode[] {
if (!queryText && !selectedSite) return []
return selectedSite?.commands ?? matchingNodes
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect featuredOpenCLIAdapterGroups to check whether matchingNodes order
# already matches the featured-first rendering order used by command-palette.tsx.
rg -nP -C8 'function featuredOpenCLIAdapterGroups' frontend/lib/plugins/opencli-adapter-catalog.ts

Repository: 2233admin/opencli-admin

Length of output: 161


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== matching files =="
fd -a 'command-palette\.tsx$|opencli-adapter-catalog\.ts$' .

echo "== symbol searches =="
rg -n "openCLIKeyboardCandidates|featuredOpenCLIAdapterGroups|matchingNodes|OpenCLIKeyboardCandidates" frontend || true

echo "== catalog outline around relevant area =="
ast-grep outline frontend/lib/plugins/opencli-adapter-catalog.ts --view expanded 2>/dev/null | sed -n '1,220p' || true

echo "== catalog lines 430-510 =="
sed -n '430,510p' frontend/lib/plugins/opencli-adapter-catalog.ts

echo "== palette candidates references =="
file="$(fd 'command-palette\.tsx$' frontend | head -n1 || true)"
if [ -n "$file" ]; then
  echo "$file"
  sed -n '1,260p' "$file"
fi

Repository: 2233admin/opencli-admin

Length of output: 15842


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== featuredOpenCLIAdapterGroups definition =="
sed -n '240,320p' frontend/lib/workflow/backend-opencli-adapter-nodes.ts

echo "== command palette relevant lines =="
sed -n '700,790p' frontend/components/flow/command-palette.tsx

echo "== workflow catalog opencli adapter candidates definitions =="
rg -n -C6 "openCLIKeyboardCandidates|featuredOpenCLIAdapterGroups|searchText|sortOpenCLIAdapterNodes|findMatching" frontend/lib/workflow

echo "== focused search for matching/flattening in backend catalog =="
rg -n -C8 "function .*matching|matchingOpenCLINodes|OPENCLI_SEARCH_RESULT_LIMIT|selectedSite|firstOpenCLI" frontend/components/flow/command-palette.tsx backend-opencli-adapter-nodes.ts workflow/use-opencli-adapter-catalog.ts

Repository: 2233admin/opencli-admin

Length of output: 28529


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== opencliNodes source definitions in palette =="
rg -n -C5 "opencliNodes|useOpenCLI|fetchWorkflowOpenCLIAdapterNodes|openCLIAdapterNodeSort|sort" frontend/components/flow/command-palette.tsx

echo "== use opencli catalog =="
sed -n '1,220p' frontend/lib/workflow/use-opencli-adapter-catalog.ts

echo "== relevant palette around state/top =="
sed -n '1,180p' frontend/components/flow/command-palette.tsx

echo "== deterministic ordering probe: compare featured-first array vs input array for same query =="
python3 - <<'PY'
from pathlib import Path
src = Path('frontend/components/flow/command-palette.tsx').read_text()
print(src[src.find('opencliNodes'):src.find('opencliNodes')+1200])
PY

echo "== catalog tests around openCLIKeyboardCandidates =="
sed -n '530,600p' frontend/scripts/check-node-capability-catalog-regressions.mjs

Repository: 2233admin/opencli-admin

Length of output: 15244


Align keyboard candidates with the featured-first OpenCLI results.

When searching without a selected site, matchingOpenCLINodes are rendered as featured groups first (commonOpenCLINodes), but openCLIKeyboardCandidates() still returns the unfiltered matchingNodes order, so Enter can select the first matching source from the raw catalog order rather than the first featured matching group. Dedupe and order candidates the same way, for example by starting from featuredOpenCLIAdapterNodes(matchingNodes) and appending the remaining matching nodes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/lib/plugins/opencli-adapter-catalog.ts` around lines 475 - 483,
Update openCLIKeyboardCandidates to match the featured-first ordering used by
matchingOpenCLINodes: when no selectedSite is provided, derive candidates from
featuredOpenCLIAdapterNodes(matchingNodes), then append remaining matching nodes
while deduplicating them. Preserve the selectedSite?.commands result and the
empty-query/no-selection behavior.

Comment on lines +661 to +663
opencli_adapter_nodes.refresh_opencli_adapter_catalog()


Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the second refresh result.

Line 661 only clears the cache; the test ends before observing another invalid-catalog load. Re-list and reassert the empty response after it.

Proposed fix
     assert response.total == 0
     assert response.nodes == []
     opencli_adapter_nodes.refresh_opencli_adapter_catalog()
+    response = list_opencli_adapter_nodes(refresh=True)
+    assert response.total == 0
+    assert response.nodes == []
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
opencli_adapter_nodes.refresh_opencli_adapter_catalog()
opencli_adapter_nodes.refresh_opencli_adapter_catalog()
response = list_opencli_adapter_nodes(refresh=True)
assert response.total == 0
assert response.nodes == []
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/integration/test_workflow_capabilities_api.py` around lines 661 - 663,
Update the test after refresh_opencli_adapter_catalog() to call the
catalog-listing operation again and assert that it still returns an empty
response for the invalid catalog. Ensure the second refresh result is observed
rather than ending immediately after cache refresh.

@2233admin
2233admin merged commit 534e53c into main Jul 28, 2026
1 check passed
@2233admin
2233admin deleted the codex/source-card-config-20260728 branch July 28, 2026 09:45
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.

1 participant