关于 survey-sdk-audit
survey-sdk-audit 是用于检查 PostHog 各 SDK 调查功能支持情况的 skill,指导仓库检查、版本追溯、实现验证和问题跟踪。
主要功能
- 01比较各 SDK 的调查功能支持
- 02通过变更日志和 Git 追溯版本
- 03验证筛选与渲染行为
- 04创建并关联 SDK 问题
适用场景
- 01审查某项调查功能在各 SDK 中的支持情况
- 02查找功能首次支持的 SDK 版本
- 03发现实现缺口并跟踪问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ posthog/ posthog --skill survey-sdk-audit安装后在 Claude Code 中输入/survey-sdk-audit确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/contributing-surveys.mdlocal-repos.mdscripts/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 浏览器端是规范实现——它包含所有功能,是功能预期行为的唯一事实来源。
审计某项功能时:
- 首先检查
$POSTHOG_JS_PATH/packages/browser/src/extensions/surveys.ts,了解完整、正确的行为 - 然后将移动端 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-js | feature/surveys |
| PostHog/posthog-ios | Survey, enhancement |
| PostHog/posthog-android | Survey, enhancement |
| PostHog/posthog-flutter | Survey, 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(参见回填同级链接)
常见陷阱
- 不要猜测版本 - 始终通过 changelog 或 git 历史进行核实
- 类型 ≠ 实现 - 数据类中存在某个字段并不意味着存在过滤逻辑
- 模型字段 ≠ 功能支持 - 该字段可能被解析但从未用于决策(例如
linkedFlagKey存在,但缺少linkedFlagVariant检查) - 测试代码 ≠ 生产代码 - 仅存在于测试文件中的函数不会被发布
- Flutter 继承自原生 - 其“支持”取决于它所要求的 iOS/Android SDK 版本
- 始终先搜索已有 issue - 在创建新的 GitHub issue 之前
- 比较工具函数实现 - 像
canActivateRepeatedly这样的函数在不同 SDK 中可能有不同逻辑;浏览器是事实来源 - 内置 UI ≠ delegate - iOS、React Native 和 Flutter 有内置的问卷渲染;Android 仅支持 delegate(无内置 UI)。对于 Android,显示模型上的字段就足够了(
issue: false),但对于具有内置渲染的 SDK,渲染代码必须实际使用该字段 - 检查渲染代码,而不仅仅是模型 - 例如,iOS 在
PostHogDisplayChoiceQuestion上暴露了shuffleOptions,但 SwiftUIQuestionTypes.swift在渲染选项时完全忽略了它
审计后:技能改进
完成审计后,考虑是否应将任何经验教训添加到此技能文件中:
- 发现的新陷阱 - 添加到常见陷阱部分
- 识别出的新关键文件 - 添加到步骤 5 中的文件路径
- 需要比较的新工具函数 - 添加到“关键工具函数”列表
- 模式变更 - 如果 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?