[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M72XED60D83PZTPTYAD1P1CP":3,"skill-same:01M72XED60D83PZTPTYAD1P1CP":48},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":28,"repositoryHtmlUrl":29,"repositoryHomepageUrl":6,"ownerHtmlUrl":30,"ownerBlogUrl":31,"ownerDescription":32,"updatedAt":33,"install":34,"resources":47},"01M72XED60D83PZTPTYAD1P1CP","kotlin-coroutines-flows",null,"Kotlin协程与Flow在Android和KMP中的模式——结构化并发、Flow操作符、StateFlow、错误处理和测试。","SriramGandhiS\u002FSkills","SriramGandhiS","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F211849986?v=4","01M72WQCW12BYX71C6WN584TTA","Sriram S","01M72WQCWTJ2RD0ET1X31AF1RC",1,"MIT","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fdocs\u002Fzh-CN\u002Fskills\u002Fkotlin-coroutines-flows\u002FSKILL.md",[],[],"2026-11-10 22:39:42",false,"---\nname: kotlin-coroutines-flows\ndescription: Kotlin协程与Flow在Android和KMP中的模式——结构化并发、Flow操作符、StateFlow、错误处理和测试。\norigin: ECC\n---\n\n# Kotlin 协程与 Flow\n\n适用于 Android 和 Kotlin 多平台项目的结构化并发模式、基于 Flow 的响应式流以及协程测试。\n\n## 何时启用\n\n* 使用 Kotlin 协程编写异步代码\n* 使用 Flow、StateFlow 或 SharedFlow 实现响应式数据\n* 处理并发操作（并行加载、防抖、重试）\n* 测试协程和 Flow\n* 管理协程作用域与取消\n\n## 结构化并发\n\n### 作用域层级\n\n```\nApplication\n  └── viewModelScope (ViewModel)\n        └── coroutineScope { } (结构化子作用域)\n              ├── async { } (并发任务)\n              └── async { } (并发任务)\n```\n\n始终使用结构化并发——绝不使用 `GlobalScope`：\n\n```kotlin\n\u002F\u002F BAD\nGlobalScope.launch { fetchData() }\n\n\u002F\u002F GOOD — scoped to ViewModel lifecycle\nviewModelScope.launch { fetchData() }\n\n\u002F\u002F GOOD — scoped to composable lifecycle\nLaunchedEffect(key) { fetchData() }\n```\n\n### 并行分解\n\n使用 `coroutineScope` + `async` 处理并行工作：\n\n```kotlin\nsuspend fun loadDashboard(): Dashboard = coroutineScope {\n    val items = async { itemRepository.getRecent() }\n    val stats = async { statsRepository.getToday() }\n    val profile = async { userRepository.getCurrent() }\n    Dashboard(\n        items = items.await(),\n        stats = stats.await(),\n        profile = profile.await()\n    )\n}\n```\n\n### SupervisorScope\n\n当子协程失败不应取消同级协程时，使用 `supervisorScope`：\n\n```kotlin\nsuspend fun syncAll() = supervisorScope {\n    launch { syncItems() }       \u002F\u002F failure here won't cancel syncStats\n    launch { syncStats() }\n    launch { syncSettings() }\n}\n```\n\n## Flow 模式\n\n### Cold Flow —— 一次性操作到流的转换\n\n```kotlin\nfun observeItems(): Flow\u003CList\u003CItem>> = flow {\n    \u002F\u002F Re-emits whenever the database changes\n    itemDao.observeAll()\n        .map { entities -> entities.map { it.toDomain() } }\n        .collect { emit(it) }\n}\n```\n\n### 用于 UI 状态的 StateFlow\n\n```kotlin\nclass DashboardViewModel(\n    observeProgress: ObserveUserProgressUseCase\n) : ViewModel() {\n    val progress: StateFlow\u003CUserProgress> = observeProgress()\n        .stateIn(\n            scope = viewModelScope,\n            started = SharingStarted.WhileSubscribed(5_000),\n            initialValue = UserProgress.EMPTY\n        )\n}\n```\n\n`WhileSubscribed(5_000)` 会在最后一个订阅者离开后，保持上游活动 5 秒——可在配置更改时存活而无需重启。\n\n### 组合多个 Flow\n\n```kotlin\nval uiState: StateFlow\u003CHomeState> = combine(\n    itemRepository.observeItems(),\n    settingsRepository.observeTheme(),\n    userRepository.observeProfile()\n) { items, theme, profile ->\n    HomeState(items = items, theme = theme, profile = profile)\n}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), HomeState())\n```\n\n### Flow 操作符\n\n```kotlin\n\u002F\u002F Debounce search input\nsearchQuery\n    .debounce(300)\n    .distinctUntilChanged()\n    .flatMapLatest { query -> repository.search(query) }\n    .catch { emit(emptyList()) }\n    .collect { results -> _state.update { it.copy(results = results) } }\n\n\u002F\u002F Retry with exponential backoff\nfun fetchWithRetry(): Flow\u003CData> = flow { emit(api.fetch()) }\n    .retryWhen { cause, attempt ->\n        if (cause is IOException && attempt \u003C 3) {\n            delay(1000L * (1 shl attempt.toInt()))\n            true\n        } else {\n            false\n        }\n    }\n```\n\n### 用于一次性事件的 SharedFlow\n\n```kotlin\nclass ItemListViewModel : ViewModel() {\n    private val _effects = MutableSharedFlow\u003CEffect>()\n    val effects: SharedFlow\u003CEffect> = _effects.asSharedFlow()\n\n    sealed interface Effect {\n        data class ShowSnackbar(val message: String) : Effect\n        data class NavigateTo(val route: String) : Effect\n    }\n\n    private fun deleteItem(id: String) {\n        viewModelScope.launch {\n            repository.delete(id)\n            _effects.emit(Effect.ShowSnackbar(\"Item deleted\"))\n        }\n    }\n}\n\n\u002F\u002F Collect in Composable\nLaunchedEffect(Unit) {\n    viewModel.effects.collect { effect ->\n        when (effect) {\n            is Effect.ShowSnackbar -> snackbarHostState.showSnackbar(effect.message)\n            is Effect.NavigateTo -> navController.navigate(effect.route)\n        }\n    }\n}\n```\n\n## 调度器\n\n```kotlin\n\u002F\u002F CPU-intensive work\nwithContext(Dispatchers.Default) { parseJson(largePayload) }\n\n\u002F\u002F IO-bound work\nwithContext(Dispatchers.IO) { database.query() }\n\n\u002F\u002F Main thread (UI) — default in viewModelScope\nwithContext(Dispatchers.Main) { updateUi() }\n```\n\n在 KMP 中，使用 `Dispatchers.Default` 和 `Dispatchers.Main`（在所有平台上可用）。`Dispatchers.IO` 仅适用于 JVM\u002FAndroid——在其他平台上使用 `Dispatchers.Default` 或通过依赖注入提供。\n\n## 取消\n\n### 协作式取消\n\n长时间运行的循环必须检查取消状态：\n\n```kotlin\nsuspend fun processItems(items: List\u003CItem>) = coroutineScope {\n    for (item in items) {\n        ensureActive()  \u002F\u002F throws CancellationException if cancelled\n        process(item)\n    }\n}\n```\n\n### 使用 try\u002Ffinally 进行清理\n\n```kotlin\nviewModelScope.launch {\n    try {\n        _state.update { it.copy(isLoading = true) }\n        val data = repository.fetch()\n        _state.update { it.copy(data = data) }\n    } finally {\n        _state.update { it.copy(isLoading = false) }  \u002F\u002F always runs, even on cancellation\n    }\n}\n```\n\n## 测试\n\n### 使用 Turbine 测试 StateFlow\n\n```kotlin\n@Test\nfun `search updates item list`() = runTest {\n    val fakeRepository = FakeItemRepository().apply { emit(testItems) }\n    val viewModel = ItemListViewModel(GetItemsUseCase(fakeRepository))\n\n    viewModel.state.test {\n        assertEquals(ItemListState(), awaitItem())  \u002F\u002F initial\n\n        viewModel.onSearch(\"query\")\n        val loading = awaitItem()\n        assertTrue(loading.isLoading)\n\n        val loaded = awaitItem()\n        assertFalse(loaded.isLoading)\n        assertEquals(1, loaded.items.size)\n    }\n}\n```\n\n### 使用 TestDispatcher 测试\n\n```kotlin\n@Test\nfun `parallel load completes correctly`() = runTest {\n    val viewModel = DashboardViewModel(\n        itemRepo = FakeItemRepo(),\n        statsRepo = FakeStatsRepo()\n    )\n\n    viewModel.load()\n    advanceUntilIdle()\n\n    val state = viewModel.state.value\n    assertNotNull(state.items)\n    assertNotNull(state.stats)\n}\n```\n\n### 模拟 Flow\n\n```kotlin\nclass FakeItemRepository : ItemRepository {\n    private val _items = MutableStateFlow\u003CList\u003CItem>>(emptyList())\n\n    override fun observeItems(): Flow\u003CList\u003CItem>> = _items\n\n    fun emit(items: List\u003CItem>) { _items.value = items }\n\n    override suspend fun getItemsByCategory(category: String): Result\u003CList\u003CItem>> {\n        return Result.success(_items.value.filter { it.category == category })\n    }\n}\n```\n\n## 应避免的反模式\n\n* 使用 `GlobalScope`——会导致协程泄漏，且无法结构化取消\n* 在没有作用域的情况下于 `init {}` 中收集 Flow——应使用 `viewModelScope.launch`\n* 将 `MutableStateFlow` 与可变集合一起使用——始终使用不可变副本：`_state.update { it.copy(list = it.list + newItem) }`\n* 捕获 `CancellationException`——应让其传播以实现正确的取消\n* 使用 `flowOn(Dispatchers.Main)` 进行收集——收集调度器是调用方的调度器\n* 在 `@Composable` 中创建 `Flow` 而不使用 `remember`——每次重组都会重新创建 Flow\n\n## 参考\n\n关于 Flow 在 UI 层的消费，请参阅技能：`compose-multiplatform-patterns`。\n关于协程在各层中的适用位置，请参阅技能：`android-clean-architecture`。\n","# Kotlin 协程与 Flow\n\n适用于 Android 和 Kotlin 多平台项目的结构化并发模式、基于 Flow 的响应式流以及协程测试。\n\n## 何时启用\n\n* 使用 Kotlin 协程编写异步代码\n* 使用 Flow、StateFlow 或 SharedFlow 实现响应式数据\n* 处理并发操作（并行加载、防抖、重试）\n* 测试协程和 Flow\n* 管理协程作用域与取消\n\n## 结构化并发\n\n### 作用域层级\n\n```\nApplication\n  └── viewModelScope (ViewModel)\n        └── coroutineScope { } (结构化子作用域)\n              ├── async { } (并发任务)\n              └── async { } (并发任务)\n```\n\n始终使用结构化并发——绝不使用 `GlobalScope`：\n\n```kotlin\n\u002F\u002F BAD\nGlobalScope.launch { fetchData() }\n\n\u002F\u002F GOOD — scoped to ViewModel lifecycle\nviewModelScope.launch { fetchData() }\n\n\u002F\u002F GOOD — scoped to composable lifecycle\nLaunchedEffect(key) { fetchData() }\n```\n\n### 并行分解\n\n使用 `coroutineScope` + `async` 处理并行工作：\n\n```kotlin\nsuspend fun loadDashboard(): Dashboard = coroutineScope {\n    val items = async { itemRepository.getRecent() }\n    val stats = async { statsRepository.getToday() }\n    val profile = async { userRepository.getCurrent() }\n    Dashboard(\n        items = items.await(),\n        stats = stats.await(),\n        profile = profile.await()\n    )\n}\n```\n\n### SupervisorScope\n\n当子协程失败不应取消同级协程时，使用 `supervisorScope`：\n\n```kotlin\nsuspend fun syncAll() = supervisorScope {\n    launch { syncItems() }       \u002F\u002F failure here won't cancel syncStats\n    launch { syncStats() }\n    launch { syncSettings() }\n}\n```\n\n## Flow 模式\n\n### Cold Flow —— 一次性操作到流的转换\n\n```kotlin\nfun observeItems(): Flow\u003CList\u003CItem>> = flow {\n    \u002F\u002F Re-emits whenever the database changes\n    itemDao.observeAll()\n        .map { entities -> entities.map { it.toDomain() } }\n        .collect { emit(it) }\n}\n```\n\n### 用于 UI 状态的 StateFlow\n\n```kotlin\nclass DashboardViewModel(\n    observeProgress: ObserveUserProgressUseCase\n) : ViewModel() {\n    val progress: StateFlow\u003CUserProgress> = observeProgress()\n        .stateIn(\n            scope = viewModelScope,\n            started = SharingStarted.WhileSubscribed(5_000),\n            initialValue = UserProgress.EMPTY\n        )\n}\n```\n\n`WhileSubscribed(5_000)` 会在最后一个订阅者离开后，保持上游活动 5 秒——可在配置更改时存活而无需重启。\n\n### 组合多个 Flow\n\n```kotlin\nval uiState: StateFlow\u003CHomeState> = combine(\n    itemRepository.observeItems(),\n    settingsRepository.observeTheme(),\n    userRepository.observeProfile()\n) { items, theme, profile ->\n    HomeState(items = items, theme = theme, profile = profile)\n}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), HomeState())\n```\n\n### Flow 操作符\n\n```kotlin\n\u002F\u002F Debounce search input\nsearchQuery\n    .debounce(300)\n    .distinctUntilChanged()\n    .flatMapLatest { query -> repository.search(query) }\n    .catch { emit(emptyList()) }\n    .collect { results -> _state.update { it.copy(results = results) } }\n\n\u002F\u002F Retry with exponential backoff\nfun fetchWithRetry(): Flow\u003CData> = flow { emit(api.fetch()) }\n    .retryWhen { cause, attempt ->\n        if (cause is IOException && attempt \u003C 3) {\n            delay(1000L * (1 shl attempt.toInt()))\n            true\n        } else {\n            false\n        }\n    }\n```\n\n### 用于一次性事件的 SharedFlow\n\n```kotlin\nclass ItemListViewModel : ViewModel() {\n    private val _effects = MutableSharedFlow\u003CEffect>()\n    val effects: SharedFlow\u003CEffect> = _effects.asSharedFlow()\n\n    sealed interface Effect {\n        data class ShowSnackbar(val message: String) : Effect\n        data class NavigateTo(val route: String) : Effect\n    }\n\n    private fun deleteItem(id: String) {\n        viewModelScope.launch {\n            repository.delete(id)\n            _effects.emit(Effect.ShowSnackbar(\"Item deleted\"))\n        }\n    }\n}\n\n\u002F\u002F Collect in Composable\nLaunchedEffect(Unit) {\n    viewModel.effects.collect { effect ->\n        when (effect) {\n            is Effect.ShowSnackbar -> snackbarHostState.showSnackbar(effect.message)\n            is Effect.NavigateTo -> navController.navigate(effect.route)\n        }\n    }\n}\n```\n\n## 调度器\n\n```kotlin\n\u002F\u002F CPU-intensive work\nwithContext(Dispatchers.Default) { parseJson(largePayload) }\n\n\u002F\u002F IO-bound work\nwithContext(Dispatchers.IO) { database.query() }\n\n\u002F\u002F Main thread (UI) — default in viewModelScope\nwithContext(Dispatchers.Main) { updateUi() }\n```\n\n在 KMP 中，使用 `Dispatchers.Default` 和 `Dispatchers.Main`（在所有平台上可用）。`Dispatchers.IO` 仅适用于 JVM\u002FAndroid——在其他平台上使用 `Dispatchers.Default` 或通过依赖注入提供。\n\n## 取消\n\n### 协作式取消\n\n长时间运行的循环必须检查取消状态：\n\n```kotlin\nsuspend fun processItems(items: List\u003CItem>) = coroutineScope {\n    for (item in items) {\n        ensureActive()  \u002F\u002F throws CancellationException if cancelled\n        process(item)\n    }\n}\n```\n\n### 使用 try\u002Ffinally 进行清理\n\n```kotlin\nviewModelScope.launch {\n    try {\n        _state.update { it.copy(isLoading = true) }\n        val data = repository.fetch()\n        _state.update { it.copy(data = data) }\n    } finally {\n        _state.update { it.copy(isLoading = false) }  \u002F\u002F always runs, even on cancellation\n    }\n}\n```\n\n## 测试\n\n### 使用 Turbine 测试 StateFlow\n\n```kotlin\n@Test\nfun `search updates item list`() = runTest {\n    val fakeRepository = FakeItemRepository().apply { emit(testItems) }\n    val viewModel = ItemListViewModel(GetItemsUseCase(fakeRepository))\n\n    viewModel.state.test {\n        assertEquals(ItemListState(), awaitItem())  \u002F\u002F initial\n\n        viewModel.onSearch(\"query\")\n        val loading = awaitItem()\n        assertTrue(loading.isLoading)\n\n        val loaded = awaitItem()\n        assertFalse(loaded.isLoading)\n        assertEquals(1, loaded.items.size)\n    }\n}\n```\n\n### 使用 TestDispatcher 测试\n\n```kotlin\n@Test\nfun `parallel load completes correctly`() = runTest {\n    val viewModel = DashboardViewModel(\n        itemRepo = FakeItemRepo(),\n        statsRepo = FakeStatsRepo()\n    )\n\n    viewModel.load()\n    advanceUntilIdle()\n\n    val state = viewModel.state.value\n    assertNotNull(state.items)\n    assertNotNull(state.stats)\n}\n```\n\n### 模拟 Flow\n\n```kotlin\nclass FakeItemRepository : ItemRepository {\n    private val _items = MutableStateFlow\u003CList\u003CItem>>(emptyList())\n\n    override fun observeItems(): Flow\u003CList\u003CItem>> = _items\n\n    fun emit(items: List\u003CItem>) { _items.value = items }\n\n    override suspend fun getItemsByCategory(category: String): Result\u003CList\u003CItem>> {\n        return Result.success(_items.value.filter { it.category == category })\n    }\n}\n```\n\n## 应避免的反模式\n\n* 使用 `GlobalScope`——会导致协程泄漏，且无法结构化取消\n* 在没有作用域的情况下于 `init {}` 中收集 Flow——应使用 `viewModelScope.launch`\n* 将 `MutableStateFlow` 与可变集合一起使用——始终使用不可变副本：`_state.update { it.copy(list = it.list + newItem) }`\n* 捕获 `CancellationException`——应让其传播以实现正确的取消\n* 使用 `flowOn(Dispatchers.Main)` 进行收集——收集调度器是调用方的调度器\n* 在 `@Composable` 中创建 `Flow` 而不使用 `remember`——每次重组都会重新创建 Flow\n\n## 参考\n\n关于 Flow 在 UI 层的消费，请参阅技能：`compose-multiplatform-patterns`。\n关于协程在各层中的适用位置，请参阅技能：`android-clean-architecture`。\n",{"name":5,"origin":24,"description":7},"ECC","master","d6ca01da0f24a3b0e26e4a8b7b66cbd25d429f5d","docs\u002Fzh-CN\u002Fskills\u002Fkotlin-coroutines-flows",0,"https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills","https:\u002F\u002Fgithub.com\u002FSriramGandhiS","https:\u002F\u002Fsriram.website\u002F","Curious guy who keeps tinkering until something works","2026-05-20 16:21:34",{"source":8,"skillName":5,"commands":35,"prompt":45,"zipAvailable":46},[36,39,42],{"tool":37,"command":38},"npx","npx skills add SriramGandhiS\u002FSkills --skill kotlin-coroutines-flows",{"tool":40,"command":41},"bunx","bunx skills add SriramGandhiS\u002FSkills --skill kotlin-coroutines-flows",{"tool":43,"command":44},"pnpm","pnpm dlx skills add SriramGandhiS\u002FSkills --skill kotlin-coroutines-flows","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fdocs\u002Fzh-CN\u002Fskills\u002Fkotlin-coroutines-flows\u002FSKILL.md",true,[],[49,57,62,68,75,82],{"skillNo":50,"name":51,"nameZh":6,"description":52,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":53,"categories":54,"keywords":55,"publishedAt":56},"01M732609EPJWV13PVTX3GT4TM","webgpu-threejs-tsl","Comprehensive guide for developing WebGPU-enabled Three.js applications using TSL (Three.js Shading Language). Covers WebGPU renderer setup, TSL syntax and node materials, compute shaders, post-processing effects, and WGSL integration. Use this skill when working with Three.js WebGPU, TSL shaders, node materials, or GPU compute in Three.js.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fwebgpu-threejs-tsl\u002Fskills\u002Fwebgpu-threejs-tsl\u002FSKILL.md",[],[],"2026-11-11 15:11:14",{"skillNo":58,"name":51,"nameZh":6,"description":52,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":59,"categories":60,"keywords":61,"publishedAt":56},"01M7325XM47AGWB6K6C4VXKE6B","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fwebgpu-threejs-tsl\u002FSKILL.md",[],[],{"skillNo":63,"name":64,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":65,"categories":66,"keywords":67,"publishedAt":56},"01M7325WP6DES69JKC840VMFEP","verification-loop","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Fverification-loop\u002FSKILL.md",[],[],{"skillNo":69,"name":70,"nameZh":6,"description":71,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":72,"categories":73,"keywords":74,"publishedAt":56},"01M7325TFQF1DZTQ6J3WGQQ1VR","tdd-workflow","Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Ftdd-workflow\u002FSKILL.md",[],[],{"skillNo":76,"name":77,"nameZh":6,"description":78,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":81,"publishedAt":56},"01M7325RGV9AY9PK92D2V8KKPW","strategic-compact","Suggests manual context compaction at logical intervals to preserve context through task phases rather than arbitrary auto-compaction.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Fstrategic-compact\u002FSKILL.md",[],[],{"skillNo":83,"name":84,"nameZh":6,"description":85,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":56},"01M7325MZC28SE86E7NMCNEFS4","security-review","Use this skill when adding authentication, handling user input, working with secrets, creating API endpoints, or implementing payment\u002Fsensitive features. Provides comprehensive security checklist and patterns.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Fsecurity-review\u002FSKILL.md",[],[]]