Skip to content

docs(ai-integrations): add openspec for RHIDP-15205 TechDocs/model card integration - #4132

Merged
gabemontero merged 4 commits into
redhat-developer:mainfrom
gabemontero:rhidp-15205-openspecs
Aug 2, 2026
Merged

docs(ai-integrations): add openspec for RHIDP-15205 TechDocs/model card integration#4132
gabemontero merged 4 commits into
redhat-developer:mainfrom
gabemontero:rhidp-15205-openspecs

Conversation

@gabemontero

Copy link
Copy Markdown
Contributor

Retroactive openspec covering connector self-discovery, auto TechDocsKey annotation, wildcard model card route, mkdocs.yml generation, and url-reader config alignment with cluster-nested structure.

Assisted-by: Claude Opus 4.6

Hey, I just made a Pull Request!

✔️ Checklist

  • [n/a] A changeset describing the change and affected packages. (more info)
  • [/] Added or Updated documentation
  • [n/a] Tests for new functionality and regression tests for bug fixes
  • [n/a] Screenshots attached (for UI changes)

…rd integration

openspec covering connector self-discovery, auto TechDocsKey
annotation, wildcard model card route, mkdocs.yml generation, and
url-reader config alignment with cluster-nested structure.

Signed-off-by: gabemontero <gmontero@redhat.com>
Assisted-by: Claude Opus 4.6
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 31, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 7:48 PM UTC · Completed 8:06 PM UTC
Commit: 44a1089 · View workflow run →

@rhdh-qodo-merge

Copy link
Copy Markdown

PR Summary by Qodo

docs(ai-integrations): add openspec for TechDocs/model card finalization

📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Add RHIDP-15205 openspec docs for TechDocs-backed model card rendering end-to-end.
• Specify connector self-discovery, TechDocsKey auto-annotation, and wildcard modelcard routing.
• Define url-reader mkdocs.yml generation and cluster-nested config/schema expectations.
Diagram

graph TD
  H["app-config.yaml (cluster-nested)"] --> B["KServe connector"] --> C["Model Catalog provider"] --> D["TechDocs builder"] --> F["Built TechDocs site"] --> G["RHDH UI"]
  D --> E["Techdoc URL reader"] --> B
  A["InferenceService CRs"] --> B
Loading
High-Level Assessment

The chosen approach—capturing the retroactive design/proposal/spec/tasks as an openspec change—is appropriate for aligning multiple plugins after a rebase. Alternatives like embedding these details into the parent openspec would reduce discoverability and make it harder to track RHIDP-15205-specific acceptance criteria.

Files changed (4) +527 / -0

Documentation (4) +527 / -0
design.mdAdd detailed design decisions for TechDocs/model card finalization +166/-0

Add detailed design decisions for TechDocs/model card finalization

• Introduces a full design write-up for RHIDP-15205, including pipeline context across connector/entity-provider/url-reader, config shape expectations, and explicit decisions (self-discovery, path-only TechDocsKey, wildcard routing, mkdocs.yml generation, and schema/index-signature strategy). Includes risks/trade-offs and verification steps.

workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/design.md

proposal.mdDocument the problem statement and proposed end-to-end fixes +68/-0

Document the problem statement and proposed end-to-end fixes

• Adds a proposal describing the integration gaps (connector self-URL, auto-annotation, config misalignment, route limitations, mkdocs.yml requirement) and enumerates the specific changes needed across impacted plugins/config. Summarizes new/modified capabilities and expected impact areas.

workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/proposal.md

spec.mdDefine executable-style requirements and scenarios for integration +213/-0

Define executable-style requirements and scenarios for integration

• Adds a structured spec with SHALL requirements and scenarios covering discovery-based base URL resolution, TechDocsKey auto-setting rules, TechDocsKey→techdocs-ref transformation, wildcard modelcard route behavior, mkdocs.yml generation, cluster-nested url-reader config parsing, config schema preservation, and quality gates.

workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/specs/techdocs-integration/spec.md

tasks.mdProvide implementation task checklist for RHIDP-15205 +80/-0

Provide implementation task checklist for RHIDP-15205

• Adds a step-by-step task plan mapping each spec/design decision to concrete code touchpoints (connector deps/self-discovery, cluster-nested config navigation, auto TechDocsKey logic, wildcard route change, mkdocs.yml creation, url-reader config alignment, config.d.ts updates, and verification commands).

workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/tasks.md

@codecov

codecov Bot commented Jul 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 58.04%. Comparing base (fb73f2d) to head (6ad98cf).
⚠️ Report is 6 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4132   +/-   ##
=======================================
  Coverage   58.04%   58.04%           
=======================================
  Files        2409     2409           
  Lines       96354    96354           
  Branches    26852    26850    -2     
=======================================
  Hits        55932    55932           
  Misses      38927    38927           
  Partials     1495     1495           
Flag Coverage Δ *Carryforward flag
adoption-insights 84.55% <ø> (ø) Carriedforward from fb73f2d
ai-integrations 69.71% <ø> (ø)
app-defaults 69.79% <ø> (ø) Carriedforward from fb73f2d
augment 46.67% <ø> (ø) Carriedforward from fb73f2d
boost 76.77% <ø> (ø) Carriedforward from fb73f2d
bulk-import 72.56% <ø> (ø) Carriedforward from fb73f2d
cost-management 13.55% <ø> (ø) Carriedforward from fb73f2d
dcm 60.72% <ø> (ø) Carriedforward from fb73f2d
extensions 56.59% <ø> (ø) Carriedforward from fb73f2d
global-floating-action-button 71.18% <ø> (ø) Carriedforward from fb73f2d
global-header 66.50% <ø> (ø) Carriedforward from fb73f2d
homepage 47.50% <ø> (ø) Carriedforward from fb73f2d
install-dynamic-plugins 59.95% <ø> (ø) Carriedforward from fb73f2d
intelligent-assistant 74.61% <ø> (ø) Carriedforward from fb73f2d
konflux 91.98% <ø> (ø) Carriedforward from fb73f2d
lightspeed 69.02% <ø> (ø) Carriedforward from fb73f2d
mcp-integrations 83.40% <ø> (ø) Carriedforward from fb73f2d
orchestrator 66.85% <ø> (ø) Carriedforward from fb73f2d
quickstart 62.72% <ø> (ø) Carriedforward from fb73f2d
sandbox 79.56% <ø> (ø) Carriedforward from fb73f2d
scorecard 85.34% <ø> (ø) Carriedforward from fb73f2d
theme 88.52% <ø> (ø) Carriedforward from fb73f2d
translations 5.12% <ø> (ø) Carriedforward from fb73f2d
x2a 79.20% <ø> (ø) Carriedforward from fb73f2d

*This pull request uses carry forward flags. Click here to find out more.


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update fb73f2d...6ad98cf. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@rhdh-qodo-merge

rhdh-qodo-merge Bot commented Jul 31, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 14 rules
✅ Cross-repo context
  Not relevant to this PR: redhat-developer/rhdh
  Not relevant to this PR: redhat-developer/rhdh-chart
  Not relevant to this PR: redhat-developer/rhdh-operator
  Not relevant to this PR: redhat-developer/rhdh-local

Grey Divider


Action required

1. Cluster iteration includes scalars ✓ Resolved 🐞 Bug ≡ Correctness
Description
The spec’s proposed two-level config iteration blindly calls connectorConfig.getConfig(clusterKey)
for every key under a connector, but the same doc explicitly allows connector-level scalar/schedule
fields via a union type. This can throw at runtime for scalar keys (e.g., baseUrl) or incorrectly
treat schedule as a cluster config, producing bad BridgeConfig entries.
Code

workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/design.md[R122-129]

+```typescript
+for (const connectorId of configs.keys()) {
+  const connectorConfig = configs.getConfig(connectorId);
+  for (const clusterKey of connectorConfig.keys()) {
+    const clusterConfig = connectorConfig.getConfig(clusterKey);
+    result.push(readBridgeConfig(connectorId, clusterConfig));
+  }
+}
Relevance

●●● Strong

Team historically fixes config-shape pitfalls; accepted model-catalog config parsing corrections in
PR #3705.

PR-#3705

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The design’s two-level iteration uses connectorConfig.keys() + getConfig(clusterKey) for all
keys, while the same design explicitly allows connector-level scalar/schedule keys. Existing config
schema and config reading code in the model-catalog provider demonstrate those connector-level keys
exist today (baseUrl, schedule), making the proposed iteration unsafe without
filtering/structure changes.

workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/design.md[118-145]
workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/config.d.ts[18-31]
workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/providers/config.ts[26-55]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The OpenSpec proposes iterating `connectorConfig.keys()` and immediately calling `connectorConfig.getConfig(clusterKey)` for each key. This is incompatible with the same document’s plan to keep connector-level scalar/schedule keys (via a union type), because those keys are not cluster objects.

### Issue Context
- The proposed iteration will break if any connector-level scalar exists (e.g. `baseUrl`) because `getConfig('baseUrl')` is invalid.
- Even connector-level objects like `schedule` would be incorrectly treated as a cluster config and passed into `readBridgeConfig`, producing a bogus BridgeConfig.

### Fix Focus Areas
- workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/design.md[118-145]

### Suggested change
Adjust the OpenSpec pseudocode and accompanying text to only iterate cluster sub-keys, for example by:
- Introducing an explicit `clusters` subsection (preferred for unambiguous typing), or
- Filtering keys, e.g. only keys that match a convention like `cluster-*`, and/or
- Using `getOptionalConfig(clusterKey)` and additionally validating the presence of expected cluster fields (e.g. `'kubeflow-model-catalog-url'`) before treating the entry as a cluster.

Also explicitly state whether connector-level fields (`baseUrl`, `schedule`, etc.) may coexist with cluster sub-keys; if yes, the filtering/structure must handle that coexistence.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

2. Curl path missing prefix ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The new verification steps use /modelcard/... as the curl target, but elsewhere in the same design
the connector base URL is /api/kserve-kubeflow-connector, so the verification instruction is
incomplete and can lead to testing the wrong endpoint. This can cause a valid implementation to
appear broken during manual validation.
Code

workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/design.md[164]

+5. `curl` to `/modelcard/redhat_ai_validated_models/RedHatAI/Meta-Llama-3.1-8B-Instruct-quantized.w4a16` returns 200 with model card markdown
Relevance

●●● Strong

Docs verification/path inconsistencies usually corrected; OpenSpec verification doc fixes accepted
(PR #3718, #3755).

PR-#3718
PR-#3755

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The design’s own data-flow section shows the connector base URL includes
/api/kserve-kubeflow-connector and constructs backstage.io/techdocs-ref using that prefix, but
the later verification step omits it, making the curl instruction inconsistent/incomplete.

workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/design.md[20-31]
workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/design.md[156-165]
workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/tasks.md[68-76]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The verification `curl` example is written as a root-relative path (`/modelcard/...`), but the design itself shows the connector is mounted under `/api/kserve-kubeflow-connector`. As written, the verification step is ambiguous and commonly executed against the wrong URL.

### Issue Context
In the same document, the data flow shows `svcUrl` includes `/api/kserve-kubeflow-connector` and the resulting `backstage.io/techdocs-ref` includes `/api/kserve-kubeflow-connector/modelcard/...`.

### Fix Focus Areas
- workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/design.md[160-165]
- workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/tasks.md[70-76]

### Suggested change
Update the verification bullets to show a complete example, e.g.
- `curl http://localhost:7007/api/kserve-kubeflow-connector/modelcard/<sourceId>/<modelName>`

(Optionally mention auth header requirements if applicable.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

@rhdh-qodo-merge rhdh-qodo-merge Bot added the documentation Improvements or additions to documentation label Jul 31, 2026
Adds the required .openspec.yaml manifest file to the
techdocs-modelcard-finalization openspec change directory.

Signed-off-by: gabemontero <gmontero@redhat.com>
Assisted-by: Claude Opus 4.6
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review

Findings

Low

  • [internal-consistency] workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/design.md:22 — The Context section presents current and planned behavior as a unified pipeline without distinguishing what already exists from what this openspec proposes. The Decisions section clarifies what is new, but a brief note in the Context section would help implementers orient themselves.

  • [algorithm-logic-consistency] workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/design.md:105 — Decision D5's claim that the entity provider is "unaffected" was verified correct: connector-level fields (baseUrl, schedule) remain at the connector level alongside new cluster sub-keys, so the entity provider's config reading is unaffected.

  • [edge-case-correctness] workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/specs/techdocs-integration/spec.md:100 — The spec's BridgeConfig scenario describes fields (name, kubeflowModelCatalogUrl, defaultOwner, defaultLifecycle) that are planned additions to the type. The proposal's Modified Capabilities section documents this expansion from {id, baseUrl}.

  • [api-behavior-claims] workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/design.md:85 — D3's (req.params as Record<string, string>)[0] works correctly via JS numeric-to-string coercion, but req.params['0'] would be the more explicit access pattern. Minor clarity point.

  • [spec-heading-convention] workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/specs/techdocs-integration/spec.md:1 — Uses topic-based H2 headings rather than ADDED/MODIFIED Requirements categorization. Sibling openspecs in the workspace use varying heading styles, so this is an acceptable alternative.

Previous run

Review

Findings

Medium

  • [Incorrect technical claim] workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/design.md — D5 rationale states "The entity provider already uses this two-level pattern," but the entity provider's config reading in plugins/catalog-backend-module-model-catalog/src/providers/config.ts uses flat single-level iteration (providerConfigs.keys().map(...)). This claim is factually incorrect and could mislead implementers into believing the entity provider is already compatible with the cluster-nested config structure. The same incorrect claim appears in the Context section ("The entity provider's existing config reading at catalog.providers.modelCatalog also uses this pattern").
    Remediation: Correct D5's rationale and the Context section to acknowledge that the entity provider currently uses flat iteration and will need its own config reading updated.

  • [Missing consumer update] workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/tasks.md — The tasks list covers the connector (Task 2), url-reader (Task 6), and config.d.ts (Task 7) for the cluster-nested config structure, but omits a task for updating the entity provider's config reading in plugins/catalog-backend-module-model-catalog/src/providers/config.ts. The entity provider's readModelCatalogApiEntityConfigs function uses flat iteration that will treat cluster sub-keys as provider IDs when the config structure changes — resulting in empty configs or errors.
    Remediation: Add a task to update the entity provider's config reading to navigate the two-level structure, or document why the entity provider is excluded from this change.

Low

  • [Config schema compatibility] workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/design.md — D6 proposes adding a [clusterKey: string] index signature but does not explicitly mention TypeScript's constraint that named properties must be assignable to the index signature's value type. While the proposed union type accommodates this, an explicit note would help implementers.

  • [Missing .openspec.yaml] workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/ — All four existing sibling directories under openspec/changes/ include a .openspec.yaml manifest with schema, created, and status fields. The new directory does not include this file.

  • [intent-label-mismatch] workspaces/ai-integrations/openspec/changes/techdocs-modelcard-finalization/proposal.md — The proposal declares Change type: feature while the PR title uses docs() prefix. Both labels are accurate in their contexts (the openspec documents a feature; the PR is documentation-only), but the dissonance could confuse readers.


Labels: PR adds only markdown design documentation (openspec files) with no code changes

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added the requires-manual-review Review requires human judgment label Jul 31, 2026
gabemontero and others added 2 commits July 31, 2026 16:13
…tion

- Correct D5 rationale: entity provider uses flat single-level config
  iteration, not two-level — it reads connector-level fields and is
  unaffected by this change
- Update D5 pseudocode to filter non-cluster keys (e.g. schedule) via
  getOptionalConfig and field presence checks
- Remove stale baseUrl references (replaced by cluster-level fields)
- Add full connector base URL to curl verification examples
- Update spec scenario for existing config fields (baseUrl removed)

Signed-off-by: gabemontero <gmontero@redhat.com>
Assisted-by: Claude Opus 4.6
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add parenthetical noting that http://localhost:7007 URLs assume RHDH
running locally via yarn dev from the ai-integrations workspace.

Signed-off-by: gabemontero <gmontero@redhat.com>
Assisted-by: Claude Opus 4.6
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gabemontero
gabemontero force-pushed the rhidp-15205-openspecs branch from 44a1089 to 6ad98cf Compare July 31, 2026 20:15
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 31, 2026

Copy link
Copy Markdown

🤖 Review · ❌ Terminated · Started 8:16 PM UTC · Ended 8:32 PM UTC
Commit: 6ad98cf · View workflow run →

@sonarqubecloud

Copy link
Copy Markdown

@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge and removed requires-manual-review Review requires human judgment labels Jul 31, 2026
@fullsend-ai-review

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 8:16 PM UTC · Completed 8:32 PM UTC
Commit: 6ad98cf · View workflow run →

@johnmcollier johnmcollier left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No concerns outside of what fullsend already raised

@gabemontero
gabemontero merged commit 59a7949 into redhat-developer:main Aug 2, 2026
96 checks passed
@gabemontero
gabemontero deleted the rhidp-15205-openspecs branch August 2, 2026 13:38
JslYoon pushed a commit to JslYoon/rhdh-plugins that referenced this pull request Aug 3, 2026
JslYoon pushed a commit to JslYoon/rhdh-plugins that referenced this pull request Aug 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation ready-for-merge All reviewers approved — ready to merge workspace/ai-integrations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants