Skip to content

feat: File Browser Sidebar with Preview, Security Audit UI, and Syntax Highlighting#145

Merged
XiaoSeS merged 42 commits intomainfrom
sidebar-file-tree
Mar 23, 2026
Merged

feat: File Browser Sidebar with Preview, Security Audit UI, and Syntax Highlighting#145
XiaoSeS merged 42 commits intomainfrom
sidebar-file-tree

Conversation

@XiaoSeS
Copy link
Collaborator

@XiaoSeS XiaoSeS commented Mar 22, 2026

概述 / Summary

本 PR 实现了三个主要功能模块,显著提升了技能包的审查和管理体验:

  1. 文件浏览器侧边栏 - 层级化的文件树浏览和预览功能
  2. 安全审计 UI - 集成安全扫描结果展示
  3. 代码语法高亮 - 文件预览中的语法高亮支持

🎯 核心功能 / Key Features

1. 文件浏览器侧边栏 (File Browser Sidebar)

前端实现:

  • ✅ 层级化文件树结构,支持文件夹展开/折叠
  • ✅ 文件类型图标识别(20+ 文件类型)
  • ✅ 文件大小显示(自动格式化为 KB/MB)
  • ✅ 文件预览对话框(支持 Markdown、代码、纯文本)
  • ✅ 文件下载功能(保留原始文件名)
  • ✅ 复制文件内容到剪贴板
  • ✅ 响应式设计,支持大文件预览(1MB 限制)
  • ✅ 国际化支持(中英文)

后端实现:

  • ✅ 文件读取 API 端点 (/api/portal/reviews/{id}/files)
  • ✅ 权限控制(仅审核者和技能包所有者可访问)
  • ✅ 文件大小限制(1MB)
  • ✅ 错误处理和异常管理

集成位置:

  • 技能详情页面 (Skill Detail)
  • 审核详情页面 (Review Detail)

2. 安全审计 UI (Security Audit UI)

前端实现:

  • ✅ 安全审计摘要卡片(显示扫描结果、严重性统计)
  • ✅ 安全发现列表(按严重性分组展示)
  • ✅ 严重性徽章(Critical/High/Medium/Low/Info)
  • ✅ 审核结果徽章(Pass/Fail/Warning)
  • ✅ 扫描器类型显示(支持多扫描器)
  • ✅ 国际化支持

后端实现:

  • ✅ 安全审计领域模型 (SecurityAudit, SecurityFinding)
  • ✅ 多扫描器支持(Bandit, Semgrep, Skill-Vetter 等)
  • ✅ Redis Stream 异步扫描任务处理
  • ✅ 扫描结果 API 端点 (/api/portal/security-audits/{skillId}/{version})
  • ✅ 软删除支持(随技能包版本删除)
  • ✅ 数据库迁移 (V35__security_audit.sql)

基础设施:

  • ✅ Skill Scanner HTTP 客户端和适配器
  • ✅ Redis Stream 生产者/消费者
  • ✅ Docker Compose 和 K8s 部署配置
  • ✅ 扫描器配置管理(支持自定义规则)

文档:

  • ✅ 安全扫描文档 (docs/security-scanning.md)
  • ✅ 扫描器配置文档 (scanner/docs/configuration.md)
  • ✅ 自定义规则文档 (scanner/docs/custom-rules.md)
  • ✅ 监控指南 (scanner/docs/monitoring-guide.md)
  • ✅ 故障影响分析 (scanner/docs/failure-impact-analysis.md)

3. 代码语法高亮 (Syntax Highlighting)

实现方案:

  • ✅ 复用 rehype-highlight 基础设施(通过 lowlight
  • ✅ 支持 20+ 编程语言(Python, JS/TS, Java, Go, Rust, C/C++, Ruby, PHP, Shell, JSON, YAML, XML 等)
  • ✅ 500KB 语法高亮阈值(超过则显示纯文本)
  • ✅ 1MB 文件预览上限(超过则仅提供下载)
  • ✅ 自动适配 light/dark 主题
  • ✅ 与 Markdown 代码块样式保持一致

技术细节:

  • 新增 CodeRenderer 组件(使用 lowlight)
  • 扩展 file-type-utils.ts 添加语言映射
  • 集成到 file-preview-dialog.tsx

📋 完整需求文档 / PRD

本 PR 包含三份完整的产品需求文档(PRD):

  1. 文件浏览器侧边栏 PRD (docs/prds/skill-file-browser-sidebar-v1.0-prd.md)

    • 247 行,包含完整的功能规格、用户故事、验收标准
  2. 安全审计 UI PRD (docs/prds/security-audit-ui-v1.0-prd.md)

    • 313 行,包含安全扫描集成、UI 设计、错误处理
  3. 文件预览语法高亮 PRD (docs/prds/file-preview-syntax-highlighting-supplements/)

    • 核心 PRD (286 行) + 4 份补充文档
    • 业务规则 (8 条)
    • 影响分析 (8 个风险)
    • 验收用例 (25 个)
    • 测试计划 (100% 覆盖率)
    • 清晰度评分:95/100

🧪 测试计划 / Test Plan

前端测试

  • ✅ 文件树组件单元测试 (file-tree-builder.test.ts)
  • ✅ 文件类型工具测试 (file-type-utils.test.ts)
  • ✅ 审核详情页面集成测试 (review-skill-detail-section.test.tsx)
  • ✅ 技能详情页面集成测试 (skill-detail.test.tsx)

后端测试

  • ✅ 安全扫描服务测试 (SecurityScanServiceTest.java)
  • ✅ 扫描任务消费者测试 (ScanTaskConsumerTest.java)
  • ✅ 扫描器适配器测试 (SkillScannerAdapterTest.java)
  • ✅ 安全审计控制器测试 (SecurityAuditControllerTest.java)
  • ✅ 配置绑定测试 (SkillScannerPropertiesBindingTest.java)

手动测试清单

  • 文件树展开/折叠交互
  • 文件预览(Markdown、代码、纯文本)
  • 语法高亮(多种编程语言)
  • 文件下载(验证文件名和内容)
  • 复制文件内容到剪贴板
  • 安全审计结果展示
  • 主题切换(light/dark mode)
  • 国际化(中英文切换)
  • 大文件处理(500KB/1MB 阈值)
  • 权限控制(审核者/所有者)

📊 变更统计 / Change Statistics

  • 111 个文件变更
  • 9,951 行新增
  • 91 行删除
  • 38 个提交

主要变更文件:

  • 前端 (web/src/):

    • 新增 features/skill/code-renderer.tsx - 语法高亮组件
    • 新增 features/skill/file-preview-dialog.tsx - 文件预览对话框
    • 新增 features/skill/file-tree-*.ts - 文件树构建器和节点
    • 新增 features/security-audit/* - 安全审计 UI 组件
    • 修改 pages/skill-detail.tsx - 集成文件浏览器和安全审计
    • 修改 pages/dashboard/review-detail.tsx - 集成审核流程
  • 后端 (server/):

    • 新增 domain/security/* - 安全审计领域模型
    • 新增 infra/scanner/* - 扫描器基础设施
    • 新增 stream/* - Redis Stream 消费者
    • 新增 controller/portal/SecurityAuditController.java - 安全审计 API
    • 修改 domain/skill/service/SkillPublishService.java - 集成安全扫描
  • 基础设施:

    • 新增 scanner/* - 扫描器 Docker 镜像和配置
    • 修改 deploy/k8s/* - K8s 部署配置
    • 修改 docker-compose.yml - 本地开发环境
  • 文档:

    • 新增 3 份完整 PRD
    • 新增 6 份扫描器文档
    • 更新部署文档

🔧 技术栈 / Tech Stack

前端:

  • React 19 + TypeScript
  • TanStack Router + TanStack Query
  • Radix UI + Tailwind CSS
  • lowlight (highlight.js wrapper)
  • react-markdown + rehype-highlight

后端:

  • Java 17 + Spring Boot 3
  • Redis Streams (异步任务处理)
  • PostgreSQL (数据持久化)
  • WebClient (HTTP 客户端)

基础设施:

  • Docker + Docker Compose
  • Kubernetes
  • Skill Scanner (Python + FastAPI)

🚀 部署说明 / Deployment Notes

环境变量配置

# application.yml
skill-scanner:
  enabled: true
  base-url: http://skill-scanner:8000
  timeout: 30s
  analyzers:
    - bandit
    - semgrep
    - skill-vetter

Docker Compose

docker-compose up -d skill-scanner

Kubernetes

kubectl apply -f deploy/k8s/scanner-deployment.yaml
kubectl apply -f deploy/k8s/configmap.yaml

数据库迁移

# 自动执行 Flyway 迁移
# V35__security_audit.sql

📝 相关 Issue / Related Issues

  • 文件浏览器功能需求
  • 安全扫描集成需求
  • 代码预览体验优化

✅ 验收标准 / Acceptance Criteria

文件浏览器

  • 用户可以在技能详情页查看文件树
  • 用户可以展开/折叠文件夹
  • 用户可以预览文件内容(Markdown、代码、纯文本)
  • 用户可以下载文件
  • 用户可以复制文件内容
  • 文件大小正确显示
  • 文件类型图标正确显示

安全审计

  • 审核者可以查看安全扫描结果
  • 安全发现按严重性分组展示
  • 扫描结果包含详细信息(规则 ID、描述、位置)
  • 支持多扫描器结果聚合
  • 扫描失败时显示友好错误信息

语法高亮

  • 代码文件自动应用语法高亮
  • 支持 20+ 编程语言
  • 大文件(>500KB)降级为纯文本
  • 主题自动适配 light/dark mode
  • 样式与 Markdown 代码块一致

🔍 代码审查要点 / Review Checklist

  • 前端组件是否遵循项目规范
  • 后端 API 是否有适当的权限控制
  • 错误处理是否完善
  • 测试覆盖率是否充分
  • 国际化文本是否完整
  • 性能是否满足要求(大文件处理)
  • 安全性是否考虑周全(XSS、注入攻击)
  • 文档是否清晰完整

📸 截图 / Screenshots

(建议添加以下截图)

  • 文件浏览器侧边栏
  • 文件预览对话框(Markdown、代码)
  • 语法高亮效果(light/dark 主题)
  • 安全审计摘要卡片
  • 安全发现列表

🎉 总结 / Conclusion

本 PR 通过三个紧密集成的功能模块,显著提升了 SkillHub 的技能包审查和管理能力:

  1. 文件浏览器提供了直观的文件结构浏览和预览体验
  2. 安全审计 UI 将安全扫描结果无缝集成到审核流程
  3. 语法高亮提升了代码文件的可读性和审查效率

所有功能均经过完整的需求分析、设计和测试,代码质量和文档完整性达到生产级别标准。

XiaoSeS added 30 commits March 22, 2026 14:53
Integrate skill-scanner's 8 analysis engines and policy configuration
into SkillHub's config system. Operators can now control behavioral,
LLM, Meta, AI Defense, VirusTotal, and trigger analyzers via
application.yml or environment variables.

Changes:
- Add Analyzers and Policy nested classes to SkillScannerProperties
- Create ScanOptions record to encapsulate analyzer flags
- Update SkillScannerService to pass options in /scan body and /scan-upload query params
- Wire ScanOptions through SkillScannerConfig and SkillScannerAdapter
- Extend application.yml with full scanner config block and env var overrides
- Update all tests to verify new configuration flow

All tests pass.
Add SCANNING/SCAN_FAILED status to SkillVersionStatus. Introduce
SecurityScanService, SecurityScanner port, ScanTask, SecurityAudit
and related domain types. Wire scan trigger into SkillPublishService
so non-auto-publish versions enter scanning when scanner is enabled,
falling back to review task creation when disabled.
Add WebClient-based HttpClient abstraction with WebClientHttpClient
implementation. Add SkillScannerApiResponse record, SecurityScanException,
and SecurityAuditJpaRepository. Add webflux and test dependencies to
infra module.
Add AbstractStreamConsumer base class, ScanTaskConsumer for processing
scan results from Redis stream, and RedisScanTaskProducer. Add
RedisStreamConfig for stream/group initialization. Add SecurityAudit
REST controller and DTO. Add V35 Flyway migration for security_audits
table.
Add scanner enabled flag to application-local.yml and
application-test.yml. Enable behavioral analyzer by default
in application.yml.
Add skill-scanner service to docker-compose.yml with health check.
Add scanner k8s deployment, service, and configmap entries. Wire
scanner env vars into Makefile dev-all flow. Add verify-scanner.sh
script for post-deploy validation.
Add scanner docs: configuration guide, failure impact analysis,
monitoring guide, improvement recommendations, custom rules guide,
and skill-vetter rules conversion example. Update deployment docs
with scanner section. Add security-scanning overview and PRD.
Add example Regex and YARA rules derived from skill-vetter RED FLAGS
in scanner/examples/vetter-rules/. Includes 7 Regex rules
(signatures-append.yaml) and 3 YARA rules (skillhub_vetter.yara)
covering agent memory theft, IP-based exfiltration, and browser
data theft detection.
Add Dockerfile for cisco-ai-skill-scanner container and
.env.example with LLM configuration placeholders.
SkillScannerApiResponse.Finding used incorrect field names (message,
location.file, location.line, code_snippet) that did not match the
scanner's actual JSON output (description, file_path, line_number,
snippet), causing all four fields to deserialize as null.

Flatten Finding to match scanner API: remove nested Location, rename
fields to description/file_path/line_number/snippet. Add skill_name
and timestamp to SkillScannerApiResponse. Extend SecurityFinding with
remediation, analyzer, and metadata fields to capture LLM analyzer
output. Retain 8-arg compact constructor for backward compatibility.
Log raw scanner API response and mapped SecurityFinding fields
side-by-side to help verify data consistency between scanner
output and database records.
…y audits

- Add ScannerType enum for type-safe scanner identification
- Update V35 migration to support multiple scanners and soft delete
- Remove CASCADE delete, use code-level soft delete (deleted_at)
- Add repository methods for querying latest audit by scanner type
- Update SecurityScanService to handle scanner type parameter
- Integrate soft delete in SkillHardDeleteService
- Update all tests to use ScannerType enum

This enables multiple scanner integrations (skill-scanner, future LLM/compliance scanners)
and preserves complete audit history through soft deletion.
…il pages

Display security scan results on the review detail page (full audit
section with collapsible findings) and the skill detail sidebar (compact
summary with dialog for details).  Handles empty/404 gracefully by
returning null, avoids loading shimmer flicker, and separates lifecycle
action buttons with a visual divider.
# Conflicts:
#	server/skillhub-app/src/main/resources/application-local.yml
Implement buildFileTree function to convert flat SkillFile[] into hierarchical tree structure.
- Nodes sorted alphabetically by path
- Support for nested directories
- Each node includes depth, type, and path information
- Includes comprehensive test coverage
Implement utilities for file type detection and preview capability checks:
- isPreviewable: checks if file can be previewed based on extension and size
- canPreviewFile: provides detailed reason when file cannot be previewed
- getFileTypeLabel: returns human-readable file type labels
- getFileIcon: maps file types to appropriate Lucide icons
- Supports 1MB max file size limit
- Comprehensive test coverage for all functions
Implement recursive FileTreeNodeComponent with:
- Expand/collapse functionality for directories
- File and directory icons from Lucide React
- Hover effects showing file sizes
- Proper indentation based on depth
- Support for nested directory structures
Replace flat file list with tree structure:
- Use buildFileTree to convert flat files into hierarchy
- Integrate FileTreeNodeComponent for rendering
- Update onFileClick to accept FileTreeNode instead of SkillFile
- Add file count badge in header
- Root-level directories expanded by default
Implement FilePreviewDialog with:
- Markdown rendering via existing MarkdownRenderer
- Plain text/code display with monospace font
- Non-previewable file message with download button
- Copy-to-clipboard and download actions in header
- File path display in footer
- Loading and error states
Add Chinese and English translations for:
- File browser title
- Preview error messages (load failure, too large, binary, unsupported)
- Download file button
- Add useSkillFile hook for fetching arbitrary file content
- Add file preview state, click handler, and download handler
- Pass onFileClick to FileTree for opening preview dialog
- Add FilePreviewDialog to skill detail page
Add GET /api/v1/reviews/{id}/file?path=... for reading single files
from the review-bound skill version:
- ReviewController: new endpoint with path traversal validation
- GovernanceWorkflowAppService: route method for review file access
- ReviewSkillDetailAppService: authorization and delegation
- SkillQueryService: getFileContentByVersionId for direct version access
- Add useReviewFile hook for fetching review file content
- Add file preview state and handlers to ReviewSkillDetailSection
- Pass reviewId prop for API calls
- Add FilePreviewDialog to review detail expanded section
- Update review-detail.tsx to pass taskId as reviewId
- Add useSkillFile mock to skill-detail.test.tsx
- Add useQuery mock to @tanstack/react-query mock
- Add useReviewFile mock to review-skill-detail-section.test.tsx
- Fix SkillFile test fixtures to include all required properties
- Remove unused imports in test and component files
Replace DomainNotFoundException with DomainBadRequestException in
getFileContentByVersionId to match existing patterns and imports.
- Move file tree to right sidebar for persistent visibility
- Display file sizes always visible (not just on hover)
- Keep Files tab showing the same tree structure
- Add scrollable container with max-height for long file lists
- Remove redundant title from file tree sidebar
- Adjust scrollbar placement with proper flex layout
- Sort folders first, then files (both alphabetically)
- Collapse all folders by default for cleaner initial view
- Increase dialog width to max-w-5xl and height to 90vh
- Remove duplicate close button (X icon)
- Add hover effects to action buttons
- Use flexbox for proper content scrolling
- Allow .pyc files in backend configuration

Fixes:
1. File tree sidebar now has cleaner layout without title
2. Scrollbar properly contained within card
3. Folders appear before files in tree
4. All folders collapsed by default
5. Preview dialog wider and more usable
6. Single close method (ESC or click outside)
7. Action buttons have visual feedback on hover
1. Default all folders to collapsed state
2. File tree sidebar now uses Card+bare pattern matching SecurityAuditSummary
   - Scrollbar inside the card content area instead of wrapping the tree
   - Consistent padding and header layout with other sidebar cards
3. Preview dialog close button fixed:
   - Hide DialogContent's built-in close button via [&>button]:hidden
   - Add X button in the header row, same level as copy/download
   - All action buttons share consistent hover animation (opacity transition)
4. Sort directories before files at every tree level
5. Update tests for new directory-first sort order
XiaoSeS added 11 commits March 22, 2026 19:58
1. File browser sidebar now supports expand/collapse toggle
   - Click the header row to toggle visibility
   - ChevronUp/Down icon indicates state
   - Default expanded on page load

2. File preview dialog widened to 72rem (was 5xl/64rem)
   - Uses w-[min(calc(100vw-2rem),72rem)] for responsive max

3. Header action buttons now have micro-interactions:
   - Copy/Download: scale up on hover, scale down on click
   - Close (X): rotates 90° on hover with destructive tint
   - All buttons: opacity 60→100 transition on hover
…eview sidebar

1. File browser chevron: single ChevronDown with rotate-180 CSS transition
   instead of swapping two icons — smooth 200ms rotation animation

2. Preview dialog action button animations:
   - Copy icon: active:scale-125 feedback on click
   - Download icon: hover:translate-y-0.5 subtle downward motion
   - Close icon: hover:rotate-90 with destructive tint (unchanged)

3. Download tooltip now shows full file path:
   "下载 src/prompts/system.md" instead of generic "下载文件"
   - New i18n keys: filePreview.downloadHint, filePreview.copy, filePreview.close

4. Review detail page now has a sidebar file browser:
   - Two-column layout (main content + lg:w-80 sidebar)
   - File tree sourced from reviewSkillDetail.files (active review version)
   - Collapsible with same chevron animation as skill detail page
   - Shows active version badge below file tree
   - File preview uses review file API (/reviews/{id}/file?path=...)
   - Test mocks updated for new useReviewFile dependency
1. Download button tooltip/text now shows actual filename:
   "下载 README.md" instead of generic path
   - i18n key changed from {{path}} to {{name}}

2. Copy button animation reworked to rotation:
   - idle: hover:rotate-180 on the Copy icon
   - click: animate-spin during clipboard write
   - done: swap to green Check icon for 1.5s, then reset

3. Copy success toast notification:
   - Shows "已复制到剪贴板" / "Copied to clipboard" via toast.success
   - New i18n key: filePreview.copySuccess
…ename

The <a> element was missing the download attribute, causing the browser
to derive the filename from the URL path segment (/file?path=...) which
always resolved to "file". Now explicitly sets link.download = node.name
so the saved file uses the original name (e.g. README.md, config.json).

Applied to all three download handlers:
- skill-detail.tsx (skill version file)
- review-detail.tsx (review sidebar file)
- review-skill-detail-section.tsx (review expanded section file)
Add Lucide icons to each sidebar section for visual consistency
with the existing SecurityAuditSummary (Shield) and file browser (Folder):

- Terminal: Install command
- Clock: Pending review (amber-colored to match card theme)
- RefreshCw: Lifecycle management
- Tag: Label management (in SkillLabelPanel component)
- ArrowUpCircle: Promotion
- ShieldCheck: Governance

All icons use the same pattern: w-4 h-4 text-muted-foreground
placed inside a flex row with gap-2 before the section title.
When a skill has only a REJECTED version, the detail page crashed with
400 "版本未发布" because assertPreviewAccessible() only allowed PUBLISHED
and PENDING_REVIEW(owner). The frontend fallback to versions[0] would
pick the REJECTED version and fail all file/readme queries.

Backend changes:
- assertPreviewAccessible(): now allows owners and namespace admins to
  preview ANY version status (DRAFT, REJECTED, YANKED, SCANNING, etc.)
  via canManageRestrictedSkill() check. Also passes userNsRoles so
  namespace admin role is respected, not just owner.
- resolveOwnerPendingPreview(): expanded from PENDING_REVIEW-only to
  include all non-published, non-yanked statuses so headlineVersion
  resolves correctly for owners with REJECTED/DRAFT/SCANNING versions.

Frontend changes:
- isOwnerPreviewResolution(): relaxed from checking PENDING_REVIEW
  specifically to checking any non-PUBLISHED status, matching the
  backend's broader projection.

Fixes: owner viewing skill with only REJECTED version → 400 error
Also fixes: DRAFT-only, SCANNING-only, SCAN_FAILED-only scenarios
…yntax highlighting

Generated complete documentation suite including:
- Core PRD (clarity score: 95/100)
- Constraints specification (8 business rules)
- Impact analysis (8 risks identified)
- Acceptance cases (25 test cases: 10 positive, 5 error, 7 boundary, 3 security)
- Test plan (100% coverage)

Mode: Quick (3 clarification rounds)
Complexity: Simple (3.5 days estimated)
Implement syntax highlighting for code files in the file preview dialog:
- Add CodeRenderer component using lowlight (highlight.js wrapper via rehype-highlight)
- Add getLanguageForHighlight() to map file extensions to highlight.js languages
- Support 20+ languages: Python, JS/TS, Java, Go, Rust, C/C++, Ruby, PHP, Shell, JSON, YAML, XML, etc.
- Apply 500KB threshold for syntax highlighting (larger files show plain text)
- Maintain visual consistency with Markdown code blocks
- Auto-adapt to light/dark theme using existing CSS variables
- Add lowlight as direct dependency to enable programmatic syntax highlighting

Implements solution 1 from PRD (reuse rehype-highlight infrastructure).
# Conflicts:
#	docs/prds/skill-file-browser-sidebar-v1.0-prd.md
#	server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/SecurityAuditResponse.java
#	server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/portal/SecurityAuditControllerTest.java
#	server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/security/SecurityAudit.java
#	server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/security/SecurityScanService.java
#	web/src/pages/dashboard/review-detail.tsx
…ssues

Backend:
- Add hardDeleteByVersionId to physically remove audit records before
  deleting skill versions (fixes FK constraint violation on hard delete)
- Add softDeleteByVersionId calls in SkillGovernanceService and
  SkillPublishService version deletion paths
- Add V36 migration to convert security_audit TIMESTAMP columns to
  TIMESTAMPTZ matching project convention
- Update tests to verify audit cleanup in all deletion flows

Frontend:
- Prevent stale API calls after skill deletion by gating all query
  hooks with a skillDeleted flag that disables them immediately
- Move cache cleanup from useDeleteSkill onSuccess to the handler
  to avoid refetching while the component is still mounted
Backend:
- Include SCANNING/SCAN_FAILED in version listing filters so owners
  can see versions being scanned
- Add explicit lifecycle sort priority for scanner statuses
- Allow deletion of SCAN_FAILED versions alongside DRAFT and REJECTED

Frontend:
- Add i18n labels and CSS classes for SCANNING/SCAN_FAILED in my-skills
- Add localized version status labels in skill-detail version list
- Hide archive button when no published version exists (my-skills and
  skill-detail)
- Allow deleting SCAN_FAILED versions from skill-detail
@XiaoSeS XiaoSeS merged commit ea15a99 into main Mar 23, 2026
2 checks passed
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.

2 participants