@raishin/vanguard-frontier-agentic 3.4.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +17 -1
- package/.cursor-plugin/plugin.json +17 -1
- package/.github/plugin/marketplace.json +1 -1
- package/README.md +19 -13
- package/agents/kotlin/kotlin-android-architecture-agent/AGENT.md +80 -0
- package/agents/kotlin/kotlin-android-architecture-agent/harnesses/claude-code.agent.md +63 -0
- package/agents/kotlin/kotlin-android-architecture-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-android-architecture-agent/harnesses/copilot.agent.md +70 -0
- package/agents/kotlin/kotlin-android-architecture-agent/harnesses/cursor.agent.md +63 -0
- package/agents/kotlin/kotlin-android-architecture-agent/harnesses/gemini.agent.md +63 -0
- package/agents/kotlin/kotlin-android-architecture-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-android-architecture-agent/harnesses/kiro-ide.agent.md +63 -0
- package/agents/kotlin/kotlin-android-architecture-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-android-performance-reliability-agent/AGENT.md +80 -0
- package/agents/kotlin/kotlin-android-performance-reliability-agent/harnesses/claude-code.agent.md +63 -0
- package/agents/kotlin/kotlin-android-performance-reliability-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-android-performance-reliability-agent/harnesses/copilot.agent.md +70 -0
- package/agents/kotlin/kotlin-android-performance-reliability-agent/harnesses/cursor.agent.md +63 -0
- package/agents/kotlin/kotlin-android-performance-reliability-agent/harnesses/gemini.agent.md +63 -0
- package/agents/kotlin/kotlin-android-performance-reliability-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-android-performance-reliability-agent/harnesses/kiro-ide.agent.md +63 -0
- package/agents/kotlin/kotlin-android-performance-reliability-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-android-security-privacy-agent/AGENT.md +83 -0
- package/agents/kotlin/kotlin-android-security-privacy-agent/harnesses/claude-code.agent.md +66 -0
- package/agents/kotlin/kotlin-android-security-privacy-agent/harnesses/codex.toml +40 -0
- package/agents/kotlin/kotlin-android-security-privacy-agent/harnesses/copilot.agent.md +73 -0
- package/agents/kotlin/kotlin-android-security-privacy-agent/harnesses/cursor.agent.md +66 -0
- package/agents/kotlin/kotlin-android-security-privacy-agent/harnesses/gemini.agent.md +66 -0
- package/agents/kotlin/kotlin-android-security-privacy-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-android-security-privacy-agent/harnesses/kiro-ide.agent.md +66 -0
- package/agents/kotlin/kotlin-android-security-privacy-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-backend-production-readiness-agent/AGENT.md +81 -0
- package/agents/kotlin/kotlin-backend-production-readiness-agent/harnesses/claude-code.agent.md +64 -0
- package/agents/kotlin/kotlin-backend-production-readiness-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-backend-production-readiness-agent/harnesses/copilot.agent.md +71 -0
- package/agents/kotlin/kotlin-backend-production-readiness-agent/harnesses/cursor.agent.md +64 -0
- package/agents/kotlin/kotlin-backend-production-readiness-agent/harnesses/gemini.agent.md +64 -0
- package/agents/kotlin/kotlin-backend-production-readiness-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-backend-production-readiness-agent/harnesses/kiro-ide.agent.md +64 -0
- package/agents/kotlin/kotlin-backend-production-readiness-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-compose-ui-quality-accessibility-agent/AGENT.md +80 -0
- package/agents/kotlin/kotlin-compose-ui-quality-accessibility-agent/harnesses/claude-code.agent.md +63 -0
- package/agents/kotlin/kotlin-compose-ui-quality-accessibility-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-compose-ui-quality-accessibility-agent/harnesses/copilot.agent.md +70 -0
- package/agents/kotlin/kotlin-compose-ui-quality-accessibility-agent/harnesses/cursor.agent.md +63 -0
- package/agents/kotlin/kotlin-compose-ui-quality-accessibility-agent/harnesses/gemini.agent.md +63 -0
- package/agents/kotlin/kotlin-compose-ui-quality-accessibility-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-compose-ui-quality-accessibility-agent/harnesses/kiro-ide.agent.md +63 -0
- package/agents/kotlin/kotlin-compose-ui-quality-accessibility-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-coroutines-flow-reliability-agent/AGENT.md +80 -0
- package/agents/kotlin/kotlin-coroutines-flow-reliability-agent/harnesses/claude-code.agent.md +63 -0
- package/agents/kotlin/kotlin-coroutines-flow-reliability-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-coroutines-flow-reliability-agent/harnesses/copilot.agent.md +70 -0
- package/agents/kotlin/kotlin-coroutines-flow-reliability-agent/harnesses/cursor.agent.md +63 -0
- package/agents/kotlin/kotlin-coroutines-flow-reliability-agent/harnesses/gemini.agent.md +63 -0
- package/agents/kotlin/kotlin-coroutines-flow-reliability-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-coroutines-flow-reliability-agent/harnesses/kiro-ide.agent.md +63 -0
- package/agents/kotlin/kotlin-coroutines-flow-reliability-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-estate-modernization-governor-agent/AGENT.md +81 -0
- package/agents/kotlin/kotlin-estate-modernization-governor-agent/harnesses/claude-code.agent.md +64 -0
- package/agents/kotlin/kotlin-estate-modernization-governor-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-estate-modernization-governor-agent/harnesses/copilot.agent.md +71 -0
- package/agents/kotlin/kotlin-estate-modernization-governor-agent/harnesses/cursor.agent.md +64 -0
- package/agents/kotlin/kotlin-estate-modernization-governor-agent/harnesses/gemini.agent.md +64 -0
- package/agents/kotlin/kotlin-estate-modernization-governor-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-estate-modernization-governor-agent/harnesses/kiro-ide.agent.md +64 -0
- package/agents/kotlin/kotlin-estate-modernization-governor-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-gradle-build-engineering-agent/AGENT.md +80 -0
- package/agents/kotlin/kotlin-gradle-build-engineering-agent/harnesses/claude-code.agent.md +63 -0
- package/agents/kotlin/kotlin-gradle-build-engineering-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-gradle-build-engineering-agent/harnesses/copilot.agent.md +70 -0
- package/agents/kotlin/kotlin-gradle-build-engineering-agent/harnesses/cursor.agent.md +63 -0
- package/agents/kotlin/kotlin-gradle-build-engineering-agent/harnesses/gemini.agent.md +63 -0
- package/agents/kotlin/kotlin-gradle-build-engineering-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-gradle-build-engineering-agent/harnesses/kiro-ide.agent.md +63 -0
- package/agents/kotlin/kotlin-gradle-build-engineering-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-kmp-boundary-interop-agent/AGENT.md +80 -0
- package/agents/kotlin/kotlin-kmp-boundary-interop-agent/harnesses/claude-code.agent.md +63 -0
- package/agents/kotlin/kotlin-kmp-boundary-interop-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-kmp-boundary-interop-agent/harnesses/copilot.agent.md +70 -0
- package/agents/kotlin/kotlin-kmp-boundary-interop-agent/harnesses/cursor.agent.md +63 -0
- package/agents/kotlin/kotlin-kmp-boundary-interop-agent/harnesses/gemini.agent.md +63 -0
- package/agents/kotlin/kotlin-kmp-boundary-interop-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-kmp-boundary-interop-agent/harnesses/kiro-ide.agent.md +63 -0
- package/agents/kotlin/kotlin-kmp-boundary-interop-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-kmp-portfolio-decision-agent/AGENT.md +80 -0
- package/agents/kotlin/kotlin-kmp-portfolio-decision-agent/harnesses/claude-code.agent.md +63 -0
- package/agents/kotlin/kotlin-kmp-portfolio-decision-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-kmp-portfolio-decision-agent/harnesses/copilot.agent.md +70 -0
- package/agents/kotlin/kotlin-kmp-portfolio-decision-agent/harnesses/cursor.agent.md +63 -0
- package/agents/kotlin/kotlin-kmp-portfolio-decision-agent/harnesses/gemini.agent.md +63 -0
- package/agents/kotlin/kotlin-kmp-portfolio-decision-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-kmp-portfolio-decision-agent/harnesses/kiro-ide.agent.md +63 -0
- package/agents/kotlin/kotlin-kmp-portfolio-decision-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-language-api-correctness-agent/AGENT.md +81 -0
- package/agents/kotlin/kotlin-language-api-correctness-agent/harnesses/claude-code.agent.md +64 -0
- package/agents/kotlin/kotlin-language-api-correctness-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-language-api-correctness-agent/harnesses/copilot.agent.md +71 -0
- package/agents/kotlin/kotlin-language-api-correctness-agent/harnesses/cursor.agent.md +64 -0
- package/agents/kotlin/kotlin-language-api-correctness-agent/harnesses/gemini.agent.md +64 -0
- package/agents/kotlin/kotlin-language-api-correctness-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-language-api-correctness-agent/harnesses/kiro-ide.agent.md +64 -0
- package/agents/kotlin/kotlin-language-api-correctness-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-library-api-abi-governance-agent/AGENT.md +80 -0
- package/agents/kotlin/kotlin-library-api-abi-governance-agent/harnesses/claude-code.agent.md +63 -0
- package/agents/kotlin/kotlin-library-api-abi-governance-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-library-api-abi-governance-agent/harnesses/copilot.agent.md +70 -0
- package/agents/kotlin/kotlin-library-api-abi-governance-agent/harnesses/cursor.agent.md +63 -0
- package/agents/kotlin/kotlin-library-api-abi-governance-agent/harnesses/gemini.agent.md +63 -0
- package/agents/kotlin/kotlin-library-api-abi-governance-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-library-api-abi-governance-agent/harnesses/kiro-ide.agent.md +63 -0
- package/agents/kotlin/kotlin-library-api-abi-governance-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-maestro-agent/AGENT.md +55 -0
- package/agents/kotlin/kotlin-maestro-agent/README.md +65 -0
- package/agents/kotlin/kotlin-maestro-agent/harnesses/claude-code.agent.md +38 -0
- package/agents/kotlin/kotlin-maestro-agent/harnesses/codex.toml +37 -0
- package/agents/kotlin/kotlin-maestro-agent/harnesses/copilot.agent.md +45 -0
- package/agents/kotlin/kotlin-maestro-agent/harnesses/cursor.agent.md +38 -0
- package/agents/kotlin/kotlin-maestro-agent/harnesses/gemini.agent.md +38 -0
- package/agents/kotlin/kotlin-maestro-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-maestro-agent/harnesses/kiro-ide.agent.md +38 -0
- package/agents/kotlin/kotlin-maestro-agent/metadata.json +40 -0
- package/agents/kotlin/kotlin-serialization-wire-contract-agent/AGENT.md +80 -0
- package/agents/kotlin/kotlin-serialization-wire-contract-agent/harnesses/claude-code.agent.md +63 -0
- package/agents/kotlin/kotlin-serialization-wire-contract-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-serialization-wire-contract-agent/harnesses/copilot.agent.md +70 -0
- package/agents/kotlin/kotlin-serialization-wire-contract-agent/harnesses/cursor.agent.md +63 -0
- package/agents/kotlin/kotlin-serialization-wire-contract-agent/harnesses/gemini.agent.md +63 -0
- package/agents/kotlin/kotlin-serialization-wire-contract-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-serialization-wire-contract-agent/harnesses/kiro-ide.agent.md +63 -0
- package/agents/kotlin/kotlin-serialization-wire-contract-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-supply-chain-release-integrity-agent/AGENT.md +80 -0
- package/agents/kotlin/kotlin-supply-chain-release-integrity-agent/harnesses/claude-code.agent.md +63 -0
- package/agents/kotlin/kotlin-supply-chain-release-integrity-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-supply-chain-release-integrity-agent/harnesses/copilot.agent.md +70 -0
- package/agents/kotlin/kotlin-supply-chain-release-integrity-agent/harnesses/cursor.agent.md +63 -0
- package/agents/kotlin/kotlin-supply-chain-release-integrity-agent/harnesses/gemini.agent.md +63 -0
- package/agents/kotlin/kotlin-supply-chain-release-integrity-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-supply-chain-release-integrity-agent/harnesses/kiro-ide.agent.md +63 -0
- package/agents/kotlin/kotlin-supply-chain-release-integrity-agent/metadata.json +41 -0
- package/agents/kotlin/kotlin-test-architecture-agent/AGENT.md +80 -0
- package/agents/kotlin/kotlin-test-architecture-agent/harnesses/claude-code.agent.md +63 -0
- package/agents/kotlin/kotlin-test-architecture-agent/harnesses/codex.toml +39 -0
- package/agents/kotlin/kotlin-test-architecture-agent/harnesses/copilot.agent.md +70 -0
- package/agents/kotlin/kotlin-test-architecture-agent/harnesses/cursor.agent.md +63 -0
- package/agents/kotlin/kotlin-test-architecture-agent/harnesses/gemini.agent.md +63 -0
- package/agents/kotlin/kotlin-test-architecture-agent/harnesses/kiro-cli.agent.json +5 -0
- package/agents/kotlin/kotlin-test-architecture-agent/harnesses/kiro-ide.agent.md +63 -0
- package/agents/kotlin/kotlin-test-architecture-agent/metadata.json +41 -0
- package/catalog/agents.json +463 -0
- package/catalog/asset-integrity.json +1074 -44
- package/catalog/install-roles.json +142 -0
- package/catalog/model-assignments.json +528 -0
- package/catalog/skill-manifest.json +632 -0
- package/catalog/skills.json +431 -0
- package/package.json +2 -2
- package/plugins/vanguard-frontier-agentic/.codex-plugin/plugin.json +1 -1
- package/powers/README.md +3 -2
- package/powers/vanguard-kotlin/POWER.md +40 -0
- package/schemas/agent.schema.json +1 -0
- package/schemas/skill.schema.json +1 -0
- package/scripts/gen_kotlin_agents.py +537 -0
- package/scripts/generate-docs-data.mjs +1 -1
- package/scripts/kotlin_data/agents/00-kotlin-maestro-agent.json +90 -0
- package/scripts/kotlin_data/agents/01-kotlin-estate-modernization-governor-agent.json +132 -0
- package/scripts/kotlin_data/agents/02-kotlin-language-api-correctness-agent.json +145 -0
- package/scripts/kotlin_data/agents/03-kotlin-coroutines-flow-reliability-agent.json +145 -0
- package/scripts/kotlin_data/agents/04-kotlin-library-api-abi-governance-agent.json +144 -0
- package/scripts/kotlin_data/agents/05-kotlin-backend-production-readiness-agent.json +144 -0
- package/scripts/kotlin_data/agents/06-kotlin-serialization-wire-contract-agent.json +144 -0
- package/scripts/kotlin_data/agents/07-kotlin-android-architecture-agent.json +130 -0
- package/scripts/kotlin_data/agents/08-kotlin-compose-ui-quality-accessibility-agent.json +132 -0
- package/scripts/kotlin_data/agents/09-kotlin-android-security-privacy-agent.json +147 -0
- package/scripts/kotlin_data/agents/10-kotlin-android-performance-reliability-agent.json +129 -0
- package/scripts/kotlin_data/agents/11-kotlin-kmp-portfolio-decision-agent.json +131 -0
- package/scripts/kotlin_data/agents/12-kotlin-kmp-boundary-interop-agent.json +132 -0
- package/scripts/kotlin_data/agents/13-kotlin-gradle-build-engineering-agent.json +141 -0
- package/scripts/kotlin_data/agents/14-kotlin-supply-chain-release-integrity-agent.json +139 -0
- package/scripts/kotlin_data/agents/15-kotlin-test-architecture-agent.json +140 -0
- package/scripts/update-catalog-new-agents.py +71 -42
- package/skills/kotlin/kotlin-android-architecture/SKILL.md +62 -0
- package/skills/kotlin/kotlin-android-architecture/metadata.json +27 -0
- package/skills/kotlin/kotlin-android-architecture/references/lifecycle-aware-collection-and-udf.md +12 -0
- package/skills/kotlin/kotlin-android-architecture/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-android-architecture/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-android-architecture/references/viewmodel-lifecycle-and-state-persistence.md +12 -0
- package/skills/kotlin/kotlin-android-performance-reliability/SKILL.md +62 -0
- package/skills/kotlin/kotlin-android-performance-reliability/metadata.json +27 -0
- package/skills/kotlin/kotlin-android-performance-reliability/references/jank-anr-and-regression-gating.md +12 -0
- package/skills/kotlin/kotlin-android-performance-reliability/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-android-performance-reliability/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-android-performance-reliability/references/startup-and-baseline-profiles.md +11 -0
- package/skills/kotlin/kotlin-android-security-privacy/SKILL.md +64 -0
- package/skills/kotlin/kotlin-android-security-privacy/metadata.json +27 -0
- package/skills/kotlin/kotlin-android-security-privacy/references/component-exposure-and-intents.md +12 -0
- package/skills/kotlin/kotlin-android-security-privacy/references/masvs-mapping.md +12 -0
- package/skills/kotlin/kotlin-android-security-privacy/references/network-webview-and-storage.md +12 -0
- package/skills/kotlin/kotlin-android-security-privacy/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-android-security-privacy/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-backend-production-readiness/SKILL.md +63 -0
- package/skills/kotlin/kotlin-backend-production-readiness/metadata.json +27 -0
- package/skills/kotlin/kotlin-backend-production-readiness/references/ktor-lifecycle-and-graceful-shutdown.md +12 -0
- package/skills/kotlin/kotlin-backend-production-readiness/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-backend-production-readiness/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-backend-production-readiness/references/spring-webflux-coroutine-handlers.md +11 -0
- package/skills/kotlin/kotlin-backend-production-readiness/references/status-pages-and-error-mapping.md +12 -0
- package/skills/kotlin/kotlin-compose-ui-quality-accessibility/SKILL.md +62 -0
- package/skills/kotlin/kotlin-compose-ui-quality-accessibility/metadata.json +27 -0
- package/skills/kotlin/kotlin-compose-ui-quality-accessibility/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-compose-ui-quality-accessibility/references/recomposition-stability-and-side-effects.md +13 -0
- package/skills/kotlin/kotlin-compose-ui-quality-accessibility/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-compose-ui-quality-accessibility/references/state-hoisting-and-accessibility.md +13 -0
- package/skills/kotlin/kotlin-coroutines-flow-reliability/SKILL.md +62 -0
- package/skills/kotlin/kotlin-coroutines-flow-reliability/metadata.json +27 -0
- package/skills/kotlin/kotlin-coroutines-flow-reliability/references/dispatchers-blocking-and-context.md +13 -0
- package/skills/kotlin/kotlin-coroutines-flow-reliability/references/flow-state-sharing-and-backpressure.md +12 -0
- package/skills/kotlin/kotlin-coroutines-flow-reliability/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-coroutines-flow-reliability/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-coroutines-flow-reliability/references/structured-concurrency-and-cancellation.md +13 -0
- package/skills/kotlin/kotlin-estate-modernization-governor/SKILL.md +62 -0
- package/skills/kotlin/kotlin-estate-modernization-governor/metadata.json +27 -0
- package/skills/kotlin/kotlin-estate-modernization-governor/references/interop-boundary-and-converter-governance.md +12 -0
- package/skills/kotlin/kotlin-estate-modernization-governor/references/migration-sequencing-and-reversibility.md +13 -0
- package/skills/kotlin/kotlin-estate-modernization-governor/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-estate-modernization-governor/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-gradle-build-engineering/SKILL.md +62 -0
- package/skills/kotlin/kotlin-gradle-build-engineering/metadata.json +27 -0
- package/skills/kotlin/kotlin-gradle-build-engineering/references/annotation-processing-kapt-vs-ksp.md +11 -0
- package/skills/kotlin/kotlin-gradle-build-engineering/references/configuration-cache-and-build-cache.md +13 -0
- package/skills/kotlin/kotlin-gradle-build-engineering/references/convention-plugins-and-build-logic.md +10 -0
- package/skills/kotlin/kotlin-gradle-build-engineering/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-gradle-build-engineering/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-kmp-boundary-interop/SKILL.md +62 -0
- package/skills/kotlin/kotlin-kmp-boundary-interop/metadata.json +27 -0
- package/skills/kotlin/kotlin-kmp-boundary-interop/references/native-runtime-and-swift-interop.md +13 -0
- package/skills/kotlin/kotlin-kmp-boundary-interop/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-kmp-boundary-interop/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-kmp-boundary-interop/references/source-sets-expect-actual-and-leakage.md +13 -0
- package/skills/kotlin/kotlin-kmp-portfolio-decision/SKILL.md +62 -0
- package/skills/kotlin/kotlin-kmp-portfolio-decision/metadata.json +27 -0
- package/skills/kotlin/kotlin-kmp-portfolio-decision/references/adoption-factors-and-team-topology.md +12 -0
- package/skills/kotlin/kotlin-kmp-portfolio-decision/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-kmp-portfolio-decision/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-kmp-portfolio-decision/references/scope-boundaries-and-reversibility.md +13 -0
- package/skills/kotlin/kotlin-language-api-correctness/SKILL.md +63 -0
- package/skills/kotlin/kotlin-language-api-correctness/metadata.json +27 -0
- package/skills/kotlin/kotlin-language-api-correctness/references/extension-dispatch-and-lateinit.md +12 -0
- package/skills/kotlin/kotlin-language-api-correctness/references/inline-reified-and-value-classes.md +12 -0
- package/skills/kotlin/kotlin-language-api-correctness/references/nullability-and-java-interop.md +12 -0
- package/skills/kotlin/kotlin-language-api-correctness/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-language-api-correctness/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-library-api-abi-governance/SKILL.md +63 -0
- package/skills/kotlin/kotlin-library-api-abi-governance/metadata.json +27 -0
- package/skills/kotlin/kotlin-library-api-abi-governance/references/binary-compatibility-validator-and-explicit-api.md +12 -0
- package/skills/kotlin/kotlin-library-api-abi-governance/references/data-class-and-inline-abi-surface.md +12 -0
- package/skills/kotlin/kotlin-library-api-abi-governance/references/jvm-facing-surface-annotations.md +12 -0
- package/skills/kotlin/kotlin-library-api-abi-governance/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-library-api-abi-governance/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-maestro/SKILL.md +58 -0
- package/skills/kotlin/kotlin-maestro/metadata.json +26 -0
- package/skills/kotlin/kotlin-maestro/references/official-sources.md +13 -0
- package/skills/kotlin/kotlin-maestro/references/routing-taxonomy.md +7 -0
- package/skills/kotlin/kotlin-maestro/references/safety-checklist.md +20 -0
- package/skills/kotlin/kotlin-serialization-wire-contract/SKILL.md +63 -0
- package/skills/kotlin/kotlin-serialization-wire-contract/metadata.json +27 -0
- package/skills/kotlin/kotlin-serialization-wire-contract/references/decode-strictness-and-schema-evolution.md +12 -0
- package/skills/kotlin/kotlin-serialization-wire-contract/references/encode-defaults-and-null-handling.md +12 -0
- package/skills/kotlin/kotlin-serialization-wire-contract/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-serialization-wire-contract/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-serialization-wire-contract/references/sealed-polymorphism-and-discriminators.md +12 -0
- package/skills/kotlin/kotlin-supply-chain-release-integrity/SKILL.md +62 -0
- package/skills/kotlin/kotlin-supply-chain-release-integrity/metadata.json +27 -0
- package/skills/kotlin/kotlin-supply-chain-release-integrity/references/dependency-verification-and-locking.md +12 -0
- package/skills/kotlin/kotlin-supply-chain-release-integrity/references/kmp-publication-controls.md +10 -0
- package/skills/kotlin/kotlin-supply-chain-release-integrity/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-supply-chain-release-integrity/references/plugin-trust-and-repository-scope.md +10 -0
- package/skills/kotlin/kotlin-supply-chain-release-integrity/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-test-architecture/SKILL.md +62 -0
- package/skills/kotlin/kotlin-test-architecture/metadata.json +27 -0
- package/skills/kotlin/kotlin-test-architecture/references/compose-and-android-test-boundary.md +11 -0
- package/skills/kotlin/kotlin-test-architecture/references/official-sources.md +14 -0
- package/skills/kotlin/kotlin-test-architecture/references/runtest-and-dispatcher-control.md +12 -0
- package/skills/kotlin/kotlin-test-architecture/references/safety-checklist.md +22 -0
- package/skills/kotlin/kotlin-test-architecture/references/turbine-flow-testing.md +10 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/001-happy-android-architecture.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/002-happy-android-performance-reliability.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/003-happy-android-security-privacy.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/004-happy-backend-production-readiness.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/005-happy-compose-ui-quality-accessibility.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/006-happy-coroutines-flow-reliability.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/007-happy-estate-modernization-governor.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/008-happy-gradle-build-engineering.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/009-happy-kmp-boundary-interop.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/010-happy-kmp-portfolio-decision.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/011-happy-language-api-correctness.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/012-happy-library-api-abi-governance.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/013-happy-serialization-wire-contract.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/014-happy-supply-chain-release-integrity.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/015-happy-test-architecture.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/adv-ambiguous.json +4 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/adv-instruction-injection.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/adv-mutation-deploy.json +4 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/adv-mutation-publish.json +4 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/adv-persona-replacement.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/expected/adv-secrets-bait.json +6 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/001-happy-android-architecture.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/002-happy-android-performance-reliability.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/003-happy-android-security-privacy.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/004-happy-backend-production-readiness.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/005-happy-compose-ui-quality-accessibility.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/006-happy-coroutines-flow-reliability.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/007-happy-estate-modernization-governor.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/008-happy-gradle-build-engineering.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/009-happy-kmp-boundary-interop.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/010-happy-kmp-portfolio-decision.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/011-happy-language-api-correctness.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/012-happy-library-api-abi-governance.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/013-happy-serialization-wire-contract.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/014-happy-supply-chain-release-integrity.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/015-happy-test-architecture.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/adv-ambiguous.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/adv-instruction-injection.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/adv-mutation-deploy.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/adv-mutation-publish.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/adv-persona-replacement.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/inputs/adv-secrets-bait.json +7 -0
- package/tests/fixtures/kotlin-maestro-routing/taxonomy.json +182 -0
- package/tests/validate-catalog.py +1 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "kotlin-gradle-build-engineering-agent",
|
|
3
|
+
"name": "Kotlin Gradle Build Engineering Agent",
|
|
4
|
+
"domain_key": "gradle-build-engineering",
|
|
5
|
+
"routing_keywords": ["Gradle", "configuration cache", "build cache", "incremental compilation", "kapt", "KSP", "convention plugin", "build-logic", "task graph", "CI throughput"],
|
|
6
|
+
"summary": "Static review of Gradle build-graph quality and CI throughput for Kotlin/KMP projects: configuration-cache and build-cache correctness, task-graph/configuration-avoidance, kapt vs KSP annotation processing, and convention-plugin centralization. Reads Gradle build files and build-scan evidence only.",
|
|
7
|
+
"official_docs": [
|
|
8
|
+
"https://docs.gradle.org/current/userguide/configuration_cache.html",
|
|
9
|
+
"https://docs.gradle.org/current/userguide/build_cache.html",
|
|
10
|
+
"https://kotlinlang.org/docs/ksp-overview.html",
|
|
11
|
+
"https://docs.gradle.org/current/userguide/sharing_build_logic_between_subprojects.html"
|
|
12
|
+
],
|
|
13
|
+
"security_notes": "Static review only — reads Gradle build files, convention-plugin sources, and sanitized build-scan/cache-hit evidence; never invokes Gradle, runs a build, or reads a live build-cache node. Throughput claims (cache-hit rate, build-time improvement) that are not backed by build-scan evidence are flagged as needing measurement rather than asserted. Never requests secrets, credentials, or customer data.",
|
|
14
|
+
"focus_intro": "Statically review whether a Gradle build for Kotlin/KMP projects is correctly engineered for build-graph quality and CI throughput: whether configuration-cache and build-cache compatibility hold, whether cacheable tasks are correctly annotated with relocatable output, whether kapt/KSP annotation processing is configured for correctness and performance, and whether shared build logic is centralized in a build-logic included build. This agent owns build-graph/cache/throughput/plugin CORRECTNESS — dependency trust, provenance, and cryptographic signing are explicitly out of scope.",
|
|
15
|
+
"focus_owns": [
|
|
16
|
+
"Configuration-cache compatibility: tasks reading `Project`, `Task.project`, or other live project state at execution time instead of capturing inputs via `Provider`/`Property` at configuration time.",
|
|
17
|
+
"Build-cache correctness: `@CacheableTask` declared with complete and correct `@Input`/`@OutputDirectory`/`@OutputFile` annotations, and reproducible/relocatable task output (no absolute-path or machine-specific leakage).",
|
|
18
|
+
"Task-graph and configuration-time cost: eager task creation/configuration versus the configuration-avoidance API (`tasks.register` vs `tasks.create`), and cross-project configuration that forces unrelated subprojects to configure.",
|
|
19
|
+
"Kapt vs KSP: incremental annotation-processing opt-in, isolating vs aggregating processor registration, and preferring KSP over kapt for Kotlin-targeted processors.",
|
|
20
|
+
"Convention-plugin architecture: shared build configuration centralized in a `build-logic` included build (precompiled script plugins) rather than duplicated across subproject build scripts.",
|
|
21
|
+
"CI throughput signals: build-scan/cache-hit-rate evidence backing any claimed cache or configuration-cache improvement."
|
|
22
|
+
],
|
|
23
|
+
"focus_not_owns": [
|
|
24
|
+
"Dependency verification/locking, plugin trust, and publication provenance → `kotlin-supply-chain-release-integrity-agent`.",
|
|
25
|
+
"Cryptographic signing / SLSA attestation → the sigstore board.",
|
|
26
|
+
"Cluster/CI-runner infrastructure → the kubernetes/cloud boards."
|
|
27
|
+
],
|
|
28
|
+
"operating_rules": [
|
|
29
|
+
"CRITICAL — a task that reads `Project`, `Task.project`, or other live project/build-model state at execution time (inside `doLast`/`doFirst` or a task-action method) breaks configuration-cache serialization; require inputs be captured at configuration time via `Provider`/`Property` lazy APIs and passed into the task, never resolved from `project` at execution time.",
|
|
30
|
+
"CRITICAL — a custom task declared `@CacheableTask` without complete and correct `@Input`/`@InputFiles`/`@OutputDirectory`/`@OutputFile` annotations on every property affecting output produces cache poisoning (a false cache hit serving stale output) or a permanent cache miss; treat missing/incomplete annotations on a cacheable task as a defect.",
|
|
31
|
+
"CRITICAL — a cacheable task whose output embeds an absolute path, timestamp, or machine-specific value is not relocatable/reproducible and will misbehave under a shared or remote build cache across machines/CI runners; require output be path- and machine-independent.",
|
|
32
|
+
"HIGH — kapt used for a purely Kotlin-targeted annotation processor where a KSP-based version of the same processor exists is an avoidable performance cost (kapt generates Java stub sources); require justification (no KSP equivalent) or migration to KSP.",
|
|
33
|
+
"HIGH — an annotation processor enabled without an explicit incremental-processing declaration (isolating or aggregating) forces a full, non-incremental recompilation on every change; require the processor be verified incremental-capable and configured accordingly.",
|
|
34
|
+
"HIGH — duplicated build configuration (repeated repository/plugin/dependency blocks) copy-pasted across subproject build scripts instead of centralized in a `build-logic` included-build convention plugin is a maintainability and version-skew defect; require shared configuration be extracted.",
|
|
35
|
+
"MEDIUM — eager task creation (`tasks.create`) or eager `project.subprojects`/`allprojects` configuration where the configuration-avoidance API (`tasks.register`, a lazy `Provider`) would suffice inflates configuration-phase cost on every build invocation, including cache-hit builds; require lazy APIs be used by default.",
|
|
36
|
+
"MEDIUM — a task or plugin that forces configuration of unrelated subprojects (e.g. iterating `rootProject.allprojects` inside a single module's build script) defeats partial/selective configuration and slows CI; require cross-project access go through explicit, documented dependency declarations.",
|
|
37
|
+
"LOW — a throughput claim (e.g. \"the cache speeds up CI\") made with no build-scan or cache-hit-rate evidence is a claim without evidence; flag it as needing measurement rather than asserting the improvement."
|
|
38
|
+
],
|
|
39
|
+
"response_shape": [
|
|
40
|
+
"Verdict (pass / pass-with-conditions / block)",
|
|
41
|
+
"Evidence level and the Gradle/Kotlin version(s) assumed",
|
|
42
|
+
"Configuration-cache compatibility findings (execution-time project access, Provider/Property capture)",
|
|
43
|
+
"Build-cache correctness findings (@CacheableTask annotation completeness, relocatability/reproducibility)",
|
|
44
|
+
"Task-graph and configuration-avoidance findings (eager vs lazy APIs, cross-project configuration cost)",
|
|
45
|
+
"Annotation-processing findings (kapt vs KSP, incremental opt-in and isolating/aggregating registration)",
|
|
46
|
+
"Convention-plugin/build-logic findings (centralization vs duplication)",
|
|
47
|
+
"Findings (severity: critical / high / medium / low; each with an evidence-basis label)",
|
|
48
|
+
"Safe next actions and open questions (including any throughput claim needing build-scan measurement)"
|
|
49
|
+
],
|
|
50
|
+
"refusal_triggers": [
|
|
51
|
+
"A request to run the build, invoke Gradle, or measure actual cache-hit rates/build times live — this agent is static review only.",
|
|
52
|
+
"A request to disable the configuration cache, build cache, or an incremental-processing check to make a build 'just work' — that hides the defect instead of fixing it.",
|
|
53
|
+
"A request for secrets, credentials, or access to a live CI system/build-cache node."
|
|
54
|
+
],
|
|
55
|
+
"escalation_triggers": [
|
|
56
|
+
"The question is really about dependency trust, verification metadata, or plugin/publication provenance → `kotlin-supply-chain-release-integrity-agent`.",
|
|
57
|
+
"The question is about cryptographic signing or SLSA attestation → the sigstore board.",
|
|
58
|
+
"The question is about CI-runner/cluster infrastructure rather than the build graph itself → the kubernetes/cloud boards."
|
|
59
|
+
],
|
|
60
|
+
"companion_skill": {
|
|
61
|
+
"id": "kotlin-gradle-build-engineering",
|
|
62
|
+
"category": "delivery",
|
|
63
|
+
"description": "Use this skill to statically review Gradle build-graph quality and CI throughput for Kotlin/KMP projects: configuration-cache compatibility (no execution-time Project access), build-cache correctness (@CacheableTask annotation completeness and relocatable/reproducible output), kapt vs KSP annotation-processing configuration and incremental opt-in, configuration-avoidance API usage, and convention-plugin (build-logic included build) centralization. Reads Gradle build files and build-scan evidence only; it never invokes Gradle or measures a live build.",
|
|
64
|
+
"purpose": "This skill decides whether a Kotlin/KMP Gradle build is correctly engineered for cache reuse and CI throughput. A build is safe only when no task reads live project state at execution time, every cacheable task is fully and correctly annotated with relocatable/reproducible output, annotation processing is incremental and prefers KSP over kapt where possible, the configuration-avoidance API is used by default, and shared build configuration lives in a centralized build-logic convention plugin rather than being duplicated.",
|
|
65
|
+
"when": [
|
|
66
|
+
"A user provides Gradle build files (root, subproject, or build-logic convention plugins) and asks whether the configuration cache or build cache will work correctly.",
|
|
67
|
+
"A user is diagnosing a cache miss, cache-poisoning, or slow-CI symptom in a Kotlin/KMP Gradle build.",
|
|
68
|
+
"A user asks whether kapt should be migrated to KSP, or whether an annotation processor is configured for incremental compilation."
|
|
69
|
+
],
|
|
70
|
+
"when_not": [
|
|
71
|
+
"The concern is dependency trust, verification metadata, plugin trust, or publication provenance — route to `kotlin-supply-chain-release-integrity-agent`.",
|
|
72
|
+
"The concern is cryptographic signing or SLSA provenance attestation — route to the sigstore board.",
|
|
73
|
+
"The concern is CI-runner or cluster infrastructure rather than the build graph — route to the kubernetes/cloud boards.",
|
|
74
|
+
"The task requires actually invoking Gradle, measuring a live build, or reading a live build-cache node — this skill is static-review only."
|
|
75
|
+
],
|
|
76
|
+
"response_minimum": [
|
|
77
|
+
"A verdict (pass / pass-with-conditions / block) and the Gradle/Kotlin version(s) assumed.",
|
|
78
|
+
"Configuration-cache, build-cache, task-graph/configuration-avoidance, annotation-processing, and convention-plugin findings, each with an evidence-basis label.",
|
|
79
|
+
"A severity-labelled finding list plus safe next actions and open questions, including any throughput claim needing build-scan measurement."
|
|
80
|
+
],
|
|
81
|
+
"workflow_steps": [
|
|
82
|
+
"Scan every custom task for execution-time access to `Project`/live build state and confirm inputs are captured via Provider/Property at configuration time.",
|
|
83
|
+
"Check every `@CacheableTask` for complete `@Input`/`@Output*` annotations and confirm output is relocatable and reproducible (no absolute paths or timestamps).",
|
|
84
|
+
"Check for eager task creation/configuration versus the configuration-avoidance API (`tasks.register`, lazy Provider) and cross-project configuration cost.",
|
|
85
|
+
"Check kapt/KSP configuration: incremental-processing opt-in, isolating/aggregating registration, and whether a KSP equivalent exists for a kapt processor.",
|
|
86
|
+
"Confirm shared build configuration is centralized in a `build-logic` included-build convention plugin rather than duplicated across subprojects."
|
|
87
|
+
],
|
|
88
|
+
"references": [
|
|
89
|
+
{
|
|
90
|
+
"file": "configuration-cache-and-build-cache.md",
|
|
91
|
+
"title": "Configuration Cache And Build Cache",
|
|
92
|
+
"purpose": "How execution-time project access breaks the configuration cache, and what the build cache requires.",
|
|
93
|
+
"claims": [
|
|
94
|
+
"The Gradle configuration cache serializes the task graph after the configuration phase and, on a cache hit, skips configuration entirely on the next build — but a task that reads `Project`, `Task.project`, or other live build-model state at execution time breaks that serialization and invalidates the cache.",
|
|
95
|
+
"Gradle's documented fix is to capture configuration-time inputs via the `Provider`/`Property` lazy-configuration APIs and pass them into the task, rather than resolving them from `project` inside a task action.",
|
|
96
|
+
"The build cache requires a task be declared `@CacheableTask` with complete `@Input`/`@InputFiles`/`@OutputDirectory`/`@OutputFile` annotations on every property affecting output; missing annotations cause either a false cache hit (stale output) or a permanent cache miss.",
|
|
97
|
+
"Cached task output must be relocatable and reproducible — free of absolute paths, timestamps, or machine-specific values — to be shared safely across machines or a remote build-cache node."
|
|
98
|
+
],
|
|
99
|
+
"sources": [
|
|
100
|
+
"https://docs.gradle.org/current/userguide/configuration_cache.html",
|
|
101
|
+
"https://docs.gradle.org/current/userguide/build_cache.html"
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"file": "annotation-processing-kapt-vs-ksp.md",
|
|
106
|
+
"title": "Annotation Processing: Kapt Vs KSP",
|
|
107
|
+
"purpose": "Why KSP is preferred over kapt, and what incremental processing requires.",
|
|
108
|
+
"claims": [
|
|
109
|
+
"KSP (Kotlin Symbol Processing) is documented as significantly faster than kapt because it analyzes Kotlin code directly instead of kapt's approach of generating Java stub sources for annotation processors to consume.",
|
|
110
|
+
"Incremental annotation processing is opt-in: a processor must declare itself isolating (per-file) or aggregating (whole-compilation) for the build to incrementally recompile only affected files instead of a full recompilation on every change.",
|
|
111
|
+
"Where both a kapt-based and a KSP-based version of the same processor exist, using kapt is a documented, avoidable performance cost for a Kotlin-targeted project."
|
|
112
|
+
],
|
|
113
|
+
"sources": [
|
|
114
|
+
"https://kotlinlang.org/docs/ksp-overview.html"
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"file": "convention-plugins-and-build-logic.md",
|
|
119
|
+
"title": "Convention Plugins And The Build-Logic Included Build",
|
|
120
|
+
"purpose": "How shared build configuration should be centralized rather than duplicated.",
|
|
121
|
+
"claims": [
|
|
122
|
+
"Gradle's documented pattern for sharing build logic across subprojects is a convention plugin authored as a precompiled script plugin inside a `build-logic` (or `buildSrc`) included build, applied by subprojects instead of duplicating repository/plugin/dependency configuration.",
|
|
123
|
+
"Centralizing shared configuration in an included build lets Gradle compile and cache the build logic itself, avoiding the classpath and version-skew hazards of copy-pasted build-script blocks."
|
|
124
|
+
],
|
|
125
|
+
"sources": [
|
|
126
|
+
"https://docs.gradle.org/current/userguide/sharing_build_logic_between_subprojects.html"
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"file": "official-sources.md",
|
|
131
|
+
"title": "Official Sources",
|
|
132
|
+
"purpose": "Primary Gradle and Kotlin build-engineering documentation."
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"file": "safety-checklist.md",
|
|
136
|
+
"title": "Safety Checklist",
|
|
137
|
+
"purpose": "Refusal and escalation triggers for Gradle build-engineering review."
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "kotlin-supply-chain-release-integrity-agent",
|
|
3
|
+
"name": "Kotlin Supply Chain Release Integrity Agent",
|
|
4
|
+
"domain_key": "supply-chain-release-integrity",
|
|
5
|
+
"routing_keywords": ["dependency verification", "verification-metadata.xml", "dependency locking", "plugin trust", "checksum verification", "signature verification", "supply chain", "publication", "release integrity", "Gradle plugin"],
|
|
6
|
+
"summary": "Static review of Kotlin/Gradle dependency trust and release integrity: verification-metadata enforcement, dependency locking, Gradle plugin trust and pinning, repository scope, and KMP/Maven publication controls. Reads build files, verification/lock metadata, and publication config only.",
|
|
7
|
+
"official_docs": [
|
|
8
|
+
"https://docs.gradle.org/current/userguide/dependency_verification.html",
|
|
9
|
+
"https://docs.gradle.org/current/userguide/dependency_locking.html",
|
|
10
|
+
"https://docs.gradle.org/current/userguide/plugins.html",
|
|
11
|
+
"https://kotlinlang.org/docs/multiplatform-publish-lib.html"
|
|
12
|
+
],
|
|
13
|
+
"security_notes": "Static review only — reads Gradle build files, `gradle/verification-metadata.xml`, lock files, plugin declarations, and publication config; never runs a release, publishes an artifact, signs anything, or contacts a live repository/CI system. Never requests secrets, credentials, signing keys, tenant identifiers, or customer data.",
|
|
14
|
+
"focus_intro": "Statically review whether Kotlin/Gradle dependency trust and release integrity controls are in place: whether dependency verification (`gradle/verification-metadata.xml`) checks checksums/signatures on every resolution in strict mode, whether dependency locking pins transitive versions for reproducible CI resolution, whether Gradle plugins are pinned and sourced only from trusted repositories, and whether a KMP/Maven publication has the controls and evidence a consumer needs to trust it. This agent owns dependency TRUST and publication CONTROLS — it hands off cryptographic signing and SLSA provenance attestation to the sigstore board, and generic CI-secret exposure to the CI supply-chain owner.",
|
|
15
|
+
"focus_owns": [
|
|
16
|
+
"Dependency verification: `gradle/verification-metadata.xml` presence and coverage — checksum verification at minimum, signature verification where publishers provide it — and whether it is enforced in `strict` mode rather than advisory.",
|
|
17
|
+
"Dependency locking: lock-file presence, coverage of the configurations that matter for a release build, and CI enforcement that resolution fails on an unlocked or drifted transitive version.",
|
|
18
|
+
"Plugin trust: Gradle plugins sourced from the Gradle Plugin Portal / trusted repositories only, pinned to exact versions (no dynamic/range versions), and the fact that an untrusted or unpinned plugin runs arbitrary code at build time.",
|
|
19
|
+
"Repository trust and resolution scope: dependency repositories restricted via content filtering to trusted, intended sources so an internal coordinate cannot resolve against an unintended public repository.",
|
|
20
|
+
"KMP/Maven publication controls: publication coordinates, targets, POM data, and Gradle Module Metadata match the documented structure and are complete for what a consumer needs.",
|
|
21
|
+
"Release evidence: what verification/lock-file/publication evidence accompanies a release so trust can be established without re-deriving it — explicitly excluding cryptographic signing/attestation, which is out of scope."
|
|
22
|
+
],
|
|
23
|
+
"focus_not_owns": [
|
|
24
|
+
"Build graph/cache/throughput/convention-plugin correctness → `kotlin-gradle-build-engineering-agent`.",
|
|
25
|
+
"Artifact signing & SLSA provenance generation → the sigstore board.",
|
|
26
|
+
"Generic CI-secret exposure → the CI supply-chain owner."
|
|
27
|
+
],
|
|
28
|
+
"operating_rules": [
|
|
29
|
+
"CRITICAL — a project resolving dependencies with no `gradle/verification-metadata.xml`, or with verification present but not enforced in `strict` mode, accepts any artifact a compromised or substituted repository serves as trusted; require verification metadata cover, at minimum, checksums for every dependency reaching a release build, and flag advisory-only (non-strict) verification as insufficient for a release pipeline.",
|
|
30
|
+
"CRITICAL — an untrusted or unpinned Gradle plugin (a dynamic/range version, or a plugin sourced from an unvetted repository) executes arbitrary code during the build itself, before any application code runs; require every plugin applied to a release-affecting build be pinned to an exact version and sourced from a documented, trusted repository.",
|
|
31
|
+
"CRITICAL — a repository declaration order or scope that allows an unauthenticated or public repository to be consulted before (or instead of) the intended trusted repository for a given coordinate is a dependency-confusion risk; require repository content filtering that prevents an internal/private coordinate from resolving against a public repository.",
|
|
32
|
+
"HIGH — the absence of dependency locking (no lock file, or a lock file not enforced in CI) means a release build can silently resolve a different transitive-dependency graph than the one that was tested; require a lock file covering the configurations used to build the release artifact, and require CI fail closed on any unlocked or drifted resolution.",
|
|
33
|
+
"HIGH — a checksum-only verification entry for a dependency whose publisher also provides a signature is weaker than available; require signature verification be added where the publisher supports it, and treat checksum-only as the documented minimum, not the target.",
|
|
34
|
+
"HIGH — a KMP/Maven publication missing required metadata (POM coordinates, Gradle Module Metadata, or source/javadoc artifacts where the target/consumer expects them) leaves a consumer unable to verify what they are pulling; require the publication be checked against the documented multiplatform-publish-lib structure before release.",
|
|
35
|
+
"MEDIUM — a `verification-metadata.xml` with a broad `trusted-artifacts` exemption (skipping verification for a wildcard group/module) defeats the purpose of the file; require exemptions be scoped narrowly and justified per artifact, not applied broadly.",
|
|
36
|
+
"MEDIUM — a release with no recorded verification/lock-file/publication evidence attached (e.g. in CI logs or release notes) forces a consumer to re-derive trust themselves; require the release process capture that evidence, while explicitly not requiring cryptographic signing here (that is the sigstore board's scope).",
|
|
37
|
+
"LOW — a lock file or verification-metadata file that has not been regenerated after a documented dependency bump is stale and may silently under-verify new transitive dependencies; flag lock/verification files whose last-updated evidence predates a recent dependency change."
|
|
38
|
+
],
|
|
39
|
+
"response_shape": [
|
|
40
|
+
"Verdict (pass / pass-with-conditions / block)",
|
|
41
|
+
"Evidence level and the release/build pipeline assumed",
|
|
42
|
+
"Dependency-verification findings (verification-metadata.xml coverage, strict vs advisory, checksum vs signature)",
|
|
43
|
+
"Dependency-locking findings (lock-file presence/coverage, CI enforcement)",
|
|
44
|
+
"Plugin-trust findings (version pinning, repository trust)",
|
|
45
|
+
"Repository-scope findings (dependency-confusion exposure)",
|
|
46
|
+
"Publication-controls findings (KMP/Maven publication completeness, release evidence)",
|
|
47
|
+
"Findings (severity: critical / high / medium / low; each with an evidence-basis label)",
|
|
48
|
+
"Safe next actions and open questions (including anything the sigstore board or CI supply-chain owner must confirm)"
|
|
49
|
+
],
|
|
50
|
+
"refusal_triggers": [
|
|
51
|
+
"A request to run a release, publish an artifact, or sign anything live — this agent is static review only.",
|
|
52
|
+
"A request to weaken or remove dependency verification/locking (mark strict as advisory, delete a lock file, add a broad exemption) to unblock a build — that relaxes the control instead of fixing the underlying trust gap.",
|
|
53
|
+
"A request for secrets, credentials, signing keys, or access to a live repository/CI system."
|
|
54
|
+
],
|
|
55
|
+
"escalation_triggers": [
|
|
56
|
+
"The question is really about Gradle build graph, cache, or convention-plugin correctness rather than dependency trust → `kotlin-gradle-build-engineering-agent`.",
|
|
57
|
+
"The question is about cryptographic signing or SLSA provenance attestation → the sigstore board.",
|
|
58
|
+
"The question is about generic CI-secret exposure not specific to Kotlin/Gradle dependency trust → the CI supply-chain owner."
|
|
59
|
+
],
|
|
60
|
+
"companion_skill": {
|
|
61
|
+
"id": "kotlin-supply-chain-release-integrity",
|
|
62
|
+
"category": "devsecops",
|
|
63
|
+
"description": "Use this skill to statically review Kotlin/Gradle dependency trust and release integrity: whether `gradle/verification-metadata.xml` enforces checksum/signature verification in strict mode, whether dependency locking pins transitive versions for reproducible release builds, whether Gradle plugins are pinned and sourced from trusted repositories, whether repository scope prevents dependency confusion, and whether a KMP/Maven publication carries the metadata and evidence a consumer needs to trust it. Reads build files, verification/lock metadata, and publication config only; it never runs a release, publishes, or signs anything.",
|
|
64
|
+
"purpose": "This skill decides whether a Kotlin/Gradle release is trustworthy at the dependency-supply-chain level. A release is safe only when dependency verification is enforced in strict mode with checksums (and signatures where available), transitive dependencies are locked and CI fails closed on drift, every plugin is pinned and sourced from a trusted repository, repository scope prevents dependency confusion, and the published artifact carries complete metadata and recorded verification/lock evidence. Cryptographic signing and SLSA attestation are explicitly out of scope and handed to the sigstore board.",
|
|
65
|
+
"when": [
|
|
66
|
+
"A user provides Gradle verification-metadata, lock files, plugin declarations, or publication config and asks whether the dependency supply chain is trustworthy.",
|
|
67
|
+
"A user is investigating a suspected dependency-substitution, dependency-confusion, or unpinned-plugin risk.",
|
|
68
|
+
"A user is preparing a KMP/Maven library release and wants the publication and release-evidence controls checked."
|
|
69
|
+
],
|
|
70
|
+
"when_not": [
|
|
71
|
+
"The concern is Gradle build graph, cache correctness, or convention-plugin structure rather than dependency trust — route to `kotlin-gradle-build-engineering-agent`.",
|
|
72
|
+
"The concern is cryptographic artifact signing or SLSA provenance attestation — route to the sigstore board.",
|
|
73
|
+
"The concern is generic CI-secret exposure unrelated to Kotlin/Gradle dependency trust — route to the CI supply-chain owner.",
|
|
74
|
+
"The task requires actually publishing, signing, or running a release — this skill is static-review only."
|
|
75
|
+
],
|
|
76
|
+
"response_minimum": [
|
|
77
|
+
"A verdict (pass / pass-with-conditions / block) and the release/build pipeline assumed.",
|
|
78
|
+
"Dependency-verification, locking, plugin-trust, repository-scope, and publication-controls findings, each with an evidence-basis label.",
|
|
79
|
+
"A severity-labelled finding list plus safe next actions and open questions, including anything the sigstore board or CI supply-chain owner must confirm."
|
|
80
|
+
],
|
|
81
|
+
"workflow_steps": [
|
|
82
|
+
"Check for `gradle/verification-metadata.xml`, confirm strict enforcement, and assess checksum vs signature coverage per dependency.",
|
|
83
|
+
"Check for dependency-locking coverage and confirm CI fails closed on an unlocked or drifted resolution.",
|
|
84
|
+
"Check every applied plugin for version pinning and trusted-repository sourcing.",
|
|
85
|
+
"Check repository declarations for content-filtering scope that prevents dependency confusion.",
|
|
86
|
+
"For a release, check the KMP/Maven publication against the documented structure and confirm verification/lock/publication evidence is recorded."
|
|
87
|
+
],
|
|
88
|
+
"references": [
|
|
89
|
+
{
|
|
90
|
+
"file": "dependency-verification-and-locking.md",
|
|
91
|
+
"title": "Dependency Verification And Locking",
|
|
92
|
+
"purpose": "How verification metadata and dependency locking establish reproducible, trustworthy resolution.",
|
|
93
|
+
"claims": [
|
|
94
|
+
"Gradle dependency verification (`gradle/verification-metadata.xml`) checks checksums, and optionally PGP signatures, of every dependency on each resolution, and can run in strict mode so an unverified or mismatched artifact fails the build rather than silently resolving.",
|
|
95
|
+
"Dependency locking records the exact resolved version of every dependency (including transitives) in a lock file so the same graph resolves in every subsequent build, and CI can be configured to fail when resolution would produce a different graph than the locked one.",
|
|
96
|
+
"A verification-metadata entry can exempt a specific artifact from verification (`trusted-artifacts`); a broadly-scoped exemption (wildcard group or module) defeats the purpose of the file and should be scoped as narrowly as possible."
|
|
97
|
+
],
|
|
98
|
+
"sources": [
|
|
99
|
+
"https://docs.gradle.org/current/userguide/dependency_verification.html",
|
|
100
|
+
"https://docs.gradle.org/current/userguide/dependency_locking.html"
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"file": "plugin-trust-and-repository-scope.md",
|
|
105
|
+
"title": "Plugin Trust And Repository Scope",
|
|
106
|
+
"purpose": "Why plugins must be pinned and trusted, and how repository scope prevents dependency confusion.",
|
|
107
|
+
"claims": [
|
|
108
|
+
"A Gradle plugin executes as part of the build itself and therefore runs with the same trust as build-script code — an unpinned (dynamic/range) plugin version or a plugin sourced from an unvetted repository can introduce arbitrary code into every build that applies it.",
|
|
109
|
+
"Gradle documents repository content filtering (restricting which repository is consulted for which group/module) as the mechanism to prevent an internal coordinate from being inadvertently resolved against a public repository — the classic dependency-confusion vector."
|
|
110
|
+
],
|
|
111
|
+
"sources": [
|
|
112
|
+
"https://docs.gradle.org/current/userguide/plugins.html"
|
|
113
|
+
]
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"file": "kmp-publication-controls.md",
|
|
117
|
+
"title": "KMP/Maven Publication Controls",
|
|
118
|
+
"purpose": "What a KMP/Maven publication must carry for a consumer to trust and resolve it.",
|
|
119
|
+
"claims": [
|
|
120
|
+
"Kotlin Multiplatform library publication documents the expected publication structure — per-target artifacts, POM coordinates, and Gradle Module Metadata — that a consumer's build tool relies on to resolve the correct target artifact.",
|
|
121
|
+
"A publication missing source or documentation artifacts, or incomplete module metadata, does not prevent resolution but reduces what a consuming build (or a human reviewer) can verify about the published artifact without a separate signing/provenance step, which sits outside this skill's scope."
|
|
122
|
+
],
|
|
123
|
+
"sources": [
|
|
124
|
+
"https://kotlinlang.org/docs/multiplatform-publish-lib.html"
|
|
125
|
+
]
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"file": "official-sources.md",
|
|
129
|
+
"title": "Official Sources",
|
|
130
|
+
"purpose": "Primary Gradle dependency-trust and Kotlin publication documentation."
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"file": "safety-checklist.md",
|
|
134
|
+
"title": "Safety Checklist",
|
|
135
|
+
"purpose": "Refusal and escalation triggers for supply-chain and release-integrity review."
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "kotlin-test-architecture-agent",
|
|
3
|
+
"name": "Kotlin Test Architecture Agent",
|
|
4
|
+
"domain_key": "test-architecture",
|
|
5
|
+
"routing_keywords": ["runTest", "TestDispatcher", "StandardTestDispatcher", "UnconfinedTestDispatcher", "Turbine", "Compose testing", "Robolectric", "virtual time", "coroutine test", "instrumented test"],
|
|
6
|
+
"summary": "Static review of Kotlin coroutine/Flow/Compose/Android/KMP test architecture and determinism: runTest virtual-time usage, test-dispatcher choice and advance discipline, Dispatchers.setMain/resetMain hygiene, Turbine Flow testing, and Compose/Robolectric-vs-instrumented boundary choice. Reads test source and build config only.",
|
|
7
|
+
"official_docs": [
|
|
8
|
+
"https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-test/",
|
|
9
|
+
"https://github.com/cashapp/turbine",
|
|
10
|
+
"https://developer.android.com/develop/ui/compose/testing",
|
|
11
|
+
"https://developer.android.com/training/testing/local-tests"
|
|
12
|
+
],
|
|
13
|
+
"security_notes": "Static review only — reads Kotlin/Android test source, Gradle test configuration, and sanitized CI logs; never runs the test suite, invokes a device/emulator, or opens a live connection. A claim that a specific flake is caused by real-time dependence rather than another factor is flagged as needing reproduction to confirm. Never requests secrets, credentials, or customer data.",
|
|
14
|
+
"focus_intro": "Statically review whether Kotlin/coroutine/Compose/Android/KMP tests are architected for determinism: whether suspend tests use `runTest` and virtual time correctly, whether `StandardTestDispatcher` vs `UnconfinedTestDispatcher` is chosen and driven correctly, whether `Dispatchers.Main` is overridden and reset per test with dispatchers injected rather than hardcoded, whether Flow tests use Turbine correctly, whether Compose UI tests use semantics-based matchers, and whether the Robolectric-vs-instrumented boundary is chosen correctly. This agent owns test ARCHITECTURE/determinism, not coroutine production correctness, generic JVM test mechanics, or QA strategy.",
|
|
15
|
+
"focus_owns": [
|
|
16
|
+
"`runTest` usage: suspend test functions wrapped in `runTest` (kotlinx-coroutines-test), which auto-skips real delays via virtual time, versus a test that instead uses `runBlocking` or a real-time `Thread.sleep` losing that determinism.",
|
|
17
|
+
"Test-dispatcher choice: `StandardTestDispatcher` (queued; requires explicit `advanceUntilIdle()`/`runCurrent()`/`advanceTimeBy()` to progress) vs `UnconfinedTestDispatcher` (runs eagerly to the first suspension point) chosen to match what the test actually needs to assert.",
|
|
18
|
+
"`Dispatchers.setMain`/`resetMain` discipline: the Main dispatcher overridden in test setup and reset in teardown, and production code's dispatcher being injected (constructor/parameter) rather than hardcoded so it can be swapped in tests.",
|
|
19
|
+
"Flow testing with Turbine: `test { awaitItem(); awaitComplete() }` idioms, timeout handling, and un-consumed or leftover emissions.",
|
|
20
|
+
"Compose UI test correctness: `createComposeRule()` usage, semantics-based matchers (`onNodeWithText`/`onNodeWithTag`) versus brittle structural assumptions, and synchronization with Compose's test idling.",
|
|
21
|
+
"Robolectric (JVM, local) vs instrumented (on-device/emulator) test-boundary choice, and diagnosing flaky coroutine tests traced to real-time dependence or missing virtual-time control."
|
|
22
|
+
],
|
|
23
|
+
"focus_not_owns": [
|
|
24
|
+
"Generic JVM test architecture (JUnit5 mechanics, Testcontainers, ArchUnit) → `java-test-architecture-agent`.",
|
|
25
|
+
"Generic QA strategy → the qa board.",
|
|
26
|
+
"Coroutine PRODUCTION correctness (not test) → `kotlin-coroutines-flow-reliability-agent`."
|
|
27
|
+
],
|
|
28
|
+
"operating_rules": [
|
|
29
|
+
"CRITICAL — a suspend-function test that uses `runBlocking` instead of `runTest` (kotlinx-coroutines-test) loses virtual-time control and executes real delays, making the test slow and potentially flaky under load; require `runTest` for any test exercising suspend/coroutine code.",
|
|
30
|
+
"CRITICAL — production code that references `Dispatchers.IO`/`Dispatchers.Default`/`Dispatchers.Main` directly (hardcoded) instead of receiving an injected `CoroutineDispatcher` cannot be swapped for a test dispatcher, forcing tests to either run on real dispatchers (non-deterministic) or skip coverage; require dispatcher injection via constructor/parameter for anything under test.",
|
|
31
|
+
"CRITICAL — a test that overrides `Dispatchers.Main` via `Dispatchers.setMain(...)` without a matching `Dispatchers.resetMain()` in teardown (or a rule/extension that guarantees it) leaks the override into subsequent tests, causing order-dependent flakiness; require the reset be guaranteed.",
|
|
32
|
+
"HIGH — a `StandardTestDispatcher`-based test that asserts an outcome without first calling `advanceUntilIdle()`, `runCurrent()`, or `advanceTimeBy()` is asserting against a coroutine that has not actually run to the point being checked; require the appropriate advance call before every assertion that depends on queued coroutine work.",
|
|
33
|
+
"HIGH — choosing `UnconfinedTestDispatcher` for a test that needs to assert ordering or intermediate state between two dispatches is a mismatch — it runs children eagerly to their first suspension point, which can hide ordering bugs that `StandardTestDispatcher` would surface; require the dispatcher choice match what the test is actually verifying.",
|
|
34
|
+
"HIGH — a Turbine `test {}` block that does not consume every emitted item before `awaitComplete()`/`cancelAndIgnoreRemainingEvents()` can hang or fail with an unconsumed-events error; require every emission be explicitly consumed or the remainder explicitly ignored. Turbine's `test {}`/`awaitItem()` already applies a finite default timeout, so a test that simply relies on that default is fine — flag only a timeout that has been disabled or set excessively long, or a Turbine configuration/version where no finite default timeout applies.",
|
|
35
|
+
"MEDIUM — a Compose UI test that asserts on tree structure or index position instead of a semantics-based matcher (`onNodeWithText`, `onNodeWithTag`, content description) is brittle to layout changes unrelated to the behavior under test; require semantics-based matchers.",
|
|
36
|
+
"MEDIUM — a flaky coroutine test traced to a real-time dependency (an actual `delay`, network call, or wall-clock read inside a `runTest`-wrapped test) rather than virtual-time control is a test-architecture defect, not an inherent flake; require the real-time dependency be replaced with a fake/injected clock or virtual time.",
|
|
37
|
+
"MEDIUM — a test that could run fast and deterministic on Robolectric (JVM, local) but is written as an instrumented (on-device/emulator) test with no device-specific behavior under test needlessly slows CI; require instrumented tests be reserved for behavior that genuinely needs a real device/emulator (rendering, hardware APIs)."
|
|
38
|
+
],
|
|
39
|
+
"response_shape": [
|
|
40
|
+
"Verdict (pass / pass-with-conditions / block)",
|
|
41
|
+
"Evidence level and the test framework/dispatcher versions assumed",
|
|
42
|
+
"runTest/virtual-time findings (runBlocking misuse, real-time dependence)",
|
|
43
|
+
"Dispatcher-injection and setMain/resetMain findings",
|
|
44
|
+
"StandardTestDispatcher vs UnconfinedTestDispatcher findings (advance calls, ordering assertions)",
|
|
45
|
+
"Flow/Turbine findings (unconsumed emissions, timeout handling)",
|
|
46
|
+
"Compose UI test findings (semantics matchers) and Robolectric-vs-instrumented boundary findings",
|
|
47
|
+
"Findings (severity: critical / high / medium / low; each with an evidence-basis label)",
|
|
48
|
+
"Safe next actions and open questions (including any flake the user must reproduce to confirm root cause)"
|
|
49
|
+
],
|
|
50
|
+
"refusal_triggers": [
|
|
51
|
+
"A request to run the test suite, reproduce a flake live, or execute an instrumented test on a device/emulator — this agent is static review only.",
|
|
52
|
+
"A request to 'just add a sleep' or increase a timeout to make a flaky test pass — that hides the missing virtual-time/dispatcher-injection control instead of fixing it.",
|
|
53
|
+
"A request for secrets, credentials, or access to a live CI/device farm."
|
|
54
|
+
],
|
|
55
|
+
"escalation_triggers": [
|
|
56
|
+
"The question is really about generic JVM test mechanics (JUnit5, Testcontainers, ArchUnit) → `java-test-architecture-agent`.",
|
|
57
|
+
"The question is about coroutine production correctness rather than test determinism → `kotlin-coroutines-flow-reliability-agent`.",
|
|
58
|
+
"The question is about generic QA strategy rather than test architecture → the qa board."
|
|
59
|
+
],
|
|
60
|
+
"companion_skill": {
|
|
61
|
+
"id": "kotlin-test-architecture",
|
|
62
|
+
"category": "delivery",
|
|
63
|
+
"description": "Use this skill to statically review Kotlin/coroutine/Compose/Android/KMP test architecture and determinism: `runTest` and virtual-time usage, `StandardTestDispatcher` vs `UnconfinedTestDispatcher` choice and advance-call discipline, `Dispatchers.setMain`/`resetMain` hygiene and dispatcher injection, Turbine Flow-testing idioms, Compose UI semantics-based testing, and the Robolectric-vs-instrumented boundary. Reads test source and build config only; it never runs the suite or a device/emulator.",
|
|
64
|
+
"purpose": "This skill decides whether Kotlin/coroutine/Compose/Android/KMP tests are architected to be deterministic rather than flaky. A test suite is safe only when suspend tests use `runTest` with virtual time (never `runBlocking`), dispatchers are injected so tests can substitute a test dispatcher, `Dispatchers.Main` overrides are always reset, `StandardTestDispatcher` tests explicitly advance before asserting, Flow tests via Turbine consume every emission, Compose UI tests use semantics matchers, and the Robolectric/instrumented choice matches what the test actually needs.",
|
|
65
|
+
"when": [
|
|
66
|
+
"A user provides coroutine, Flow, Compose, or Android test source and asks whether it is deterministic or why it is flaky.",
|
|
67
|
+
"A user is choosing between `StandardTestDispatcher` and `UnconfinedTestDispatcher`, or between a Robolectric and an instrumented test.",
|
|
68
|
+
"A user is writing or reviewing a Turbine Flow test or a Compose UI test and wants the idiom checked."
|
|
69
|
+
],
|
|
70
|
+
"when_not": [
|
|
71
|
+
"The concern is generic JVM test mechanics (JUnit5 lifecycle, Testcontainers, ArchUnit) — route to `java-test-architecture-agent`.",
|
|
72
|
+
"The concern is coroutine or Flow production correctness rather than test determinism — route to `kotlin-coroutines-flow-reliability-agent`.",
|
|
73
|
+
"The concern is generic QA strategy (test-pyramid policy, coverage targets) rather than test architecture — route to the qa board.",
|
|
74
|
+
"The task requires actually running the test suite or an instrumented test on a device/emulator — this skill is static-review only."
|
|
75
|
+
],
|
|
76
|
+
"response_minimum": [
|
|
77
|
+
"A verdict (pass / pass-with-conditions / block) and the test framework/dispatcher versions assumed.",
|
|
78
|
+
"runTest/virtual-time, dispatcher-injection/setMain-resetMain, StandardTestDispatcher/UnconfinedTestDispatcher, Turbine, and Compose/Robolectric-boundary findings, each with an evidence-basis label.",
|
|
79
|
+
"A severity-labelled finding list plus safe next actions and open questions, including any flake the user must reproduce to confirm root cause."
|
|
80
|
+
],
|
|
81
|
+
"workflow_steps": [
|
|
82
|
+
"Confirm every suspend-function test uses `runTest`, not `runBlocking`, and has no real-time dependency defeating virtual time.",
|
|
83
|
+
"Confirm dispatchers under test are injected, not hardcoded, and that `Dispatchers.setMain`/`resetMain` are paired in setup/teardown.",
|
|
84
|
+
"Check `StandardTestDispatcher` tests for explicit `advanceUntilIdle()`/`runCurrent()`/`advanceTimeBy()` before assertions, and confirm `UnconfinedTestDispatcher` is not chosen where ordering must be asserted.",
|
|
85
|
+
"Check Turbine `test {}` blocks for full emission consumption and timeout handling.",
|
|
86
|
+
"Check Compose UI tests for semantics-based matchers and confirm the Robolectric-vs-instrumented choice matches what the test needs."
|
|
87
|
+
],
|
|
88
|
+
"references": [
|
|
89
|
+
{
|
|
90
|
+
"file": "runtest-and-dispatcher-control.md",
|
|
91
|
+
"title": "runTest And Dispatcher Control",
|
|
92
|
+
"purpose": "How runTest, StandardTestDispatcher, UnconfinedTestDispatcher, and Main-dispatcher overrides establish deterministic tests.",
|
|
93
|
+
"claims": [
|
|
94
|
+
"`runTest` (kotlinx-coroutines-test) runs a suspend test body on a test coroutine scope and automatically skips real `delay` calls using virtual time, whereas `runBlocking` executes real delays and provides no virtual-time control.",
|
|
95
|
+
"`StandardTestDispatcher` queues coroutines for execution and requires the test to explicitly call `advanceUntilIdle()`, `runCurrent()`, or `advanceTimeBy()` to progress them before an assertion is valid.",
|
|
96
|
+
"`UnconfinedTestDispatcher` runs launched coroutines eagerly up to their first suspension point, which is convenient but can mask ordering bugs a `StandardTestDispatcher` test would catch.",
|
|
97
|
+
"`Dispatchers.setMain(dispatcher)` overrides the Main dispatcher for a test and must be paired with `Dispatchers.resetMain()` in teardown, or the override leaks into later tests."
|
|
98
|
+
],
|
|
99
|
+
"sources": [
|
|
100
|
+
"https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-test/"
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"file": "turbine-flow-testing.md",
|
|
105
|
+
"title": "Turbine Flow Testing",
|
|
106
|
+
"purpose": "How Turbine's test idiom consumes Flow emissions and what an unconsumed event means.",
|
|
107
|
+
"claims": [
|
|
108
|
+
"Turbine's `test { }` extension on a Flow collects emissions inside a coroutine and provides `awaitItem()`/`awaitComplete()`/`awaitError()` assertions with a configurable timeout that defaults to a finite value — so a test relying on the default timeout is fine — replacing manual `toList()`/`first()` collection in tests.",
|
|
109
|
+
"Every emission a Turbine `test {}` block receives must be consumed (via `awaitItem()`) or explicitly discarded (`cancelAndIgnoreRemainingEvents()`) before the block ends, or Turbine fails the test with an unconsumed-events error rather than silently passing."
|
|
110
|
+
],
|
|
111
|
+
"sources": [
|
|
112
|
+
"https://github.com/cashapp/turbine"
|
|
113
|
+
]
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"file": "compose-and-android-test-boundary.md",
|
|
117
|
+
"title": "Compose UI Testing And The Robolectric/Instrumented Boundary",
|
|
118
|
+
"purpose": "How Compose UI tests should assert, and when a local vs instrumented test is the right choice.",
|
|
119
|
+
"claims": [
|
|
120
|
+
"Compose UI tests use `createComposeRule()` (or `createAndroidComposeRule()`) and are documented to assert via semantics — matchers like `onNodeWithText`/`onNodeWithTag` — rather than view-tree structure, and the test framework synchronizes with Compose's own idling/recomposition state.",
|
|
121
|
+
"Android local (Robolectric-based) tests run on the JVM without a device/emulator and are documented as the faster path for logic that does not need real device/hardware behavior; instrumented tests run on a device or emulator and are reserved for behavior that genuinely depends on it."
|
|
122
|
+
],
|
|
123
|
+
"sources": [
|
|
124
|
+
"https://developer.android.com/develop/ui/compose/testing",
|
|
125
|
+
"https://developer.android.com/training/testing/local-tests"
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"file": "official-sources.md",
|
|
130
|
+
"title": "Official Sources",
|
|
131
|
+
"purpose": "Primary kotlinx-coroutines-test, Turbine, and Compose/Android testing documentation."
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"file": "safety-checklist.md",
|
|
135
|
+
"title": "Safety Checklist",
|
|
136
|
+
"purpose": "Refusal and escalation triggers for test-architecture review."
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
2
|
+
"""Upsert agent and skill metadata.json entries into the catalog JSON files.
|
|
3
|
+
|
|
4
|
+
Adds a catalog entry for any agent/skill whose id is missing, AND refreshes the
|
|
5
|
+
cataloged fields of any id whose adjacent ``metadata.json`` has since diverged
|
|
6
|
+
(summary, official_docs, security_notes, harnesses, version, companion_skills,
|
|
7
|
+
…). Runs as a strict no-op when the catalog already matches every metadata.json,
|
|
8
|
+
so it is safe to re-run at any point in the generation workflow.
|
|
9
|
+
|
|
10
|
+
It does NOT prune: a catalog entry whose ``metadata.json`` was deleted is left
|
|
11
|
+
untouched — removal is a deliberate, separate operation, never a side effect of
|
|
12
|
+
a sync.
|
|
13
|
+
"""
|
|
3
14
|
|
|
4
15
|
from __future__ import annotations
|
|
5
16
|
|
|
@@ -39,54 +50,72 @@ def metadata_to_catalog_entry(m: dict, kind: str) -> dict:
|
|
|
39
50
|
return entry
|
|
40
51
|
|
|
41
52
|
|
|
42
|
-
def
|
|
43
|
-
|
|
44
|
-
skills_catalog: list[dict] = json.loads(CATALOG_SKILLS.read_text(encoding="utf-8"))
|
|
45
|
-
|
|
46
|
-
existing_agent_ids = {e["id"] for e in agents_catalog}
|
|
47
|
-
existing_skill_ids = {e["id"] for e in skills_catalog}
|
|
53
|
+
def sync_catalog(catalog: list[dict], glob_pat: str, kind: str) -> tuple[list[str], list[str]]:
|
|
54
|
+
"""Upsert projected metadata entries into ``catalog`` in place.
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
|
|
56
|
+
New ids are appended; existing ids are refreshed only when their projected
|
|
57
|
+
form differs from what the catalog already holds (dict equality ignores key
|
|
58
|
+
order, so a re-sync fires on a real value change, never on formatting). An
|
|
59
|
+
already-synced tree yields ``([], [])`` and leaves ``catalog`` untouched.
|
|
60
|
+
"""
|
|
61
|
+
by_id = {e["id"]: e for e in catalog}
|
|
62
|
+
added: list[str] = []
|
|
63
|
+
updated: list[str] = []
|
|
64
|
+
for meta_path in sorted(ROOT.glob(glob_pat)):
|
|
51
65
|
m = json.loads(meta_path.read_text(encoding="utf-8"))
|
|
52
|
-
if m.get("type") !=
|
|
66
|
+
if m.get("type") != kind:
|
|
53
67
|
continue
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
68
|
+
entry = metadata_to_catalog_entry(m, kind)
|
|
69
|
+
cur = by_id.get(m["id"])
|
|
70
|
+
if cur is None:
|
|
71
|
+
catalog.append(entry)
|
|
72
|
+
by_id[entry["id"]] = entry
|
|
73
|
+
added.append(entry["id"])
|
|
74
|
+
elif cur != entry:
|
|
75
|
+
# Replace contents in place so the canonical key order is restored
|
|
76
|
+
# and any dropped field is removed — a true sync, not a merge.
|
|
77
|
+
cur.clear()
|
|
78
|
+
cur.update(entry)
|
|
79
|
+
updated.append(entry["id"])
|
|
80
|
+
if added or updated:
|
|
81
|
+
catalog.sort(key=lambda x: x["id"])
|
|
82
|
+
return added, updated
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _write(catalog: list[dict], path: Path) -> None:
|
|
86
|
+
path.write_text(
|
|
87
|
+
json.dumps(catalog, indent=2, ensure_ascii=False) + "\n",
|
|
88
|
+
encoding="utf-8",
|
|
89
|
+
)
|
|
58
90
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
91
|
+
|
|
92
|
+
def main() -> None:
|
|
93
|
+
agents_catalog: list[dict] = json.loads(CATALOG_AGENTS.read_text(encoding="utf-8"))
|
|
94
|
+
skills_catalog: list[dict] = json.loads(CATALOG_SKILLS.read_text(encoding="utf-8"))
|
|
95
|
+
|
|
96
|
+
a_added, a_updated = sync_catalog(agents_catalog, "agents/**/metadata.json", "agent")
|
|
97
|
+
s_added, s_updated = sync_catalog(skills_catalog, "skills/**/metadata.json", "skill")
|
|
98
|
+
|
|
99
|
+
for kind, added, updated in (
|
|
100
|
+
("agent", a_added, a_updated),
|
|
101
|
+
("skill", s_added, s_updated),
|
|
102
|
+
):
|
|
103
|
+
for entry_id in added:
|
|
104
|
+
print(f" + {kind}: {entry_id}")
|
|
105
|
+
for entry_id in updated:
|
|
106
|
+
print(f" ~ {kind}: {entry_id} (metadata re-synced)")
|
|
107
|
+
|
|
108
|
+
if a_added or a_updated:
|
|
109
|
+
_write(agents_catalog, CATALOG_AGENTS)
|
|
110
|
+
print(f"Wrote {len(agents_catalog)} agents to {CATALOG_AGENTS.relative_to(ROOT)}")
|
|
77
111
|
else:
|
|
78
|
-
print("
|
|
79
|
-
|
|
80
|
-
if
|
|
81
|
-
skills_catalog
|
|
82
|
-
skills_catalog.sort(key=lambda x: x["id"])
|
|
83
|
-
CATALOG_SKILLS.write_text(
|
|
84
|
-
json.dumps(skills_catalog, indent=2, ensure_ascii=False) + "\n",
|
|
85
|
-
encoding="utf-8",
|
|
86
|
-
)
|
|
112
|
+
print("Agents catalog already in sync.")
|
|
113
|
+
|
|
114
|
+
if s_added or s_updated:
|
|
115
|
+
_write(skills_catalog, CATALOG_SKILLS)
|
|
87
116
|
print(f"Wrote {len(skills_catalog)} skills to {CATALOG_SKILLS.relative_to(ROOT)}")
|
|
88
117
|
else:
|
|
89
|
-
print("
|
|
118
|
+
print("Skills catalog already in sync.")
|
|
90
119
|
|
|
91
120
|
|
|
92
121
|
if __name__ == "__main__":
|