Skip to content

[Feature] 支持厂商中立的前端业务语义属性 #989

Open

Description

@xiaoyaner0201

实现进展 / Implementation: 前端实现已提交 PR #1010 供评审,覆盖范围已从原始 8 点起步清单扩展到完整前端业务域;下方保留提案与讨论历史。Frontend implementation is now available in PR #1010 for review; its broader inventory supersedes the initial eight-point slice.

范围更新 / Scope update

本议题收敛为前端被动语义 HTML 属性(点位、测试与文档);后端事件出口已拆为独立 RFC:https://github.com/iflytek/skillhub/issues/1009,分别评审、不互相阻塞。属性命名和具体点位仍待维护者确认。

This issue now tracks passive frontend semantic HTML markers, tests and documentation. Backend export is a separate RFC at #1009; the two are reviewed independently. Exact markers/conventions remain proposed.

以下保留原始提案及双语图,后端部分作为历史上下文。Original proposal and bilingual diagrams are preserved below; its backend sections are historical context.


Problem

我们在自托管 SkillHub 的使用推广中,需要将产品行为接入企业已有的分析系统,了解“搜索 → 发现 Skill → 请求获取”,以及发布/治理操作的实际结果。我们希望继续使用官方镜像和正常升级路径,由部署方选择分析平台,而不是在各页面绑定某个厂商 SDK 或维护长期 fork。

目前缺少一条稳定、受支持的外部接入路径:

  • 前端:关键交互没有统一的业务语义 HTML 属性。外部采集器依赖文案、CSS 或 DOM 层级时,会随多语言、样式或页面重构失效。局部 data-testid、辅助功能属性和组件状态属性也不是完整的业务标记契约。
  • 后端:已有 Spring 领域事件、选择性审计、请求日志和技术观测,但没有找到面向部署方的统一业务事件订阅/外发接口。现有审计与计数可以补充分析,却不能统一覆盖逐人搜索、获取及操作结果。下载计数也不能证明客户端安装或执行完成。

相关议题与现状核对

源码核对以 main@0f8867f5f13fb77bbdbeec11ff6c619bd5f94194 为边界,并对照了 v0.2.21。例如:搜索栏交互、基础 Button 属性透传、下载领域事件、既有 Provider 装配方式。这是源码核查,不是已完成的采集实现或生产联调。

Proposed Solution

将需求拆成两个可独立讨论、分步交付的部分,保持厂商中立。

A. 前端:被动、稳定的语义属性

在搜索提交、Skill 卡片/详情、下载请求、复制安装指引、发布提交等关键位置添加稳定的 data-* 属性,例如:

// 仅为命名示例,最终属性与点位由维护者确认
<Button data-analytics-id="skill.download.request" onClick={handleDownload}>
  {t('skillDetail.download')}
</Button>
  • 标记描述动作,独立于样式、文案、语言与布局;必要的对象/版本上下文另行最小化设计。
  • 属性本身不发送数据、不绑定 SDK、不加载第三方脚本;部署方自行选择可选采集器与加载方式。
  • 复用已有共享组件;对无法透传属性的业务组件补明确落点,而不是假设基础 Button 一处改动就能覆盖全站。
  • 键盘提交等非点击入口,需要统计“提交尝试”时应在共用动作入口考虑单独语义事件;不能只按按钮点击推断。服务端结果仍以服务端事实为准。

B. 后端:统一事件扩展点 + 可配置出口(待确认边界)

如果维护者认可后端方向,建议沿现有 Spring 事件和接口装配风格演进,而不是为埋点引入完整的插件市场或热加载框架:

  • 复用已存在的领域事件,为缺失的关键动作补事件,并保留必要的稳定主体、资源/版本、发生时间、来源、结果和事件标识。匿名/未知主体如实表达;不从 IP 或 UA 猜测员工身份。
  • 在业务事实形成时捕获可信上下文。写操作的成功结果在提交后形成;读取/获取类动作按其真实完成阶段表达,不把链接发放叫作安装完成。
  • 提供统一 hook/sink 接口;建议以一个官方内置、配置开启的通用 HTTP Webhook/exporter作为首个实现,投递到部署方自己的接收端。具体 SPI/协议及范围由维护者选择。
  • 仅暴露 Java 接口、要求每个部署方自建镜像,仍无法解决保持官方镜像升级路径的诉求;是否提供开箱即用出口,是希望重点讨论的部分。
  • 默认关闭、明确授权/作用域;外发异步且有界,不让分析系统故障拖住业务。配置、签名/鉴权、重试与失败可见性应随最小实现一起定义,不承诺 exactly-once。
  • 不发送密钥、Token、包文件或正文内容;具体分析厂商的字段转换、身份归一和报表继续留在外部。

Alternatives Considered

  • 审计 API/只读 ETL:适合其覆盖范围内的治理事实与对账,但不是全量行为流;现有分页/去重和管理权限仍需处理。
  • HTTP 日志、Micrometer、OTLP tracing:适合技术趋势与排障,不能自动补齐稳定的逐人业务语义,也不天然代表客户端安装/执行结果。
  • CSS/文本选择器、反代注入脚本:可以做部署侧集成,但不能替代稳定语义标记;不将这种自定义集成描述为现成插件。
  • 直接绑定某个分析 SDK 或维持长期 fork:增加厂商与升级耦合,希望避免。

Impact

  • 前端标记是加法式改动,保留已有交互、样式、可访问性及 i18n;不开启采集时不自动外发。
  • 后端是显式可选的能力;保持鉴权、命名空间隔离、发布/下载/治理规则不变。数据最小化、投递可靠性和升级兼容性需要在后端切片中评审,不能仅凭“小改动”推定无风险。
  • 注册表获取/下载发放、客户端安装完成、Agent 执行成功分开定义。 后两者需要可信客户端/执行载体提供证据,不要求注册表猜测。
  • 本提案不包含内建分析大屏、Skill 运行健康评分、任意第三方插件热加载,或自动启用遥测。

Contract Or SDK Impact

前端新增稳定属性约定及相应测试/文档,不更改 Skill 包格式或 CLI 协议。若后端获准推进,再定义版本化事件契约、受支持的配置/鉴权、投递语义和部署文档;涉及 OpenAPI 或生成式客户端时按仓库规则同步。不在本议题预先固定完整事件枚举或强制某个厂商模型。

维护者问题:是否愿意接收这个以“被动前端语义标记”为首个小切片、后端外发出口另行确认的厂商中立外接采集方向? 我们愿意在范围确认后参与点位规划、实现、测试和文档,先以前端小 PR 验证,再按认可的后端契约分步推进。

比喻图

提议:工具库的被动铭牌与可选业务回执出口

像给工具库加稳定铭牌和业务回执出口:铭牌由外部采集器读取,业务事实通过可选出口交给自有接收端。示意的是待讨论方案,不是已上线功能或安装/执行成功证明。

English version

Problem

In a self-hosted SkillHub deployment, we want to integrate product usage with an existing enterprise analytics system: search → discover a Skill → request acquisition, plus actual publishing/governance outcomes. We would like to retain official images and the normal upgrade path, with the analytics platform chosen by the deployment rather than a vendor SDK embedded across pages or a long-lived fork.

There is no stable, supported end-to-end external integration path that we could identify:

  • Frontend: key interactions do not expose a consistent business-semantic HTML attribute contract. External collectors tied to translated text, CSS or DOM structure are fragile. The limited test IDs, accessibility attributes and component state attributes do not constitute complete business markers.
  • Backend: Spring domain events, selective audit logs, request logs and technical observability exist, but we could not find a unified deployer-facing business-event subscription/export surface. Existing audits and counters are useful supplementary sources, not uniform coverage of per-user search/acquisition/outcomes. Download counters do not prove client installation or execution.

Related work and source scope

The source review is pinned to main@0f8867f5f13fb77bbdbeec11ff6c619bd5f94194, with v0.2.21 as a comparison. Relevant anchors are the search bar, shared Button props forwarding, download event and provider assembly linked in the Chinese section above. This is source review, not an implemented collector or completed production integration test.

Proposed Solution

Two independently discussable and deliverable, vendor-neutral parts:

A. Frontend: passive, stable semantic attributes

Add stable data-* attributes at search submission, Skill cards/details, download requests, copy-installation-guidance and publish submission. The data-analytics-id="skill.download.request" snippet above is only a naming example for maintainer discussion.

  • Identify the action independently of styling, translated copy or layout; minimize any resource/version context separately.
  • Attributes do not send data, bind an SDK, or load third-party scripts. The deployment selects an optional collector and its loading mechanism.
  • Reuse shared components and add explicit markers where custom business components do not forward attributes. A shared Button change alone does not mark the whole product.
  • Keyboard and other non-click submission paths need a semantic signal at their common action entry if submission attempts are measured; button clicks alone cannot represent them. Backend outcomes remain backend facts.

B. Backend: unified event extension point and configurable export (scope to confirm)

If maintainers support the backend direction, build on existing Spring events and interface assembly rather than introducing a full plugin marketplace or hot-loading framework:

  • Reuse domain events, add missing key actions and retain the necessary stable actor, resource/version, occurrence time, origin, outcome and event identity. Represent anonymous/unknown actors honestly; do not infer employees from IP/UA.
  • Capture trusted context when the fact is formed. Successful mutations become facts after commit; read/acquisition events describe the stage actually reached, not installation success merely because a link was issued.
  • Expose a consistent hook/sink contract. Consider an official built-in, configuration-enabled generic HTTP webhook/exporter as the first implementation, sending to the deployment's own receiver. Maintainers choose the precise SPI/protocol/scope.
  • A Java interface alone, requiring custom images for each deployment, would not meet the official-image upgrade-path goal; an out-of-the-box export option is an important discussion point.
  • Default off, explicit authorization/scope, bounded asynchronous delivery and business-path independence. Define configuration, signing/authentication, retries and visible failures with the minimum implementation; do not promise exactly-once delivery.
  • Exclude credentials, tokens, package files and content bodies. Vendor mapping, identity normalization and reporting stay external.

Alternatives Considered

  • Audit API/read-only ETL: useful for covered governance facts and reconciliation, not a complete usage stream; pagination/deduplication and admin permissions still need handling.
  • HTTP logs, Micrometer and OTLP tracing: useful for technical trends and diagnosis, but not automatically stable per-user business semantics or client installation/execution outcomes.
  • CSS/text selectors and reverse-proxy script injection: possible deployment integrations, not substitutes for stable markers or an existing native plugin contract.
  • A vendor SDK embedded in core or a long-lived fork: adds vendor/upgrade coupling that we want to avoid.

Impact

  • Additive frontend markers preserve interaction, styling, accessibility and i18n. No automatic outbound collection when not enabled.
  • Backend export is explicit opt-in, preserving authorization, namespace isolation and publishing/download/governance policy. Data minimization, delivery guarantees and upgrade compatibility require review in that slice; a small diff does not establish zero risk.
  • Registry acquisition/download issuance, completed client installation and successful Agent execution are separate facts. The last two require trusted client/execution receipts, not registry inference.
  • No built-in analytics dashboard, runtime health scoring, arbitrary plugin hot loading or automatically enabled telemetry is requested.

Contract Or SDK Impact

Add a frontend attribute convention with tests/docs, without changing Skill package format or CLI protocol. If backend work is accepted, define a versioned event contract, supported configuration/authentication, delivery semantics and operator docs; synchronize OpenAPI/generated clients if affected, following repository rules. This issue does not predefine an exhaustive event enum or require a vendor-specific data model.

Maintainer question: would you accept this vendor-neutral direction with passive frontend markers as the first small slice, and backend export to be confirmed separately? We are willing to contribute marker planning, implementation, tests and docs after scope agreement, starting with a small frontend PR and then proceeding in stages under an agreed backend contract.

Metaphor illustration

Proposed: passive nameplates and an optional business-event receipt exit

Like stable nameplates and an optional receipt exit in a tool library: the collector reads passive labels, while confirmed business facts go to the deployment's own receiver. This illustrates a proposal, not a deployed feature or proof of successful installation/execution.

Activity

  1. added
    triage/deferred暂留 backlog,由自动化定期重新评分 / Issue stays in backlog and is rescored by automation.
    priority/p2中优先级 / Medium priority triage bucket.
    effort/l大改动或高风险改动,需要 maintainer 负责 / Large or risky change requiring maintainer ownership.
    risk/high涉及安全、鉴权、迁移或公共契约 / Touches security, auth, migrations, or public contracts.
    on Oct 20, 2026
  2. github-actions commented on Oct 20, 2026

    @github-actions
    Contributor

    Issue Triage

    • Route: triage/core
    • Priority: priority/p1 (4.0/5)
    • Effort: effort/l (5/5)
    • Confidence: 5/5
    • Risk: high
    • Analysis Mode: rules-only

    Why

    • Touches core SkillHub workflows (publish, publishing, review).
    • Contains urgency signals (failure, cannot, production).
    • Issue includes operator or product impact details.
    • Text suggests a bounded change (copy, text, docs).
    • Thread already has follow-up discussion, so backlog pressure is rising.

    High-Risk Signals

    • Mentions sensitive areas (auth, token, credential).
    • Issue mentions API, SDK, or contract changes.

    Maintainer Brief

    Summary: In a self-hosted SkillHub deployment, we want to integrate product usage with an existing enterprise analytics system: search → discover a Skill → request acquisition, plus actual publishing/governance outcomes. We would like to retain official images and the normal upgrade path, with the analytics platform chosen by the deployment rather than a vendor SDK embedded across pages or a long-lived fork. There is no stable, supported end-to-end external integration path that we could identify: - Frontend: key interactions do not expose a consistent business-semantic HTML attribute contract. External collectors tied to translated text, CSS or DOM structure are fragile. The limited test IDs, accessibility attributes and component state attributes do not constitute complete business markers. - Backend: Spring domain events, selective audit logs, request logs and technical observability exist, but we could not find a unified deployer-facing business-event subscription/export surface. Existing audits and counters are useful supplementary sources, not uniform coverage of per-user search/acquisition/outcomes. Download counters do not prove client installation or execution. #### Related work and source scope - #432 proposed a built-in Analytics dashboard and is closed as completed. This proposal concerns integration with deployment-selected external analytics, not another built-in reporting product. - #433 proposed governance Outgoing Webhooks and is closed as not_planned, without a further scope explanation in the discussion we found. The backend overlap is explicit: we would like to confirm whether that product boundary also applies to this optional external-event use case. If backend exports remain out of scope, they can stay a discussion while frontend markers proceed independently; this proposal is not intended to bypass that earlier decision. - #587 covers runtime health scores and alerts, a separate larger scope. We do not ask for Skill runtime metrics or health scoring here. The source review is pinned to main@0f8867f5f13fb77bbdbeec11ff6c619bd5f94194, with v0.2.21 as a comparison. Relevant anchors are the search bar, shared Button props forwarding, download event and provider assembly linked in the Chinese section above. This is source review, not an implemented collector or completed production integration test.
    Why core:

    • Touches a higher-risk area where automated fixes should not be trusted without maintainer review.
    • Likely spans multiple modules or a public compatibility surface.
    • Mentions sensitive areas (auth, token, credential).
    • Issue mentions API, SDK, or contract changes.
      Reproduction or operator path:
    • In a self-hosted SkillHub deployment, we want to integrate product usage with an existing enterprise analytics system: search → discover a Skill → request acquisition, plus actual publishing/governance outcomes. We would like to retain official images and the normal upgrade path, with the analytics platform chosen by the deployment rather than a vendor SDK embedded across pages or a long-lived fork.
    • There is no stable, supported end-to-end external integration path that we could identify:
    • Frontend: key interactions do not expose a consistent business-semantic HTML attribute contract. External collectors tied to translated text, CSS or DOM structure are fragile. The limited test IDs, accessibility attributes and component state attributes do not constitute complete business markers.
    • Backend: Spring domain events, selective audit logs, request logs and technical observability exist, but we could not find a unified deployer-facing business-event subscription/export surface. Existing audits and counters are useful supplementary sources, not uniform coverage of per-user search/acquisition/outcomes. Download counters do not prove client installation or execution.
      Suspected areas:
    • CLI publish command option parsing and namespace-aware publish flow
    • Skill installation flow and registry/lockfile integration
    • Local skill sync flow and publish diff detection
    • Registry discovery and CLI query workflow
    • Authentication, session, and identity integration
      Risks to watch:
    • Mentions sensitive areas (auth, token, credential).
    • Issue mentions API, SDK, or contract changes.
    • Namespace-scoped behavior can regress default publish/install flows if fallback routing is not preserved.
      Validation checklist:
    • Validate the primary reported workflow end-to-end after the fix.
    • Verify both namespace-scoped behavior and the default non-namespace flow.

    Next Action

    • Hand the issue to a core maintainer and use a local programming agent for reproduction, scoping, and validation.

    问题分流结果

    • 路由: triage/core
    • 优先级: priority/p1 (4.0/5)
    • 修复投入: effort/l (5/5)
    • 信息完整度: 5/5
    • 风险: 高
    • 分析模式: rules-only

    原因

    • 涉及 SkillHub 核心流程(publish, publishing, review)
    • 包含紧急信号(failure, cannot, production)
    • 包含用户或产品影响说明
    • 文本显示改动范围较可控(copy, text, docs)
    • 已有后续讨论,积压压力在上升

    高风险信号

    • 提到敏感区域(auth, token, credential)
    • 提到 API、SDK 或契约变更

    维护者交接摘要

    概要: In a self-hosted SkillHub deployment, we want to integrate product usage with an existing enterprise analytics system: search → discover a Skill → request acquisition, plus actual publishing/governance outcomes. We would like to retain official images and the normal upgrade path, with the analytics platform chosen by the deployment rather than a vendor SDK embedded across pages or a long-lived fork. There is no stable, supported end-to-end external integration path that we could identify: - Frontend: key interactions do not expose a consistent business-semantic HTML attribute contract. External collectors tied to translated text, CSS or DOM structure are fragile. The limited test IDs, accessibility attributes and component state attributes do not constitute complete business markers. - Backend: Spring domain events, selective audit logs, request logs and technical observability exist, but we could not find a unified deployer-facing business-event subscription/export surface. Existing audits and counters are useful supplementary sources, not uniform coverage of per-user search/acquisition/outcomes. Download counters do not prove client installation or execution. #### Related work and source scope - #432 proposed a built-in Analytics dashboard and is closed as completed. This proposal concerns integration with deployment-selected external analytics, not another built-in reporting product. - #433 proposed governance Outgoing Webhooks and is closed as not_planned, without a further scope explanation in the discussion we found. The backend overlap is explicit: we would like to confirm whether that product boundary also applies to this optional external-event use case. If backend exports remain out of scope, they can stay a discussion while frontend markers proceed independently; this proposal is not intended to bypass that earlier decision. - #587 covers runtime health scores and alerts, a separate larger scope. We do not ask for Skill runtime metrics or health scoring here. The source review is pinned to main@0f8867f5f13fb77bbdbeec11ff6c619bd5f94194, with v0.2.21 as a comparison. Relevant anchors are the search bar, shared Button props forwarding, download event and provider assembly linked in the Chinese section above. This is source review, not an implemented collector or completed production integration test.
    为何进入 core:

    • 触及高风险区域,未经 maintainer 审查不应直接信任自动修复
    • 大概率跨多个模块或公共兼容面
    • 提到敏感区域(auth, token, credential)
    • 提到 API、SDK 或契约变更
      复现路径或操作路径:
    • In a self-hosted SkillHub deployment, we want to integrate product usage with an existing enterprise analytics system: search → discover a Skill → request acquisition, plus actual publishing/governance outcomes. We would like to retain official images and the normal upgrade path, with the analytics platform chosen by the deployment rather than a vendor SDK embedded across pages or a long-lived fork.
    • There is no stable, supported end-to-end external integration path that we could identify:
    • Frontend: key interactions do not expose a consistent business-semantic HTML attribute contract. External collectors tied to translated text, CSS or DOM structure are fragile. The limited test IDs, accessibility attributes and component state attributes do not constitute complete business markers.
    • Backend: Spring domain events, selective audit logs, request logs and technical observability exist, but we could not find a unified deployer-facing business-event subscription/export surface. Existing audits and counters are useful supplementary sources, not uniform coverage of per-user search/acquisition/outcomes. Download counters do not prove client installation or execution.
      怀疑影响区域:
    • CLI 发布命令参数解析与 namespace 感知发布流程
    • 技能安装流程与 registry/lockfile 集成
    • 本地技能同步流程与发布 diff 检测
    • Registry 发现与 CLI 查询流程
    • 认证、会话与身份集成
      重点风险:
    • 提到敏感区域(auth, token, credential)
    • 提到 API、SDK 或契约变更
    • namespace 范围行为如果没有保留 fallback routing,可能回归默认 publish/install 流程
      验证清单:
    • 修复后端到端验证主报告流程
    • 同时验证 namespace 范围行为与默认非 namespace 流程

    下一步

    • 交给 core maintainer,并结合本地编程Agent协助完成复现、收敛范围与验证闭环
  3. XiaoSeS commented on Oct 22, 2026

    @XiaoSeS
    Collaborator

    我们认可这个方向,欢迎参与实现并提交 PR。

    希望保持厂商中立,提供稳定的业务语义标记,默认不采集或外发数据,并保持现有交互、权限和业务行为不变。

    具体点位、属性约定、外部接入方式及 PR 拆分可以按你的建议提出,附上测试和使用说明,我们结合实现一起评审。后端事件出口也欢迎提出设计,是否纳入本次实现再共同确认。

  4. changed the title [-][Feature] 支持厂商中立的外部埋点接入:前端语义属性与可选后端事件出口[/-] [+][Feature] 支持厂商中立的前端业务语义属性[/+] on Oct 22, 2026
  5. xiaoyaner0201 commented on Oct 22, 2026

    @xiaoyaner0201
    ContributorAuthor

    感谢 @XiaoSeS 的回复。我理解已认可的是厂商中立、稳定业务语义标记、默认不采集/外发,以及保持现有交互、权限和业务行为不变;具体点位、属性和 PR 拆分仍需评审,后端出口是否纳入尚未确定。下面先把 #989 收敛为前端被动语义属性;后端设计独立讨论:https://github.com/iflytek/skillhub/issues/1009。原文中的后端探索、#433 边界说明和双语示意图保留为讨论历史,不代表本次前端交付范围。

    1. 建议约定(提案,不是已定标准)

    • 建议属性名为 data-analytics-id,值采用小写 domain.object.action,例如 skill.download.request。这是针对 SkillHub 的建议,请维护者确认;不以其他项目的选择作为约束。
    • 标记描述稳定语义,不依赖文案、CSS、语言或布局。它不是 HTML id,同类卡片可重复使用同一值;不要求每个 DOM 实例唯一。data-testid 继续独立服务测试,不替换、不改名,例如现有 install-for-agent-button 测试 ID 保留。
    • 首批只新增静态标记:不把搜索词、Skill 名称/slug/资源 ID、版本、命令/提示词、包内容、账号/组织/身份或凭证再写入分析属性。现有页面显示内容不因本提案扩大暴露范围。此切片只提供动作类别级别的接入锚点,不承诺逐人、逐资源、跨步骤漏斗归因。
    • 不增加 SDK、采集器、脚本加载器、网络出口、身份拼接或自动遥测;也不新增运行时 dispatchEvent 等语义事件。部署方若另行配置采集器,可按约定属性和下表的原生 DOM 事件接入;那是单独配置的部署侧行为,不是这些属性自带的能力。使用说明应要求只读静态白名单属性,不自动抓取表单值、文本、完整 URL 或整个 DOM。
    • 静态属性不等于事件。搜索看 submit,不是按钮 click;普通按钮看激活产生的 click;自定义卡片还需处理键盘。详情根节点仅是结构锚点。下表明确哪些意图可以观察、哪些结果不能推断。

    2. 首批点位:搜索 → 详情 → 下载/复制指引 → 发布

    源码冻结于 e88ebf57c2e9123ef9697ce9a08492fd7e18b7a8。下列落点是拟新增属性的位置,不是声称源码已经带有这些标记。

    建议 ID 精确文件 / 组件 / DOM 控件 可观察语义与入口 明确缺口 / 不应推断
    search.query.submit web/src/features/search/search-bar.tsx · SearchBar 的 <form onSubmit={handleSubmit}>(L54),只由 SearchPage 的调用 显式启用 原生 submit 覆盖搜索按钮与输入框 Enter;handleSubmit 调 onSearch,搜索页再更新路由参数 输入/清空不是提交;直接带查询参数进入、浏览器返回、筛选/排序/分页触发的数据加载不属于此动作;提交不证明发出新请求、返回结果或服务端搜索成功
    skill.card.open web/src/features/skill/skill-card.tsx · SkillCard 的交互根 <Card>(最终是 div),由 SearchPage 结果列表调用 显式启用,仅在 onClick 存在时落点 鼠标/触摸 click;现有 onKeyDown 对 Enter / Space 直接调用 onClick。语义是“请求打开卡片”,搜索页处理器负责路由导航 只监听 click 会漏掉该 div 的键盘路径。部署侧需按此键盘契约处理并避免重复计数;不改变键盘实现来迁就采集。激活不证明导航或详情数据成功;不自动覆盖首页、命名空间或收藏列表
    skill.detail.render web/src/pages/skill-detail.tsx · SkillDetailPage,通过 loading/error/缺失/deleted 分支之后的内容根 <div>(L867) 只标识“详情内容区域当前已渲染”的 DOM 结构;可供外部路由/DOM 观察定位,无对应原生业务完成事件 不在 loading/error/不存在分支加同一标记。挂载、重渲染、缓存数据显示或 owner preview 均不等于一次已确认业务浏览;不以节点出现次数统计唯一访问/可见曝光,也不表示版本已发布
    skill.download.request web/src/pages/skill-detail.tsx 侧栏整包下载 <Button onClick={handleDownload}>(L1423–1434) 原生按钮 click(含键盘激活)表示下载意图;handleDownload 仍先判断匿名访问条件与版本可下载性,再触发浏览器链接 可能转登录或被 guard 拦下;浏览器下载使用临时 <a>,前端同时更新缓存计数,均非完整文件传输回执。点击 ≠ 服务端成功 ≠ 文件落盘 ≠ 安装/执行成功。文件预览的单文件下载 handleDownloadFile 不在首批
    skill.command.copy web/src/features/skill/install-command.tsx 的 CommandBlock 内复制 <Button>(L79–89),限详情页 InstallCommand 宿主 启用;SkillHub / ClawHub 两个 tab 的复制按钮共用该语义 原生按钮 click 表示请求复制 CLI 安装命令;保留异步 copy(command) 与现有反馈 点击不证明剪贴板写入;即使写入成功也不证明执行/安装。首批不区分两个 CLI 方法,不复制命令到属性。该区域采用 publishedVersion.version,不应声称必然等于侧栏当前选择版本
    skill.prompt.copy web/src/features/skill/install-for-agent-button.tsx · InstallForAgentButton 的原生 <button>(L55–67),保留 data-testid="install-for-agent-button";详情宿主见 S6 原生 click 表示请求复制 Agent 安装提示,既有处理器生成提示并异步写剪贴板;保留禁用和版本安全检查 “为 Agent 安装”的按钮实际是复制提示,不是安装调用。点击或 copied 提示均不能证明 Agent 收到、执行、安装或运行成功
    skill.publish.request web/src/pages/dashboard/publish.tsx · PublishPage 的主 <Button onClick={handlePublish}>(L355–362),仅非 avatarOnly 模式带此标记 原生按钮 click 表示包发布/更新/重新提交意图;不是 <form submit>。保持 canSubmit、busy 和重复提交 guard 同一控件在 avatarOnly 时是保存头像,不能标为发布。请求激活不证明 API 已调用或发布成功;publishSkill 有预检确认、错误、待审核与已发布等分支。首批不细分新建/更新/重新提交
    skill.publish.confirm PublishPage 的预检警告 ConfirmDialog 调用(L365–384)→ web/src/shared/components/confirm-dialog.tsx · ConfirmDialog 的确认 <Button>(L73) 原生按钮 click 表示接受预检警告并继续;现有 onConfirm={() => publishSkill(true)} 保持不变 需新增可选、窄范围的确认按钮属性传递,只由这个发布调用方赋值;不是给全部确认弹窗加发布语义。不是初次请求,也不是成功;取消不属于此 ID,确认后的重复/失败仍按现有规则处理

    为什么不在基础 Button 上统一“打全站点位”: Button 已透传原生属性,但不会自动产生业务语义;SearchBar、SkillCard、CommandBlock、ConfirmDialog 等业务封装的参数需逐个检查。建议只补必要的可选属性传递,在本表指明的宿主显式启用;不让共享基础控件猜测动作,不因用了 Button 就宣称全站覆盖。

    3. PR 切片与使用说明建议

    建议以一个前端小 PR提交这 8 个静态标记、必要的调用方限定属性透传、测试和约定文档;后端作为独立 PR,不作为前端前置依赖。若维护者希望更窄,可先提交搜索/详情部分,其余随后补齐。

    建议稳定性采用 best effort:尽量保持语义 ID;调整或移除时在更新说明中记录,同时允许正常 UI 演进。这也是待维护者确认的约定。

    文档给出每个静态选择器(如 [data-analytics-id="search.query.submit"])及其 DOM 事件、重复实例规则、首次/再次渲染限制、键盘卡片漏计风险和不收集字段清单;不捆绑实际采集器,不声称当前已有官方外部分析插件。下载/复制/发布只暴露意图类别;业务结果或可信客户端回执另在后端/客户端议题讨论。

    4. 拟验证(尚未执行)

    这次只完成冻结源码核对与点位设计,没有实现属性,也没有运行组件测试、E2E、构建或网络验证。现有测试只是后续扩展入口,不是本次通过证据:

    • 在 search-bar.test.tsx 扩展 DOM 属性与 submit 断言;在 search-card-interaction.spec.ts 的导航/键盘场景扩展搜索→卡片→详情断言。验证点击与 Enter 搜索各一次,输入/清空不计为提交,卡片 click/Enter/Space 保持行为且无重复记录;非首批宿主不被误标。
    • 复制按钮测试分别驱动 clipboard resolve / reject;点击仍只是意图,保留现有 copied/错误反馈、测试 ID、两种 CLI tab 和版本安全禁用行为。详情 loading/error/缺失/deleted 分支不带内容标记,正常/缓存/预览/重挂载不被测试描述成新的服务端事实。
    • 下载保留匿名/登录、归档/无可下载版本禁用、原有 URL 和缓存更新规则,不把缓存数字变化当传输成功。用明确的测试监听器核对原生 DOM 入口,监听器仅放测试,不进入产品。
    • 在 publish-flow-ui.spec.ts 及发布组件测试扩展发布主按钮/警告确认/取消/busy/失败/待审核/已发布/头像单独保存断言;不因标记修改预检、权限、提交次数或最终状态。
    • 中英文下 ID 不变;检查新增分析属性只有静态白名单值,拒绝动态内容/身份;审查差异没有 SDK、脚本加载、请求出口或运行时事件派发,并在后续运行中核对无新增分析网络请求。按仓库检查矩阵执行相关测试、typecheck、lint 与 build;当前均未执行。

    希望先确认的三点

    1. 是否接受 [Feature] 支持厂商中立的前端业务语义属性 #989 仅覆盖上述前端被动属性,后端出口独立议题评审,且不阻塞前端?
    2. 是否接受 data-analytics-id + 小写 domain.object.action,首批仅静态动作类别、不追加资源或身份上下文,并与 data-testid 分离?
    3. 是否接受上述搜索页限定的首批范围、详情仅作结构锚点,以及单个前端小 PR 的范围?其他发现入口、单文件下载、治理操作和运行回执后续再定。
    English version

    Thank you for the maintainer reply. I understand that the direction—vendor neutrality, stable business-semantic markers, no collection/export by default, and unchanged interactions, permissions and business behavior—is supported. The precise markers, convention and PR split still need review; backend export has not been accepted into this implementation scope. I suggest keeping #989 frontend-only, with backend design discussed separately at #1009. The original backend discussion, #433 boundary and bilingual illustrations remain historical context, not frontend acceptance criteria.

    Proposed contract, not an established convention

    Use data-analytics-id with lowercase domain.object.action values. This is a proposal for SkillHub, not a convention already fixed by maintainers or imposed by another project. It is independent of data-testid; preserve existing test IDs. Repeated cards may share a semantic value—it is not a unique HTML ID.

    Add only static semantic values. Do not add query text, Skill names/slugs/resource IDs, versions, commands/prompts, package content, account/organization identity or credentials to analytics attributes. Existing displayed content is not expanded by this proposal. This slice provides action-category anchors, not per-person/per-resource attribution or a joined funnel.

    No SDK, collector, script loader, outbound integration, identity stitching, automatic telemetry or runtime semantic-event dispatch is included. An independently configured deployment-side collector may use the documented selectors and native DOM events; it is not supplied by the markers. Usage guidance should read only an explicit static-attribute allowlist, not scrape input values, text, full URLs or the DOM.

    First marker inventory

    Reviewed source: e88ebf57c2e9123ef9697ce9a08492fd7e18b7a8. These are proposed insertion points, not existing attributes.

    Proposed ID Exact component / DOM control Observable meaning and limits
    search.query.submit web/src/features/search/search-bar.tsx · SearchBar, <form onSubmit={handleSubmit}>, opted in only by SearchPage Native submit, covering the submit button and input Enter; not typing/clearing. URL entry/history/filter/sort/pagination data loads are not this action. Submission does not prove a new request, search success or returned results.
    skill.card.open web/src/features/skill/skill-card.tsx · SkillCard, interactive root Card/div, explicitly opted in by the SearchPage result-list call Pointer/touch click and existing Enter/Space keydown activation. The div directly calls onClick on those keys: click-only collection misses keyboard activation. Document keyboard handling/deduplication without changing interaction. Activation does not prove navigation/detail success. Other card hosts are not automatically included.
    skill.detail.render web/src/pages/skill-detail.tsx · SkillDetailPage, content root div at L867 after loading/error/missing/deleted branches Structural anchor for rendered detail content, with no native business-completion event. A mount, rerender, cached result or owner preview is not a confirmed business visit, unique view, visible impression or published-version fact. Do not mark error/loading roots.
    skill.download.request web/src/pages/skill-detail.tsx, sidebar package-download Button at L1423–1434 Native button click, including keyboard activation, expresses intent. handleDownload can redirect to login or stop at guards. The temporary anchor and local counter/cache updates are not transfer receipts: click ≠ server success ≠ saved file ≠ installation/execution. Single-file preview download is excluded.
    skill.command.copy web/src/features/skill/install-command.tsx · CommandBlock, copy Button at L79–89, opted in for the detail-page host Both SkillHub/ClawHub tab copy controls share one intent ID. Click does not prove clipboard success, execution or installation. No command value or CLI-method context is added. This section uses publishedVersion.version, not necessarily the currently selected sidebar version.
    skill.prompt.copy web/src/features/skill/install-for-agent-button.tsx · InstallForAgentButton, native button at L55–67; preserve its data-testid and detail-host gating Requests copying an Agent installation prompt, not an installation API call. Keep async copy/error handling and disabled/version-safety checks. Even a copied acknowledgement does not prove delivery to an Agent, execution, installation or runtime success.
    skill.publish.request web/src/pages/dashboard/publish.tsx · PublishPage, primary Button at L355–362, marked only when not avatarOnly Native button click, not form submit, for package publish/update/resubmission intent. Avatar-only mode saves an avatar and must not carry this marker. Keep canSubmit, busy and duplicate guards. publishSkill has confirmation, error, pending-review and published branches; activation is not a sent request or successful publication. These package modes are not distinguished in the first slice.
    skill.publish.confirm PublishPage warning-dialog call → web/src/shared/components/confirm-dialog.tsx · ConfirmDialog, confirm Button at L73 Native click accepts precheck warnings and continues via existing publishSkill(true). Add a narrow optional attribute-forwarding prop, set only by this publish caller—not a publish marker on every shared dialog. Not the initial attempt or success; cancellation has no such ID.

    Button already forwards native props, but business wrappers need explicit, caller-scoped forwarding where missing. A generic Button modification does not provide product-wide semantic coverage.

    Suggested PRs and usage documentation

    Propose one small frontend PR containing these eight static markers, narrowly scoped prop forwarding, tests and convention docs. Backend export is an independent PR, not a prerequisite. If a narrower first slice is preferred, search/detail can go first.

    Propose best-effort stability: preserve semantic IDs where practical, document changes/removals in release notes, and allow normal UI evolution. This policy also awaits maintainer agreement.

    Document selectors, native event types, repeated instances, render/remount limitations, card-keyboard coverage and field exclusions. Do not bundle a collector or claim an existing official analytics plugin. Business outcomes and trusted client receipts need separate backend/client contracts.

    Planned verification — not executed

    This is frozen-source review and marker design only: no markers implemented; no component tests, E2E, builds or network checks run. Existing files are extension points, not passing evidence:

    • Extend search-bar.test.tsx and search-card-interaction.spec.ts for static attributes, one submit per button/Enter action, no submission on typing/clearing, click/Enter/Space card behavior without duplication, detail-root presence/absence and unmarked out-of-scope hosts.
    • Exercise clipboard resolve/reject for both CLI tabs and Agent prompts while preserving copied feedback, existing test IDs, disabled behavior and safe-version checks. Do not label rerenders, cached detail or previews as backend facts.
    • Preserve download auth/anonymous/archive/version guards, URL and cache behavior without treating the counter as transfer success. Any DOM-event counting listener belongs in tests only.
    • Extend publish-flow-ui.spec.ts and component tests for main activation, warning confirm/cancel, busy, failure, pending/published responses and avatar-only saving, preserving authorization, prechecks, submission counts and final state.
    • Verify identical static IDs in Chinese/English, no dynamic/identity analytics values, no added SDK/script/export/runtime event dispatch and no added analytics network requests in later runtime checks. Run relevant tests/typecheck/lint/build per the repository matrix. None has been run here.

    Three confirmations requested

    1. Frontend-only scope for [Feature] 支持厂商中立的前端业务语义属性 #989, with separately reviewed backend export that does not block frontend markers?
    2. data-analytics-id, lowercase domain.object.action, static action categories only, no resource/identity context, independent of data-testid?
    3. SearchPage-limited first inventory, a structural-only detail anchor and the proposed single frontend PR, leaving other discovery hosts, single-file download, governance and runtime receipts for later?
  6. added
    triage/core交由 core maintainer 结合 AI 协同处理 / Issue should be handled by a core maintainer with AI support.
    priority/p1高优先级 / High priority triage bucket.
    and removed
    triage/deferred暂留 backlog,由自动化定期重新评分 / Issue stays in backlog and is rescored by automation.
    priority/p2中优先级 / Medium priority triage bucket.
    on Oct 22, 2026
  7. xiaoyaner0201 commented on Oct 22, 2026

    @xiaoyaner0201
    ContributorAuthor

    已提交前端实现 PR:#1010 — #1010 。

    在前面的 8 点起步清单上,进一步核对了完整路由、共享组件及条件交互,扩展到搜索/发现、技能与 Suite、发布管理、审核治理、命名空间、GitHub 同步、通知、账号与管理端;补入有业务意义的确认、取消和重试。当前清单是 54 个注册路由、804 个唯一静态语义 ID、821 处 literal JSX 属性位置,这些是源码口径,不是采集事件数或业务成功次数。

    实现仍只提供被动属性和明确的 DOM 透传,默认不采集、不外发,不改现有交互与权限。部署方可选用 Nginx 在 HTML 注入独立 JS 引用;PR 附配置、脚本小白名单示例、CSP/压缩/缓存/子路径/关闭说明。实际采集与厂商适配留在外部,后端继续独立在 #1009 讨论。

    已验证:前端全量 1,217 项测试、101 项聚焦测试、类型/lint/build/清单检查通过;独立审查无阻塞发现。实际构建配 Nginx 的 25 项 HTTP 检查,以及 Chrome 根路径/子路径/弹窗交互共 28 项通过,API 使用合成夹具,不作为生产或真实后端验收。远端 CI 结果以 PR Checks 为准。

    请结合实现审阅属性命名、覆盖与部署侧接入边界;具体选择可在 PR 中调整。原提案和讨论保留。

    English

    The frontend implementation is ready for review in PR #1010. The initial eight-marker inventory has been expanded through route/component/conditional-action audits: 54 registered routes, 804 unique static categories and 821 literal JSX attribute sites. These are source counts, not runtime event or successful-operation totals.

    Core remains passive and vendor-neutral, with no collection/export or SDK by default and unchanged interactions/permissions. Optional deployment-owned Nginx script-reference injection is documented with a small explicit collector example and CSP/compression/cache/sub-path/rollback guidance. Backend export stays separate in #1009.

    All 1,217 frontend tests, 101 focused tests, typecheck/lint/build/manifest checks passed locally; independent review found no blocking findings. Actual compiled UI and Nginx passed 25 HTTP checks and 28 Chrome checks with synthetic APIs, not production/backend acceptance. Live CI is reported on the PR. Feedback on semantic naming, coverage and deployment boundaries is welcome.

  8. xiaoyaner0201 commented on Oct 29, 2026

    @xiaoyaner0201
    ContributorAuthor

    @XiaoSeS 第二步的配置化接入已经提了 PR #1037,有空帮忙看看 🙏

    简单说一下:

    • Docker/Compose 和 Helm 用户只需填两项配置,就能开启统计,不用改 JS,也不用手写 Nginx。
    • 默认关闭,页面挂载完成后才按需加载。配置写错或统计平台故障时只关掉统计,不影响业务。
    • 第一版只接 Umami,通用的配置和加载部分没有绑定 Umami,其他平台以后加一个 adapter 就行。
    • 没有新增依赖。原设计稿里的 jq 换成了镜像自带的 awk,加上 base64,具体取舍写在 PR 里了。

    验证结果和还没覆盖的部分(Helm 本地没跑、release Compose 的 S3/auth 冒烟)都列在 PR 正文里。#989 等这个 PR 合并并验证后再关。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    effort/l大改动或高风险改动,需要 maintainer 负责 / Large or risky change requiring maintainer ownership.priority/p1高优先级 / High priority triage bucket.risk/high涉及安全、鉴权、迁移或公共契约 / Touches security, auth, migrations, or public contracts.triage/core交由 core maintainer 结合 AI 协同处理 / Issue should be handled by a core maintainer with AI support.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions