mcpField
S
survey-sdk-audit

survey-sdk-audit

github.com/posthog测试与质量40.5k246 次安装今天更新
代码仓库

关于 survey-sdk-audit

survey-sdk-audit 是用于检查 PostHog 各 SDK 调查功能支持情况的 skill,指导仓库检查、版本追溯、实现验证和问题跟踪。

主要功能

  1. 01比较各 SDK 的调查功能支持
  2. 02通过变更日志和 Git 追溯版本
  3. 03验证筛选与渲染行为
  4. 04创建并关联 SDK 问题

适用场景

  1. 01审查某项调查功能在各 SDK 中的支持情况
  2. 02查找功能首次支持的 SDK 版本
  3. 03发现实现缺口并跟踪问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/posthog/posthog --skill survey-sdk-audit

安装后在 Claude Code 中输入/survey-sdk-audit确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
contributing-surveys.md
local-repos.md
scripts/
repos.py

详细介绍

Surveys SDK 功能审计 Skill

在审计 PostHog 各 SDK 对问卷功能的支持情况以更新 surveyVersionRequirements.ts 时,使用本 skill。

要审计的功能: $ARGUMENTS

如需进行问卷功能开发,请阅读 贡献问卷更改。 如需在没有仓库检出的情况下进行客户诊断,请使用已发布的 debugging-surveys skill。

环境检查(首先运行)

开始之前,请确认 SDK 路径可访问。对每个路径运行 ls:

  • $POSTHOG_JS_PATH
  • $POSTHOG_IOS_PATH
  • $POSTHOG_ANDROID_PATH
  • $POSTHOG_FLUTTER_PATH

如果任一路径为空或不存在,请询问用户:“我需要你机器上 [SDK 仓库] 的路径。它位于哪里?”

获取所有路径后,询问用户是否希望将它们保存到 .claude/settings.local.json 以供将来使用:

{
  "env": {
    "POSTHOG_JS_PATH": "/path/to/posthog-js",
    "POSTHOG_IOS_PATH": "/path/to/posthog-ios",
    "POSTHOG_ANDROID_PATH": "/path/to/posthog-android",
    "POSTHOG_FLUTTER_PATH": "/path/to/posthog-flutter"
  },
  "permissions": {
    "allow": [
      "Read(/path/to/posthog-js/**)",
      "Read(/path/to/posthog-ios/**)",
      "Read(/path/to/posthog-android/**)",
      "Read(/path/to/posthog-flutter/**)",
      "Grep(/path/to/posthog-js/**)",
      "Grep(/path/to/posthog-ios/**)",
      "Grep(/path/to/posthog-android/**)",
      "Grep(/path/to/posthog-flutter/**)"
    ]
  }
}

注意: Read 和 Grep 权限授予 Claude 访问这些外部 SDK 仓库的权限,无需每次都提示。

在命令中使用 SDK 路径

重要:像 $POSTHOG_JS_PATH 这样的环境变量在 Bash 工具命令中无法可靠展开。

与其使用 bash 命令,不如优先:

  • 使用 Read 工具读取文件(与权限配合使用)
  • 使用 Grep 工具搜索文件(与权限配合使用)

如果必须使用 bash,请先展开变量:

echo $POSTHOG_JS_PATH

然后在后续命令中直接使用回显的路径。

问题可见性

问卷 SDK 功能对等性没有中央跟踪 issue。可见性存在于仓库级别:surveyVersionRequirements.ts 将不支持的 SDK 链接到它们的 issue,每个新 issue 通过 ## Related 部分交叉链接其同级 issue(参见下面的 issue 模板)。

SDK 路径与变更日志

SDK代码路径变更日志
posthog-js (browser)$POSTHOG_JS_PATH/packages/browser$POSTHOG_JS_PATH/packages/browser/CHANGELOG.md
posthog-react-native$POSTHOG_JS_PATH/packages/react-native$POSTHOG_JS_PATH/packages/react-native/CHANGELOG.md
posthog-ios$POSTHOG_IOS_PATH$POSTHOG_IOS_PATH/CHANGELOG.md
posthog-android$POSTHOG_ANDROID_PATH$POSTHOG_ANDROID_PATH/CHANGELOG.md
posthog-flutter$POSTHOG_FLUTTER_PATH$POSTHOG_FLUTTER_PATH/CHANGELOG.md

Flutter 原生依赖

Flutter 封装了原生 SDK。请检查以下位置的依赖版本:

  • iOS:$POSTHOG_FLUTTER_PATH/ios/posthog_flutter.podspec(查找 s.dependency 'PostHog')
  • Android:$POSTHOG_FLUTTER_PATH/android/build.gradle(查找 posthog-android 依赖)

审计流程

第 1 步:理解功能

查看 surveyVersionRequirements.ts 中的 check 函数,了解是什么字段/条件触发此功能:

  • s.conditions?.deviceTypes → 搜索 "deviceTypes"
  • s.appearance?.fontFamily → 搜索 "fontFamily"
  • s.conditions?.urlMatchType → 搜索 "urlMatchType"
第 2 步:首先搜索变更日志
# Search changelog for the feature keyword
grep -n -i "KEYWORD" /path/to/CHANGELOG.md

如果找到,请阅读周围的几行以获取版本号。

第 3 步:如果变更日志中没有,则搜索代码
# Find commits that added the keyword (use -S for exact string match)
cd /path/to/sdk && git log --oneline --all -S "KEYWORD" -- "*.swift" "*.kt" "*.ts" "*.tsx"

# Then find the first version tag containing that commit
git tag --contains COMMIT_HASH | sort -V | head -3
第 4 步:对于 Flutter,找出原生依赖何时被升级
# Find when Flutter started requiring iOS version X.Y.Z
cd $POSTHOG_FLUTTER_PATH && git log --oneline -p -- "ios/posthog_flutter.podspec" | grep -B10 "X.Y.Z"

# Get the Flutter version for that commit
git tag --contains COMMIT_HASH | sort -V | head -1
第 5 步:验证功能确实有效(不仅仅是类型)

关键:数据模型中有字段并不代表功能已实现。你必须检查实际的过滤/匹配逻辑。

SDK 渲染能力:

  • posthog-js(浏览器):内置问卷渲染(HTML/CSS 弹窗)
  • posthog-react-native:内置问卷渲染(packages/react-native/src/surveys/ 中的 React Native 组件)
  • posthog-ios:内置问卷渲染(PostHog/Surveys/ 中的 SwiftUI 视图 —— SurveySheet.swift、QuestionTypes.swift、MultipleChoiceOptions.swift)
  • posthog-android:无内置 UI —— 纯委托模式。暴露展示模型(PostHogDisplaySurvey、PostHogDisplayChoiceQuestion 等)供开发者自行渲染。对于仅渲染类特性,使用 issue: false。
  • posthog-flutter:内置问卷渲染(lib/src/surveys/widgets/ 中的 Flutter 组件 —— survey_bottom_sheet.dart、choice_question.dart)

对于具有内置渲染的 SDK,特性必须在渲染代码中实际实现,而不仅仅是作为数据模型上的一个字段存在。对于 Android(仅委托),在展示模型上暴露该字段即可 —— 标记为 issue: false 并添加注释。

需要检查问卷过滤逻辑的关键文件:

  • posthog-js(浏览器):$POSTHOG_JS_PATH/packages/browser/src/extensions/surveys/surveys-extension-utils.tsx —— 诸如 canActivateRepeatedly、getSurveySeen、hasEvents 等工具函数
  • posthog-js(浏览器):$POSTHOG_JS_PATH/packages/browser/src/extensions/surveys.tsx —— 主要问卷逻辑
  • posthog-react-native:$POSTHOG_JS_PATH/packages/react-native/src/surveys/getActiveMatchingSurveys.ts —— 主要过滤逻辑
  • posthog-react-native:$POSTHOG_JS_PATH/packages/react-native/src/surveys/surveys-utils.ts —— 诸如 canActivateRepeatedly、hasEvents 等工具函数
  • posthog-ios:$POSTHOG_IOS_PATH/PostHog/Surveys/PostHogSurveyIntegration.swift → getActiveMatchingSurveys() 方法、canActivateRepeatedly 计算属性
  • posthog-android:$POSTHOG_ANDROID_PATH/posthog-android/src/main/java/com/posthog/android/surveys/PostHogSurveysIntegration.kt → getActiveMatchingSurveys() 方法、canActivateRepeatedly() 函数

需要在各 SDK 之间比较的关键工具函数:

  • canActivateRepeatedly —— 判断问卷在被看到后是否可以再次显示
  • hasEvents —— 检查问卷是否具有基于事件的触发条件
  • getSurveySeen —— 检查用户是否已经看到过该问卷

示例陷阱 1:iOS 和 Android 的 Survey 模型中都有 linkedFlagKey,但两者都没有实现 linkedFlagVariant 检查。它们只调用 isFeatureEnabled(key)(布尔值),而没有比较 flags[key] === variant。

示例陷阱 2:浏览器的 canActivateRepeatedly 检查三个条件:(1) 事件 repeatedActivation,(2) schedule === 'always',(3) 问卷正在进行中。移动端 SDK 可能只检查条件 (1),完全遗漏了 schedule 检查。

需要检查问卷渲染逻辑的关键文件:

  • posthog-js(浏览器):$POSTHOG_JS_PATH/packages/browser/src/extensions/surveys/surveys-extension-utils.tsx —— getDisplayOrderQuestions()、getDisplayOrderChoices()
  • posthog-react-native:$POSTHOG_JS_PATH/packages/react-native/src/surveys/surveys-utils.ts —— getDisplayOrderQuestions()、getDisplayOrderChoices()
  • posthog-ios:$POSTHOG_IOS_PATH/PostHog/Surveys/QuestionTypes.swift —— SingleChoiceQuestionView、MultipleChoiceQuestionView;$POSTHOG_IOS_PATH/PostHog/Surveys/SurveySheet.swift —— 问题排序
  • posthog-android:无内置 UI —— 仅检查 $POSTHOG_ANDROID_PATH/posthog/src/main/java/com/posthog/surveys/PostHogDisplaySurveyQuestion.kt 和 PostHogDisplaySurveyAppearance.kt 中展示模型的暴露情况
  • posthog-flutter:$POSTHOG_FLUTTER_PATH/lib/src/surveys/widgets/survey_bottom_sheet.dart —— 问题排序;$POSTHOG_FLUTTER_PATH/lib/src/surveys/widgets/choice_question.dart —— 选项渲染

需要关注的内容:

  • 该字段是否从 JSON 解析到模型中?(必要但不充分)
  • 该字段是否用于 getActiveMatchingSurveys() 等过滤逻辑中?
  • 对于渲染功能:该字段是否真的被内置 UI 使用?(检查渲染代码,而不仅仅是数据模型)
  • 该逻辑是否与参考实现的行为一致?
  • 测试文件不算作实现

参考实现

posthog-js 浏览器端是规范实现——它包含所有功能,是功能预期行为的唯一事实来源。

审计某项功能时:

  1. 首先检查 $POSTHOG_JS_PATH/packages/browser/src/extensions/surveys.ts,了解完整、正确的行为
  2. 然后将移动端 SDK 与 posthog-react-native ($POSTHOG_JS_PATH/packages/react-native/src/surveys/getActiveMatchingSurveys.ts) 进行对比,后者是移动端特定实现的参考

仅 Web 端与跨平台功能

某些功能只在 Web 端才有意义:

  • URL 定向:原生应用中没有“当前 URL”的概念 → 所有移动端均为 issue: false
  • CSS 选择器定向:原生应用中没有 DOM → 所有移动端均为 issue: false
  • 通过 CSS 自定义字体:可能需要原生实现,或者不适用

输出格式

对于每项功能,生成:

{
    feature: 'Feature Name',
    sdkVersions: {
        'posthog-js': 'X.Y.Z',
        'posthog-react-native': 'X.Y.Z',  // or omit if unsupported
        'posthog-ios': 'X.Y.Z',
        'posthog-android': 'X.Y.Z',
        'posthog_flutter': 'X.Y.Z',  // add comment: first version to require native SDK >= X.Y
    },
    unsupportedSdks: [
        { sdk: 'sdk-name', issue: 'https://github.com/PostHog/repo/issues/123' },  // needs implementation
        { sdk: 'sdk-name', issue: false },  // not applicable (e.g., web-only feature)
    ],
    check: (s) => ...,
}

创建 GitHub Issue

重要:在创建新 Issue 之前,务必先搜索现有 Issue。

# Search in the SDK-specific repo
gh issue list --repo PostHog/posthog-ios --search "FEATURE_KEYWORD" --state all --limit 20
gh issue list --repo PostHog/posthog-android --search "FEATURE_KEYWORD" --state all --limit 20
gh issue list --repo PostHog/posthog-flutter --search "FEATURE_KEYWORD" --state all --limit 20

# Also search with broader terms
gh issue list --repo PostHog/posthog-ios --search "survey feature flag" --state all --limit 20

务必同时在主仓库 PostHog/posthog 和 SDK 专属仓库中搜索 Issue,确保该 Issue 在任何地方都尚未存在。

按仓库划分的标签
仓库调查功能所用标签
PostHog/posthog-jsfeature/surveys
PostHog/posthog-iosSurvey, enhancement
PostHog/posthog-androidSurvey, enhancement
PostHog/posthog-flutterSurvey, enhancement
Issue 创建命令
# posthog-js (covers browser and react-native)
gh issue create --repo PostHog/posthog-js --label "feature/surveys" --title "..." --body "..."

# posthog-ios
gh issue create --repo PostHog/posthog-ios --label "Survey" --label "enhancement" --title "..." --body "..."

# posthog-android
gh issue create --repo PostHog/posthog-android --label "Survey" --label "enhancement" --title "..." --body "..."

# posthog-flutter
gh issue create --repo PostHog/posthog-flutter --label "Survey" --label "enhancement" --title "..." --body "..."
Issue 模板
## 🚨 IMPORTANT

This issue is likely user-facing in the main PostHog app, see [`surveyVersionRequirements.ts`](https://github.com/PostHog/posthog/blob/master/frontend/src/scenes/surveys/surveyVersionRequirements.ts). If you delete or close this issue, be sure to update the version requirements list here.

## Summary

The [SDK] SDK does not support [feature] for surveys.

## Current State

- [What exists, if anything - types, partial implementation, etc.]

## Expected Behavior

[What should happen when this feature is configured]

## Reference Implementation

See posthog-js browser: `packages/browser/src/extensions/surveys.ts`
For mobile-specific patterns, see posthog-react-native: `packages/react-native/src/surveys/getActiveMatchingSurveys.ts`

## Related

- [links to the sibling SDK issues created for the same feature — list the ones that exist at creation time; the rest are backfilled below]

_This issue was generated by Claude using the `/survey-sdk-audit` skill._
回填同级链接

Issue 是一次创建一个的,因此较早创建的 Issue 无法链接尚不存在的同级 Issue。在为该功能创建完所有 Issue 后,回填每个 Issue 的 ## Related 部分,使每个 Issue 都链接到所有同级 Issue:

第 1 步:将当前正文抓取到临时文件:

gh issue view 123 --repo PostHog/posthog-ios --json body --jq '.body' > /tmp/issue_body.md

第 2 步:使用 Edit 工具编辑临时文件,填入同级链接(并删除占位符)。这样用户可以在任何内容被推送之前审阅 diff。

第 3 步:推送更新:

gh issue edit 123 --repo PostHog/posthog-ios --body-file /tmp/issue_body.md

完成检查清单

在完成审计之前,确认所有步骤均已完成:

  • 理解功能 - 阅读 surveyVersionRequirements.ts 中的检查函数
  • 检查浏览器 SDK - 在 changelog 中查找版本(这是参考实现)
  • 检查 react-native SDK - 在 changelog 中查找版本
  • 检查 iOS SDK - 确认功能是否真的已实现(而不仅仅是类型)
  • 检查 Android SDK - 确认功能是否真的已实现(而不仅仅是类型)
  • 检查 Flutter SDK - 检查原生依赖版本
  • 搜索现有 Issue - 在创建新 Issue 之前
  • 创建 GitHub Issue - 为所有不支持的 SDK 创建(使用正确的标签)
  • 更新 surveyVersionRequirements.ts - 修正版本并向 unsupportedSdks 添加 Issue 链接
  • 重新生成 SDK 对齐文档 - 运行 pnpm --filter=@posthog/frontend build:survey-sdk-docs 以更新 docs/published/docs/surveys/sdk-feature-support.mdx
  • 回填同级链接 - 在所有 Issue 创建完成后,更新每个 Issue 的 Related 部分,使每个 Issue 都链接到所有同级 Issue(参见回填同级链接)

常见陷阱

  1. 不要猜测版本 - 始终通过 changelog 或 git 历史进行核实
  2. 类型 ≠ 实现 - 数据类中存在某个字段并不意味着存在过滤逻辑
  3. 模型字段 ≠ 功能支持 - 该字段可能被解析但从未用于决策(例如 linkedFlagKey 存在,但缺少 linkedFlagVariant 检查)
  4. 测试代码 ≠ 生产代码 - 仅存在于测试文件中的函数不会被发布
  5. Flutter 继承自原生 - 其“支持”取决于它所要求的 iOS/Android SDK 版本
  6. 始终先搜索已有 issue - 在创建新的 GitHub issue 之前
  7. 比较工具函数实现 - 像 canActivateRepeatedly 这样的函数在不同 SDK 中可能有不同逻辑;浏览器是事实来源
  8. 内置 UI ≠ delegate - iOS、React Native 和 Flutter 有内置的问卷渲染;Android 仅支持 delegate(无内置 UI)。对于 Android,显示模型上的字段就足够了(issue: false),但对于具有内置渲染的 SDK,渲染代码必须实际使用该字段
  9. 检查渲染代码,而不仅仅是模型 - 例如,iOS 在 PostHogDisplayChoiceQuestion 上暴露了 shuffleOptions,但 SwiftUI QuestionTypes.swift 在渲染选项时完全忽略了它

审计后:技能改进

完成审计后,考虑是否应将任何经验教训添加到此技能文件中:

  1. 发现的新陷阱 - 添加到常见陷阱部分
  2. 识别出的新关键文件 - 添加到步骤 5 中的文件路径
  3. 需要比较的新工具函数 - 添加到“关键工具函数”列表
  4. 模式变更 - 如果 SDK 实现的结构已更改,请更新路径

如果你发现改进之处,请向用户提出:

I found some learnings during this audit that could improve the skill:
- [describe the improvement]

Would you like me to update the skill file?

评论

支持 Markdown