Skip to content

chore: sync workflow templates#875

Closed
stranske wants to merge 1 commit into
mainfrom
sync/workflows-d0d4ad2bdd25
Closed

chore: sync workflow templates#875
stranske wants to merge 1 commit into
mainfrom
sync/workflows-d0d4ad2bdd25

Conversation

@stranske

@stranske stranske commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Sync Summary

Files Updated

  • agents-guard.yml: Agents guard - enforces agents workflow protections (Health 45)
  • maint-76-claude-code-review.yml: Claude Code review (opt-in) - runs only on labeled PRs or manual dispatch
  • progress_reviewer.py: Progress reviewer - evaluates agent progress for keepalive rounds
  • llm_provider.py: LLM provider configuration - GitHub Models and OpenAI client setup
  • langchain_client.py: LangChain client builder - multi-provider client with slot-based fallback and configuration
  • tokens.css: Design-system theme tokens (theme-air/theme-paper + density axis). Override tokens in an app stylesheet loaded after this; do not fork.
  • components.css: Design-system component layer (.ds): panels/appbar/kpis/tables/fields + presentation-state patterns (.notice, .empty-state, .badge, .skeleton).
  • ds_streamlit.py: Streamlit adapter for the design system (inject_theme/empty_state/notice/error/translate_error/dev_note/availability_badge/humanize_id) so Streamlit apps consume the same presentation patterns.
  • PRESENTATION_PATTERNS.md: The presentation-patterns standard (P1-P6): the rule behind each pattern + per-app-type application + the finding->pattern map from the 2026-06 UX-Review fleet baseline.
  • README.md: Design-system usage guide: how to apply the theme + components/kit per app type.

Files Skipped

  • pr-00-gate.yml: File exists and sync_mode is create_only
  • ci.yml: File exists and sync_mode is create_only
  • renovate.json: File exists and sync_mode is create_only
  • cross-repo-smoke.yml: File exists and sync_mode is create_only
  • llm_slots.json: None

Review Checklist

  • CI passes with updated workflows
  • No repo-specific customizations were overwritten

Source: stranske/Workflows
Source SHA: dfe0854ae9b1ba1c616e4b57fb498f283ea3216f
Template hash: d0d4ad2bdd25
Sync branch: sync/workflows-d0d4ad2bdd25
Consumer repo: stranske/Collab-Admin
Manifest: .github/sync-manifest.yml

Summary by CodeRabbit

  • New Features

    • Introduced a comprehensive design system with multiple theme variants and responsive component library for visual consistency.
    • Added standardized UI helpers for error messaging, empty states, diagnostics, and feature availability across applications.
    • Improved AI model configuration with flexible selection and enhanced dependency handling for better reliability.
  • Chores

    • Updated workflow automation references and build infrastructure.

Automated sync from stranske/Workflows
Template hash: d0d4ad2bdd25

Changes synced from sync-manifest.yml
@stranske stranske added sync Automated sync from Workflows automated Automated sync from Workflows labels Jun 23, 2026
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Three independent changes: CI action pins are bumped for setup-api-client (both workflow event branches) and claude-code-action. A new design-system/ directory introduces CSS tokens, a component layer, a Streamlit Python adapter (ds_streamlit.py), and a presentation-patterns guide. tools/langchain_client.py and tools/llm_provider.py are refactored to tolerate a missing langchain_openai package and route model selection through a configurable registry.

Changes

CI Action Pin Updates

Layer / File(s) Summary
Workflow SHA bumps
.github/workflows/agents-guard.yml, .github/workflows/maint-76-claude-code-review.yml
Pins setup-api-client to a new commit SHA in both pull_request_target and pull_request branches, and pins claude-code-action to a new SHA in the Claude review job.

Design System Kit

Layer / File(s) Summary
Token foundation and theme variants
design-system/tokens.css, design-system/README.md
Defines :root spacing/typography/shape defaults, a .density-compact override class, and two full theme palettes (.theme-air, .theme-paper) with surface, text, accent, semantic color, and button tokens. README documents usage rules, per-app override strategy, file roles, and proposed theme-to-app mapping.
Token-driven component CSS
design-system/components.css
Adds the .ds-scoped component layer: base typography, panels, app bar with active navigation, KPI tiles, responsive grid, table with zebra rows, form controls, button variants, callouts, semantic .notice variants, .empty-state, .badge, and .skeleton shimmer with prefers-reduced-motion fallback.
Streamlit adapter
design-system/ds_streamlit.py
New module with nine public helpers: inject_theme, empty_state, notice, error, translate_error, dev_note, diagnostics_expander, availability_badge, and humanize_id.
Presentation patterns guide
design-system/PRESENTATION_PATTERNS.md
Defines six patterns (P1–P6) for themes, empty states, error messaging, dev notices, availability badges, and ID humanization. Includes a finding-to-pattern map and a three-step rollout sequence.

LLM Client and Provider Refactor

Layer / File(s) Summary
Graceful langchain_openai degradation
tools/langchain_client.py
Both build_chat_client and build_chat_clients now store chat_openai_cls = None on ImportError instead of returning immediately. All GITHUB/OPENAI provider branches guard on chat_openai_cls and pass it into _build_github_client/_build_openai_client.
Configurable model resolution in providers
tools/llm_provider.py
Adds DEFAULT_OPENAI_ANALYSIS_MODEL, DEFAULT_ANTHROPIC_ANALYSIS_MODEL, and _configured_langchain_model() querying tools.llm_registry. Both _get_client() implementations delegate to build_chat_client(...) and store the resolved model in self._model_name. analyze_completion() populates CompletionAnalysis.model_name from self._model_name with a registry fallback.
Import path update
scripts/langchain/progress_reviewer.py
review_progress_with_llm imports build_client from scripts.langchain._llm_client with an ImportErrorNone fallback, replacing the previous tools.langchain_client path.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • stranske/Collab-Admin#829: Updates the same maint-76-claude-code-review.yml file by bumping the pinned anthropics/claude-code-action digest.
  • stranske/Collab-Admin#843: Also changes the pinned anthropics/claude-code-action commit hash in the claude-review job of the same workflow file.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 68.42% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'chore: sync workflow templates' is partially related to the changeset. While it accurately describes the workflow file updates, it overlooks the substantial design system additions (tokens.css, components.css, ds_streamlit.py, PRESENTATION_PATTERNS.md, README.md) and Python file changes that represent a significant portion of the PR's scope.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sync/workflows-d0d4ad2bdd25

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: 5

🤖 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 `@design-system/ds_streamlit.py`:
- Around line 109-117: The notice function's docstring documents that the action
parameter accepts markdown, but the implementation on line 116 escapes the
action string before rendering it, which prevents markdown from being formatted.
To align the behavior with the documentation, remove the escape() call from the
act variable assignment that processes the action parameter, allowing markdown
formatting to work as documented while still ensuring safe HTML rendering for
the action content.
- Around line 180-186: The humanize_id function's fallback path still exposes
raw internal ID information despite the "never show raw keys" contract.
Currently, when the raw ID is not in the mapping, the function attempts to
extract a "human-ish segment" by processing the raw string, which can still leak
internal identifiers. Replace the fallback logic so that whenever a mapping
entry doesn't exist for the given raw ID, always return a generic safe value
like "item" instead of processing and returning parts of the raw ID string. This
ensures complete suppression of raw keys in all cases.

In `@design-system/PRESENTATION_PATTERNS.md`:
- Line 83: The section headings at lines 83 and 94 violate Markdown linting
standard MD022 by lacking required blank lines above them. Add a blank line
before the section heading that starts with "## Streamlit design kit (most of
the fleet is Streamlit)" on line 83, and also add a blank line before the
section heading on line 94 to comply with Markdown formatting rules.

In `@design-system/README.md`:
- Line 50: The README.md file contains incorrect source-of-truth information in
the sync instructions around line 50. The text currently states "Update it here
first," but since this repository is a consumer of synced templates from
stranske/Workflows (the actual source-of-truth), this guidance is incorrect and
can cause local drift. Revise the instruction to clearly direct contributors to
make updates in the stranske/Workflows repository first, then rely on the sync
workflow to propagate those changes downstream to this consumer copy.

In `@tools/llm_provider.py`:
- Around line 47-53: The `is None` guard in the return statement of
`_configured_langchain_model` is unreachable dead code because
`configured_model_for_provider` is typed to return a string and never returns
`None` - it returns an empty string instead when no model is resolved. Replace
the conditional check `return fallback if configured is None else configured`
with `return configured or fallback` to correctly match the actual contract and
handle the empty string case using truthiness evaluation.
🪄 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: ASSERTIVE

Plan: Pro Plus

Run ID: 925ad65e-0c48-4cdc-84b6-09368bfaaef4

📥 Commits

Reviewing files that changed from the base of the PR and between 49053ff and 3f13b14.

📒 Files selected for processing (10)
  • .github/workflows/agents-guard.yml
  • .github/workflows/maint-76-claude-code-review.yml
  • design-system/PRESENTATION_PATTERNS.md
  • design-system/README.md
  • design-system/components.css
  • design-system/ds_streamlit.py
  • design-system/tokens.css
  • scripts/langchain/progress_reviewer.py
  • tools/langchain_client.py
  • tools/llm_provider.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • stranske/Workflows (auto-detected)
  • stranske/Template (auto-detected)
📜 Review details
🧰 Additional context used
📓 Path-based instructions (7)
{pyproject.toml,.github/workflows/*.{yml,yaml}}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

{pyproject.toml,.github/workflows/*.{yml,yaml}}: Ensure coverage thresholds in pyproject.toml ([tool.coverage.report] fail_under) match the coverage-min settings in CI workflow files to avoid threshold conflicts
The Manager-Database repository has a coverage threshold of 75%

Files:

  • .github/workflows/agents-guard.yml
  • .github/workflows/maint-76-claude-code-review.yml
.github/workflows/*.{yml,yaml}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

When a GitHub Actions workflow fails with startup_failure, check for invalid YAML syntax, top-level permissions: blocks on workflow_call reusable workflows (which conflicts with caller permissions), invalid permission scopes, or circular workflow references

Files:

  • .github/workflows/agents-guard.yml
  • .github/workflows/maint-76-claude-code-review.yml
.github/workflows/**/*.yml

📄 CodeRabbit inference engine (CLAUDE.md)

Reference reusable workflows with @main to match first-party consumer defaults, unless intentionally pinning to an exact commit SHA for a controlled reason.

Files:

  • .github/workflows/agents-guard.yml
  • .github/workflows/maint-76-claude-code-review.yml
.github/workflows/agents-*.yml

📄 CodeRabbit inference engine (CLAUDE.md)

Synced workflows (agents-*.yml, autofix.yml) should be fixed in stranske/Workflows, not locally in the consumer repo.

Files:

  • .github/workflows/agents-guard.yml
.github/workflows/*.yml

📄 CodeRabbit inference engine (AGENTS.md)

First-party consumers should reference reusable workflows with @main unless intentionally pinning to an exact commit SHA for a controlled reason.

Files:

  • .github/workflows/agents-guard.yml
  • .github/workflows/maint-76-claude-code-review.yml
{.github/workflows/agents-*.yml,.github/workflows/autofix.yml,.github/codex/**/*.{md,txt,prompt},**/*.sync.*}

📄 CodeRabbit inference engine (AGENTS.md)

Synced workflow files, agent prompts, scripts, and consumer docs should be fixed in stranske/Workflows through the sync manifest, not edited locally.

Files:

  • .github/workflows/agents-guard.yml
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

In the Manager-Database repository, use Prefect 2.x and import schedules from prefect.client.schemas.schedules

Files:

  • scripts/langchain/progress_reviewer.py
  • design-system/ds_streamlit.py
  • tools/langchain_client.py
  • tools/llm_provider.py
🪛 LanguageTool
design-system/README.md

[uncategorized] ~50-~50: The official name of this software platform is spelled with a capital “H”.
Context: ...m/and distributed by Maint 68 through.github/sync-manifest.yml`. Update it here firs...

(GITHUB)

🪛 markdownlint-cli2 (0.22.1)
design-system/PRESENTATION_PATTERNS.md

[warning] 83-83: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 94-94: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🔀 Multi-repo context stranske/Template

Now I have enough context to provide a comprehensive analysis. Let me compile the findings:

Linked repositories findings

[::stranske/Template::]

Critical consumers of tools.langchain_client module:

  1. scripts/langchain/_llm_client.py (lines 67, 73) — Wraps build_chat_client and build_chat_clients with fallback handling. This is the canonical abstraction layer for LLM client construction used by agent scripts.

    • Calls: from tools.langchain_client import build_chat_client (line 67)
    • Calls: from tools.langchain_client import build_chat_clients (line 73)
    • This module is the primary consumer that handles import failures gracefully
  2. scripts/langchain/followup_issue_generator.py — Imports build_chat_client directly from tools.langchain_client

  3. tools/llm_provider.py (lines for OpenAIProvider and AnthropicProvider) — The PR changes these classes to use build_chat_client() instead of direct ChatOpenAI/ChatAnthropic imports

    • Critical change: OpenAIProvider._get_client() and AnthropicProvider._get_client() now delegate to tools.langchain_client.build_chat_client() rather than directly importing langchain classes
    • This creates a dependency inversion where provider implementations depend on langchain_client for client instantiation

Design-system module:

  1. design-system/ds_streamlit.py (170 lines) — Already exists in Template. The PR syncs an updated version with new helper functions:
    • inject_theme(), empty_state(), notice(), error(), translate_error(), dev_note(), diagnostics_expander(), availability_badge(), humanize_badge()
    • Currently not imported by any Python files in the Template repo (confirmed: no design-system imports found)
    • This suggests the module is available for future consumption by Streamlit apps but not yet actively used

Workflow integration:

  1. .github/actions/setup-api-client — Referenced in updated workflows (agents-guard.yml, maint-76-claude-code-review.yml)
    • The action installs pinned @octokit dependencies and exports authentication tokens
    • Updated commit SHAs indicate the action implementation was revised in the Workflows source

Import path consolidation:

The PR's change to scripts/langchain/progress_reviewer.py (attempting to import from scripts.langchain._llm_client instead of tools.langchain_client) is compatible because _llm_client.py already exists as the canonical wrapper with proper fallback handling.

Potential integration points that require verification:

  • All scripts using scripts.langchain._llm_client.get_llm_client() or build_client() will now work via the local wrapper, improving import resilience
  • The updated tools/llm_provider.py consolidates client instantiation into langchain_client.build_chat_client(), making provider initialization more uniform but dependent on successful client construction
  • Design system files are ready for adoption but currently dormant
🔇 Additional comments (8)
.github/workflows/agents-guard.yml (1)

114-114: LGTM!

Also applies to: 183-183

.github/workflows/maint-76-claude-code-review.yml (1)

192-192: LGTM!

design-system/PRESENTATION_PATTERNS.md (1)

1-105: Cross-file alignment verified: all pattern-to-code contracts are met by ds_streamlit.py.

The six patterns (P1–P6) and their Streamlit helpers are fully implemented in design-system/ds_streamlit.py (lines 56–186):

  • P1 inject_theme()
  • P2 empty_state()
  • P3 notice(), error(), translate_error()
  • P4 dev_note(), diagnostics_expander()
  • P5 availability_badge()
  • P6 humanize_id()

The CSS class names referenced in web patterns (.ds, .theme-air, .theme-paper, .notice--error, .badge, .empty-state) are provided by the companion CSS files (tokens.css / components.css, not in review scope). The finding-to-pattern map and rollout sequence are actionable and grounded in the 2026-06 UX-Review baseline.

design-system/tokens.css (1)

1-77: LGTM!

design-system/components.css (1)

1-99: LGTM!

tools/langchain_client.py (1)

207-209: LGTM!

Also applies to: 236-263, 297-336, 350-352, 389-449, 489-551

tools/llm_provider.py (1)

599-611: LGTM!

Also applies to: 643-651, 672-686, 728-734, 985-986, 1013-1014

scripts/langchain/progress_reviewer.py (1)

430-434: LGTM!

Comment on lines +109 to +117
def notice(kind: str, title: str = "", body: str = "", action: str | None = None) -> None:
"""P3/P4 — the one container for user-facing messages. kind in
{error,warn,info,ok}. `action` is optional remediation (markdown)."""
import streamlit as st

color, bg, ic = _NOTICE_STYLE.get(kind, _NOTICE_STYLE["info"])
head = f"<strong>{escape(str(title))}</strong><br>" if title else ""
act = f"<div style='margin-top:6px'>{escape(str(action))}</div>" if action else ""
safe_body = escape(str(body))

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

action markdown contract is currently broken.

The docstring says action accepts markdown, but Line 116 escapes it before rendering inside HTML, so markdown never formats.

🛠️ Proposed fix (align behavior to docs)
-def notice(kind: str, title: str = "", body: str = "", action: str | None = None) -> None:
-    """P3/P4 — the one container for user-facing messages. kind in
-    {error,warn,info,ok}. `action` is optional remediation (markdown)."""
+def notice(kind: str, title: str = "", body: str = "", action: str | None = None) -> None:
+    """P3/P4 — the one container for user-facing messages. kind in
+    {error,warn,info,ok}. `action` is optional remediation text."""
📝 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
def notice(kind: str, title: str = "", body: str = "", action: str | None = None) -> None:
"""P3/P4the one container for user-facing messages. kind in
{error,warn,info,ok}. `action` is optional remediation (markdown)."""
import streamlit as st
color, bg, ic = _NOTICE_STYLE.get(kind, _NOTICE_STYLE["info"])
head = f"<strong>{escape(str(title))}</strong><br>" if title else ""
act = f"<div style='margin-top:6px'>{escape(str(action))}</div>" if action else ""
safe_body = escape(str(body))
def notice(kind: str, title: str = "", body: str = "", action: str | None = None) -> None:
"""P3/P4the one container for user-facing messages. kind in
{error,warn,info,ok}. `action` is optional remediation text."""
import streamlit as st
color, bg, ic = _NOTICE_STYLE.get(kind, _NOTICE_STYLE["info"])
head = f"<strong>{escape(str(title))}</strong><br>" if title else ""
act = f"<div style='margin-top:6px'>{escape(str(action))}</div>" if action else ""
safe_body = escape(str(body))
🤖 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 `@design-system/ds_streamlit.py` around lines 109 - 117, The notice function's
docstring documents that the action parameter accepts markdown, but the
implementation on line 116 escapes the action string before rendering it, which
prevents markdown from being formatted. To align the behavior with the
documentation, remove the escape() call from the act variable assignment that
processes the action parameter, allowing markdown formatting to work as
documented while still ensuring safe HTML rendering for the action content.

Comment on lines +180 to +186
def humanize_id(raw: str, mapping: Mapping[str, str] | None = None) -> str:
"""P6 — decode an internal id to a human label; never show raw keys."""
if mapping and raw in mapping:
return mapping[raw]
# Best-effort: take a trailing human-ish segment, strip hashes.
tail = str(raw).replace("_", " ").split(":")[-1].strip()
return tail or "item"

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

humanize_id() can still leak raw internal IDs.

The fallback path may return near-raw identifiers, which conflicts with the stated “never show raw keys” contract.

🛠️ Proposed safer fallback
 from html import escape
+import re
 ...
 def humanize_id(raw: str, mapping: Mapping[str, str] | None = None) -> str:
     """P6 — decode an internal id to a human label; never show raw keys."""
     if mapping and raw in mapping:
         return mapping[raw]
-    # Best-effort: take a trailing human-ish segment, strip hashes.
-    tail = str(raw).replace("_", " ").split(":")[-1].strip()
-    return tail or "item"
+    # Best-effort: trailing segment, normalize separators, and hide hash-like ids.
+    tail = str(raw).replace("_", " ").split(":")[-1].strip()
+    if re.fullmatch(r"[0-9a-fA-F-]{8,}", tail):
+        return "item"
+    return tail or "item"
🤖 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 `@design-system/ds_streamlit.py` around lines 180 - 186, The humanize_id
function's fallback path still exposes raw internal ID information despite the
"never show raw keys" contract. Currently, when the raw ID is not in the
mapping, the function attempts to extract a "human-ish segment" by processing
the raw string, which can still leak internal identifiers. Replace the fallback
logic so that whenever a mapping entry doesn't exist for the given raw ID,
always return a generic safe value like "item" instead of processing and
returning parts of the raw ID string. This ensures complete suppression of raw
keys in all cases.

| LMS #351 root JSON 404 / empty surfaces | P2 (+ deployment) |
| Default dark theme (TMP/PA/MD/IMI) | P1 |

## Streamlit design kit (most of the fleet is Streamlit)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add blank lines above section headings to comply with Markdown formatting rules.

Lines 83 and 94 have section headings that lack the required blank line above them per Markdown linting standard MD022.

📝 Proposed fix for Markdown formatting
 | Default dark theme (TMP/PA/MD/IMI) | P1 |
 
+
 ## Streamlit design kit (most of the fleet is Streamlit)
 - `humanize_id(raw, mapping)` (P6)
 Graduate this kit + the CSS into `Workflows/templates/consumer-repo/design-system/` so maint-68 syncs it fleet-wide.
 
+
 ## Rollout sequence

Also applies to: 94-94

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 83-83: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🤖 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 `@design-system/PRESENTATION_PATTERNS.md` at line 83, The section headings at
lines 83 and 94 violate Markdown linting standard MD022 by lacking required
blank lines above them. Add a blank line before the section heading that starts
with "## Streamlit design kit (most of the fleet is Streamlit)" on line 83, and
also add a blank line before the section heading on line 94 to comply with
Markdown formatting rules.

Source: Linters/SAST tools

Comment thread design-system/README.md

## Status & next step

This kit is managed from `Workflows/templates/consumer-repo/design-system/` and distributed by Maint 68 through `.github/sync-manifest.yml`. Update it here first, then let the sync workflow replace consumer copies.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix source-of-truth direction in sync instructions.

Line 50 says “Update it here first,” but this repo is a consumer of synced templates. That guidance can cause local drift and overwritten edits; the instruction should point contributors to update stranske/Workflows first, then sync downstream.

✍️ Proposed doc fix
-This kit is managed from `Workflows/templates/consumer-repo/design-system/` and distributed by Maint 68 through `.github/sync-manifest.yml`. Update it here first, then let the sync workflow replace consumer copies.
+This kit is managed from `stranske/Workflows/templates/consumer-repo/design-system/` and distributed by Maint 68 through `.github/sync-manifest.yml`. Update it in `stranske/Workflows` first, then let the sync workflow propagate changes to consumer copies.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~50-~50: The official name of this software platform is spelled with a capital “H”.
Context: ...m/and distributed by Maint 68 through.github/sync-manifest.yml`. Update it here firs...

(GITHUB)

🤖 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 `@design-system/README.md` at line 50, The README.md file contains incorrect
source-of-truth information in the sync instructions around line 50. The text
currently states "Update it here first," but since this repository is a consumer
of synced templates from stranske/Workflows (the actual source-of-truth), this
guidance is incorrect and can cause local drift. Revise the instruction to
clearly direct contributors to make updates in the stranske/Workflows repository
first, then rely on the sync workflow to propagate those changes downstream to
this consumer copy.

Comment thread tools/llm_provider.py
Comment on lines +47 to +53
def _configured_langchain_model(provider: str, *, fallback: str) -> str:
try:
from tools.llm_registry import configured_model_for_provider
except ImportError:
return fallback
configured = configured_model_for_provider(provider, fallback=fallback)
return fallback if configured is None else configured

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, find and examine the llm_registry module
find . -name "*llm_registry*" -type f

Repository: stranske/Collab-Admin

Length of output: 183


🏁 Script executed:

#!/bin/bash
# Examine the _configured_langchain_model function and its context
cat -n tools/llm_provider.py | head -80

Repository: stranske/Collab-Admin

Length of output: 3522


🏁 Script executed:

#!/bin/bash
# Look for the configured_model_for_provider function definition
if [ -f "tools/llm_registry.py" ]; then
  cat -n tools/llm_registry.py
else
  rg "configured_model_for_provider" -B 2 -A 10
fi

Repository: stranske/Collab-Admin

Length of output: 12817


🏁 Script executed:

#!/bin/bash
# Examine how _configured_langchain_model is used in _get_client
rg "_get_client|_configured_langchain_model" tools/llm_provider.py -A 5 -B 2

Repository: stranske/Collab-Admin

Length of output: 3505


is None guard is unreachable — function never returns None, only empty string when fallback is blocked.

configured_model_for_provider is typed -> str and returns an empty string "" (line 205 of llm_registry.py) when no model can be resolved, never None. The is None check at line 53 is therefore dead code. The empty string does get caught by the downstream if not model_name: check in _get_client, so behavior is correct, but the guard signals a contract mismatch. Use return configured or fallback instead to match the actual contract:

configured = configured_model_for_provider(provider, fallback=fallback)
-return fallback if configured is None else configured
+return configured or fallback
📝 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
def _configured_langchain_model(provider: str, *, fallback: str) -> str:
try:
from tools.llm_registry import configured_model_for_provider
except ImportError:
return fallback
configured = configured_model_for_provider(provider, fallback=fallback)
return fallback if configured is None else configured
def _configured_langchain_model(provider: str, *, fallback: str) -> str:
try:
from tools.llm_registry import configured_model_for_provider
except ImportError:
return fallback
configured = configured_model_for_provider(provider, fallback=fallback)
return configured or fallback
🤖 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 `@tools/llm_provider.py` around lines 47 - 53, The `is None` guard in the
return statement of `_configured_langchain_model` is unreachable dead code
because `configured_model_for_provider` is typed to return a string and never
returns `None` - it returns an empty string instead when no model is resolved.
Replace the conditional check `return fallback if configured is None else
configured` with `return configured or fallback` to correctly match the actual
contract and handle the empty string case using truthiness evaluation.

@stranske

Copy link
Copy Markdown
Owner Author

Closing as superseded by newer sync wave in PR #880 after the Workflows source fix merged.

@stranske stranske closed this Jun 23, 2026
@stranske stranske deleted the sync/workflows-d0d4ad2bdd25 branch June 23, 2026 12:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automated Automated sync from Workflows sync Automated sync from Workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant