@1aboveio/skills 0.0.0-stage → 1.0.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/README.md +30 -2
- package/bin/cli.mjs +14 -0
- package/bin/select-core.mjs +172 -0
- package/package.json +146 -4
- package/skills/app-dev/airflow/LICENSE +3 -0
- package/skills/app-dev/airflow/SKILL.md +199 -0
- package/skills/app-dev/airflow/release-check.mjs +93 -0
- package/skills/app-dev/android-foundation/LICENSE +3 -0
- package/skills/app-dev/android-foundation/SKILL.md +192 -0
- package/skills/app-dev/android-foundation/assets/android-ci-job.yml +217 -0
- package/skills/app-dev/android-foundation/references/ci.md +87 -0
- package/skills/app-dev/android-foundation/references/gotchas.md +221 -0
- package/skills/app-dev/android-foundation/references/setup.md +164 -0
- package/skills/app-dev/android-foundation/release-check.mjs +93 -0
- package/skills/app-dev/android-foundation/scripts/device-run.sh +176 -0
- package/skills/app-dev/android-foundation/scripts/device-run.test.mjs +172 -0
- package/skills/app-dev/app-debug/LICENSE +3 -0
- package/skills/app-dev/app-debug/SKILL.md +110 -0
- package/skills/app-dev/app-debug/references/common-errors.md +128 -0
- package/skills/app-dev/app-debug/release-check.mjs +93 -0
- package/skills/app-dev/better-auth/LICENSE +3 -0
- package/skills/app-dev/better-auth/SKILL.md +598 -0
- package/skills/app-dev/better-auth/references/feishu-api.md +270 -0
- package/skills/app-dev/better-auth/release-check.mjs +93 -0
- package/skills/app-dev/data-catalog/LICENSE +3 -0
- package/skills/app-dev/data-catalog/SKILL.md +204 -0
- package/skills/app-dev/data-catalog/agents/openai.yaml +3 -0
- package/skills/app-dev/data-catalog/references/data-catalog-conventions.md +75 -0
- package/skills/app-dev/data-catalog/references/field-definitions.md +116 -0
- package/skills/app-dev/data-catalog/references/format.md +121 -0
- package/skills/app-dev/data-catalog/release-check.mjs +93 -0
- package/skills/app-dev/data-catalog/scripts/data-catalog.test.mjs +36 -0
- package/skills/app-dev/data-catalog/scripts/data_catalog.py +1392 -0
- package/skills/app-dev/data-catalog/scripts/persist-conventions-core.mjs +117 -0
- package/skills/app-dev/data-catalog/scripts/persist-conventions.mjs +17 -0
- package/skills/app-dev/data-catalog/scripts/test_data_catalog.py +571 -0
- package/skills/app-dev/ios-foundation/LICENSE +3 -0
- package/skills/app-dev/ios-foundation/SKILL.md +184 -0
- package/skills/app-dev/ios-foundation/references/setup.md +243 -0
- package/skills/app-dev/ios-foundation/release-check.mjs +93 -0
- package/skills/app-dev/monorepo/LICENSE +3 -0
- package/skills/app-dev/monorepo/SKILL.md +462 -0
- package/skills/app-dev/monorepo/release-check.mjs +93 -0
- package/skills/app-dev/nextjs-fullstack/LICENSE +3 -0
- package/skills/app-dev/nextjs-fullstack/SKILL.md +211 -0
- package/skills/app-dev/nextjs-fullstack/conventions.md +318 -0
- package/skills/app-dev/nextjs-fullstack/frontend-conventions.md +61 -0
- package/skills/app-dev/nextjs-fullstack/nextjs16.md +287 -0
- package/skills/app-dev/nextjs-fullstack/release-check.mjs +93 -0
- package/skills/app-dev/nextjs-fullstack/server-actions.md +409 -0
- package/skills/app-dev/prisma-setup/LICENSE +3 -0
- package/skills/app-dev/prisma-setup/SKILL.md +181 -0
- package/skills/app-dev/prisma-setup/nextjs.md +258 -0
- package/skills/app-dev/prisma-setup/release-check.mjs +93 -0
- package/skills/app-dev/prisma-setup/turborepo.md +301 -0
- package/skills/app-dev/pyspark/LICENSE +3 -0
- package/skills/app-dev/pyspark/SKILL.md +127 -0
- package/skills/app-dev/pyspark/assets/templates/etl.py +748 -0
- package/skills/app-dev/pyspark/assets/templates/utils/__init__.py +1 -0
- package/skills/app-dev/pyspark/assets/templates/utils/hudi_metadata.py +14 -0
- package/skills/app-dev/pyspark/references/diagnosis-and-profiling.md +169 -0
- package/skills/app-dev/pyspark/references/etl-contract.md +129 -0
- package/skills/app-dev/pyspark/references/production-validation.md +131 -0
- package/skills/app-dev/pyspark/references/reconciliation.md +38 -0
- package/skills/app-dev/pyspark/references/transformation-design.md +190 -0
- package/skills/app-dev/pyspark/references/velocity-feature-calculation.md +193 -0
- package/skills/app-dev/pyspark/release-check.mjs +93 -0
- package/skills/app-dev/pyspark/scripts/spark_eventlog_summary.py +223 -0
- package/skills/app-dev/python-backend/LICENSE +3 -0
- package/skills/app-dev/python-backend/SKILL.md +325 -0
- package/skills/app-dev/python-backend/assets/uv-install.sh +48 -0
- package/skills/app-dev/python-backend/references/uv-installs.md +83 -0
- package/skills/app-dev/python-backend/release-check.mjs +93 -0
- package/skills/app-dev/shadcn/LICENSE +3 -0
- package/skills/app-dev/shadcn/SKILL.md +120 -0
- package/skills/app-dev/shadcn/assets/shadcn-small.png +0 -0
- package/skills/app-dev/shadcn/assets/shadcn.png +0 -0
- package/skills/app-dev/shadcn/cli.md +411 -0
- package/skills/app-dev/shadcn/customization.md +224 -0
- package/skills/app-dev/shadcn/mcp.md +101 -0
- package/skills/app-dev/shadcn/release-check.mjs +93 -0
- package/skills/app-dev/shadcn/rules/base-vs-radix.md +323 -0
- package/skills/app-dev/shadcn/rules/component-selection.md +67 -0
- package/skills/app-dev/shadcn/rules/composition.md +195 -0
- package/skills/app-dev/shadcn/rules/data-table.md +201 -0
- package/skills/app-dev/shadcn/rules/forms.md +255 -0
- package/skills/app-dev/shadcn/rules/icons.md +103 -0
- package/skills/app-dev/shadcn/rules/styling.md +167 -0
- package/skills/app-dev/zod-v4/LICENSE +3 -0
- package/skills/app-dev/zod-v4/SKILL.md +286 -0
- package/skills/app-dev/zod-v4/release-check.mjs +93 -0
- package/skills/cicd/cloud-build/LICENSE +3 -0
- package/skills/cicd/cloud-build/SKILL.md +707 -0
- package/skills/cicd/cloud-build/release-check.mjs +93 -0
- package/skills/cicd/cloud-debug/LICENSE +3 -0
- package/skills/cicd/cloud-debug/SKILL.md +315 -0
- package/skills/cicd/cloud-debug/references/build-failures.md +238 -0
- package/skills/cicd/cloud-debug/references/deploy-failures.md +376 -0
- package/skills/cicd/cloud-debug/references/pipeline-failures.md +378 -0
- package/skills/cicd/cloud-debug/release-check.mjs +93 -0
- package/skills/cicd/cloud-deploy/LICENSE +3 -0
- package/skills/cicd/cloud-deploy/SKILL.md +230 -0
- package/skills/cicd/cloud-deploy/references/config-templates.md +257 -0
- package/skills/cicd/cloud-deploy/release-check.mjs +93 -0
- package/skills/cicd/docker/LICENSE +3 -0
- package/skills/cicd/docker/SKILL.md +151 -0
- package/skills/cicd/docker/release-check.mjs +93 -0
- package/skills/cicd/github-actions/LICENSE +3 -0
- package/skills/cicd/github-actions/SKILL.md +111 -0
- package/skills/cicd/github-actions/references/audit-profile-optimize.md +150 -0
- package/skills/cicd/github-actions/references/ci-case-studies.md +141 -0
- package/skills/cicd/github-actions/references/conditional-ci.md +214 -0
- package/skills/cicd/github-actions/references/debugging.md +13 -0
- package/skills/cicd/github-actions/references/pipeline.md +87 -0
- package/skills/cicd/github-actions/references/post-deploy-and-publishing.md +33 -0
- package/skills/cicd/github-actions/references/runners.md +253 -0
- package/skills/cicd/github-actions/references/security.md +29 -0
- package/skills/cicd/github-actions/references/speed-and-audit.md +115 -0
- package/skills/cicd/github-actions/references/two-pass-reading.md +92 -0
- package/skills/cicd/github-actions/release-check.mjs +93 -0
- package/skills/cicd/github-actions/scripts/ci-run-audit-core.mjs +612 -0
- package/skills/cicd/github-actions/scripts/ci-run-audit.mjs +4 -0
- package/skills/cicd/github-actions/scripts/ci-run-audit.test.mjs +637 -0
- package/skills/cicd/github-flow/LICENSE +3 -0
- package/skills/cicd/github-flow/SKILL.md +123 -0
- package/skills/cicd/github-flow/references/ci-conventions.md +14 -0
- package/skills/cicd/github-flow/release-check.mjs +93 -0
- package/skills/cicd/github-flow/scripts/flow-core.mjs +105 -0
- package/skills/cicd/github-flow/scripts/flow.mjs +81 -0
- package/skills/cicd/github-flow/scripts/flow.test.mjs +114 -0
- package/skills/cicd/github-flow/scripts/persist-conventions-core.mjs +117 -0
- package/skills/cicd/github-flow/scripts/persist-conventions.mjs +49 -0
- package/skills/cicd/github-flow/scripts/persist-conventions.test.mjs +108 -0
- package/skills/cicd/google-cloud/LICENSE +3 -0
- package/skills/cicd/google-cloud/SKILL.md +119 -0
- package/skills/cicd/google-cloud/references/gcs.md +469 -0
- package/skills/cicd/google-cloud/references/iam.md +451 -0
- package/skills/cicd/google-cloud/references/project.md +349 -0
- package/skills/cicd/google-cloud/references/secrets.md +336 -0
- package/skills/cicd/google-cloud/references/vpc.md +312 -0
- package/skills/cicd/google-cloud/release-check.mjs +93 -0
- package/skills/cicd/google-cloud/scripts/create-sa.sh +36 -0
- package/skills/cicd/google-cloud/scripts/gcp-config.sh +31 -0
- package/skills/cicd/google-cloud/scripts/grant-iap.sh +41 -0
- package/skills/cicd/google-cloud/scripts/setup-secrets.sh +48 -0
- package/skills/cicd/mergify/LICENSE +3 -0
- package/skills/cicd/mergify/SKILL.md +102 -0
- package/skills/cicd/mergify/assets/templates/mergify.yml +215 -0
- package/skills/cicd/mergify/assets/templates/ruleset.json +46 -0
- package/skills/cicd/mergify/references/branch-protection.md +282 -0
- package/skills/cicd/mergify/references/configuration.md +274 -0
- package/skills/cicd/mergify/references/diagnosis.md +109 -0
- package/skills/cicd/mergify/references/stacks.md +84 -0
- package/skills/cicd/mergify/references/traps.md +119 -0
- package/skills/cicd/mergify/references/watch-contract.md +274 -0
- package/skills/cicd/mergify/release-check.mjs +93 -0
- package/skills/cicd/mergify/scripts/audit-core.mjs +208 -0
- package/skills/cicd/mergify/scripts/audit.mjs +4 -0
- package/skills/cicd/mergify/scripts/audit.test.mjs +201 -0
- package/skills/cicd/mergify/scripts/entrypoints.test.mjs +106 -0
- package/skills/cicd/mergify/scripts/pr-620-mergify-comments.fixture.json +30 -0
- package/skills/cicd/mergify/scripts/stack-push-core.mjs +258 -0
- package/skills/cicd/mergify/scripts/stack-push.mjs +4 -0
- package/skills/cicd/mergify/scripts/stack-push.test.mjs +233 -0
- package/skills/cicd/mergify/scripts/watch-pr-delivery-core.mjs +1065 -0
- package/skills/cicd/mergify/scripts/watch-pr-delivery.mjs +4 -0
- package/skills/cicd/mergify/scripts/watch-pr-delivery.test.mjs +1826 -0
- package/skills/cicd/podman/LICENSE +3 -0
- package/skills/cicd/podman/SKILL.md +71 -0
- package/skills/cicd/podman/agents/openai.yaml +4 -0
- package/skills/cicd/podman/assets/templates/podman-compose-socket-directory.yml +6 -0
- package/skills/cicd/podman/assets/templates/podman-service-override.conf +3 -0
- package/skills/cicd/podman/references/compose-compatibility.md +70 -0
- package/skills/cicd/podman/references/networking-and-ports.md +74 -0
- package/skills/cicd/podman/references/rootless-services-and-sockets.md +156 -0
- package/skills/cicd/podman/references/troubleshooting.md +98 -0
- package/skills/cicd/podman/release-check.mjs +93 -0
- package/skills/content/article-review/LICENSE +3 -0
- package/skills/content/article-review/SKILL.md +66 -0
- package/skills/content/article-review/references/report-format.md +68 -0
- package/skills/content/article-review/references/template-guide.md +79 -0
- package/skills/content/article-review/references/template-wechat-payments.md +125 -0
- package/skills/content/article-review/release-check.mjs +93 -0
- package/skills/content/article-to-image/LICENSE +3 -0
- package/skills/content/article-to-image/SKILL.md +91 -0
- package/skills/content/article-to-image/references/formats.md +53 -0
- package/skills/content/article-to-image/release-check.mjs +93 -0
- package/skills/content/flowchart-svg/LICENSE +3 -0
- package/skills/content/flowchart-svg/SKILL.md +43 -0
- package/skills/content/flowchart-svg/release-check.mjs +93 -0
- package/skills/content/flowchart-svg/scripts/export_png.sh +8 -0
- package/skills/content/image-gen/LICENSE +3 -0
- package/skills/content/image-gen/SKILL.md +192 -0
- package/skills/content/image-gen/release-check.mjs +93 -0
- package/skills/content/image-gen/scripts/credentials.mjs +217 -0
- package/skills/content/image-gen/scripts/credentials.test.mjs +212 -0
- package/skills/content/image-gen/scripts/generate.mjs +240 -0
- package/skills/content/image-gen/scripts/options.mjs +293 -0
- package/skills/content/image-gen/scripts/options.test.mjs +245 -0
- package/skills/content/mermaid/LICENSE +3 -0
- package/skills/content/mermaid/SKILL.md +635 -0
- package/skills/content/mermaid/release-check.mjs +93 -0
- package/skills/content/wechat-article-writer/LICENSE +3 -0
- package/skills/content/wechat-article-writer/SKILL.md +92 -0
- package/skills/content/wechat-article-writer/references/style-selector.md +133 -0
- package/skills/content/wechat-article-writer/references/writing-rules.md +152 -0
- package/skills/content/wechat-article-writer/release-check.mjs +93 -0
- package/skills/content/wechat-article-writer/templates/wechat-comparison.md +52 -0
- package/skills/content/wechat-article-writer/templates/wechat-howto.md +51 -0
- package/skills/content/wechat-article-writer/templates/wechat-insight.md +50 -0
- package/skills/content/wechat-article-writer/templates/wechat-pitfall.md +52 -0
- package/skills/content/wechat-publisher/LICENSE +3 -0
- package/skills/content/wechat-publisher/SKILL.md +171 -0
- package/skills/content/wechat-publisher/references/api.md +105 -0
- package/skills/content/wechat-publisher/references/layout-rules.md +57 -0
- package/skills/content/wechat-publisher/references/wechat-safe-template.html +86 -0
- package/skills/content/wechat-publisher/release-check.mjs +93 -0
- package/skills/content/wechat-publisher/scripts/md_to_wechat_html.py +194 -0
- package/skills/content/wechat-publisher/scripts/publish.py +239 -0
- package/skills/content/wechat-search/LICENSE +3 -0
- package/skills/content/wechat-search/SKILL.md +211 -0
- package/skills/content/wechat-search/release-check.mjs +93 -0
- package/skills/content/wechat-search/scripts/start-chrome.sh +83 -0
- package/skills/content/xai-search/LICENSE +3 -0
- package/skills/content/xai-search/SKILL.md +79 -0
- package/skills/content/xai-search/release-check.mjs +93 -0
- package/skills/content/xai-search/scripts/xai_search.sh +187 -0
- package/skills/content/xai-search/tests/smoke_test.sh +36 -0
- package/skills/core/distill-writing/LICENSE +3 -0
- package/skills/core/distill-writing/SKILL.md +74 -0
- package/skills/core/distill-writing/references/extraction.md +95 -0
- package/skills/core/distill-writing/references/updating.md +46 -0
- package/skills/core/distill-writing/release-check.mjs +93 -0
- package/skills/core/doc-to-md/LICENSE +3 -0
- package/skills/core/doc-to-md/SKILL.md +78 -0
- package/skills/core/doc-to-md/release-check.mjs +93 -0
- package/skills/core/doc-to-md/scripts/convert.py +157 -0
- package/skills/core/editorial-review/LICENSE +3 -0
- package/skills/core/editorial-review/SKILL.md +79 -0
- package/skills/core/editorial-review/references/checklist.md +94 -0
- package/skills/core/editorial-review/release-check.mjs +93 -0
- package/skills/core/house-style/LICENSE +3 -0
- package/skills/core/house-style/SKILL.md +33 -0
- package/skills/core/house-style/references/defaults.md +66 -0
- package/skills/core/house-style/references/rules.md +267 -0
- package/skills/core/house-style/references/sources.md +27 -0
- package/skills/core/house-style/references/style-en.md +131 -0
- package/skills/core/house-style/references/style-zh.md +141 -0
- package/skills/core/house-style/references/terminology-zh.md +223 -0
- package/skills/core/house-style/release-check.mjs +93 -0
- package/skills/core/house-style/templates/brd.md +103 -0
- package/skills/core/house-style/templates/commercial-proposal.md +93 -0
- package/skills/core/house-style/templates/compliance-policy.md +109 -0
- package/skills/core/house-style/templates/gap-analysis.md +105 -0
- package/skills/core/house-style/templates/general.md +63 -0
- package/skills/core/house-style/templates/integration-guide.md +98 -0
- package/skills/core/house-style/templates/prd.md +81 -0
- package/skills/core/house-style/templates/risk-operations-procedure.md +94 -0
- package/skills/core/house-style/templates/technical-spec.md +96 -0
- package/skills/core/polish-cn/LICENSE +3 -0
- package/skills/core/polish-cn/SKILL.md +102 -0
- package/skills/core/polish-cn/references/brief.md +93 -0
- package/skills/core/polish-cn/references/models.md +76 -0
- package/skills/core/polish-cn/release-check.mjs +93 -0
- package/skills/core/polish-cn/scripts/polish-cn.test.mjs +244 -0
- package/skills/core/polish-cn/scripts/polish_blocks.py +489 -0
- package/skills/core/reg-parser/LICENSE +3 -0
- package/skills/core/reg-parser/SKILL.md +212 -0
- package/skills/core/reg-parser/references/checklist-schema.md +223 -0
- package/skills/core/reg-parser/references/checklists/hk-amlo-checklist.json +1306 -0
- package/skills/core/reg-parser/references/checklists/hk-amlo-checklist.md +469 -0
- package/skills/core/reg-parser/references/checklists/hk-fi-corporate-onboarding-cdd-checklist.json +634 -0
- package/skills/core/reg-parser/references/checklists/hk-fi-corporate-onboarding-cdd-checklist.md +233 -0
- package/skills/core/reg-parser/references/checklists/hk-mso-guideline-checklist.json +2194 -0
- package/skills/core/reg-parser/references/checklists/hk-mso-guideline-checklist.md +771 -0
- package/skills/core/reg-parser/references/checklists/kyc-aml-checklist.md +258 -0
- package/skills/core/reg-parser/references/checklists/visa-vars-checklist.md +1058 -0
- package/skills/core/reg-parser/references/mandates/hk-amlo-cap615.md +389 -0
- package/skills/core/reg-parser/references/mandates/visa-vars.md +205 -0
- package/skills/core/reg-parser/release-check.mjs +93 -0
- package/skills/core/reg-parser/scripts/compare_checklist.py +230 -0
- package/skills/core/reg-parser/scripts/dump_checklist.py +361 -0
- package/skills/core/reg-parser/scripts/preprocess-mandate.sh +187 -0
- package/skills/core/reg-parser/scripts/reg-parser.test.mjs +165 -0
- package/skills/core/reg-parser/scripts/test_quarantine.sh +105 -0
- package/skills/core/reg-parser/scripts/validate_checklist.py +563 -0
- package/skills/core/reg-parser/scripts/validate_mandate.py +273 -0
- package/skills/core/terminology/LICENSE +3 -0
- package/skills/core/terminology/SKILL.md +62 -0
- package/skills/core/terminology/references/format.md +50 -0
- package/skills/core/terminology/references/init.md +32 -0
- package/skills/core/terminology/release-check.mjs +93 -0
- package/skills/core/write-doc/LICENSE +3 -0
- package/skills/core/write-doc/SKILL.md +141 -0
- package/skills/core/write-doc/references/bilingual.md +60 -0
- package/skills/core/write-doc/release-check.mjs +93 -0
- package/skills/engineering/better-review/LICENSE +3 -0
- package/skills/engineering/better-review/SKILL.md +249 -0
- package/skills/engineering/better-review/agents/openai.yaml +9 -0
- package/skills/engineering/better-review/references/domain-hazards.md +53 -0
- package/skills/engineering/better-review/references/passes.md +147 -0
- package/skills/engineering/better-review/references/result.md +151 -0
- package/skills/engineering/better-review/release-check.mjs +93 -0
- package/skills/engineering/better-review/scripts/pr-context.mjs +212 -0
- package/skills/engineering/better-review/scripts/pr-context.test.mjs +168 -0
- package/skills/engineering/better-review/scripts/rereview-scope.mjs +503 -0
- package/skills/engineering/better-review/scripts/rereview-scope.test.mjs +587 -0
- package/skills/engineering/better-review/scripts/scan-diff.mjs +365 -0
- package/skills/engineering/better-review/scripts/scan-diff.test.mjs +414 -0
- package/skills/engineering/better-review/scripts/vendor-sync.test.mjs +96 -0
- package/skills/engineering/e2e-test/LICENSE +3 -0
- package/skills/engineering/e2e-test/SKILL.md +98 -0
- package/skills/engineering/e2e-test/assets/ci-gates.cloudbuild.yaml +24 -0
- package/skills/engineering/e2e-test/references/authoring/auth-flows.md +159 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-config.md +73 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-patterns.md +144 -0
- package/skills/engineering/e2e-test/references/ci-integration.md +25 -0
- package/skills/engineering/e2e-test/references/ci-playwright-container.md +290 -0
- package/skills/engineering/e2e-test/references/presentation-sweep.md +104 -0
- package/skills/engineering/e2e-test/references/reviewing.md +41 -0
- package/skills/engineering/e2e-test/references/route-manifest.md +51 -0
- package/skills/engineering/e2e-test/release-check.mjs +93 -0
- package/skills/engineering/e2e-test/scripts/detect-routes-nextjs.mjs +200 -0
- package/skills/engineering/e2e-test/scripts/presentation-checks.mjs +171 -0
- package/skills/engineering/e2e-test/scripts/presentation-checks.test.mjs +106 -0
- package/skills/engineering/e2e-test/scripts/presentation-perceivability.mjs +179 -0
- package/skills/engineering/e2e-test/scripts/presentation-perceivability.test.mjs +117 -0
- package/skills/engineering/e2e-test/scripts/presentation-reachability.mjs +154 -0
- package/skills/engineering/e2e-test/scripts/presentation-reachability.test.mjs +69 -0
- package/skills/engineering/e2e-test/scripts/presentation-render-health.mjs +141 -0
- package/skills/engineering/e2e-test/scripts/presentation-render-health.test.mjs +98 -0
- package/skills/engineering/e2e-test/scripts/presentation-sweep.mjs +147 -0
- package/skills/engineering/e2e-test/scripts/presentation-sweep.test.mjs +71 -0
- package/skills/engineering/e2e-test/scripts/presentation-temporal.mjs +127 -0
- package/skills/engineering/e2e-test/scripts/presentation-temporal.test.mjs +59 -0
- package/skills/engineering/e2e-test/scripts/project-route-manifest.mjs +82 -0
- package/skills/engineering/e2e-test/scripts/project-route-manifest.test.mjs +76 -0
- package/skills/engineering/e2e-test/scripts/validate-manifest.mjs +106 -0
- package/skills/engineering/engineering-runtime/LICENSE +3 -0
- package/skills/engineering/engineering-runtime/SKILL.md +11 -0
- package/skills/engineering/engineering-runtime/agents/openai.yaml +6 -0
- package/skills/engineering/engineering-runtime/coherence/workflow.json +597 -0
- package/skills/engineering/engineering-runtime/engineering-runtime.test.mjs +68 -0
- package/skills/engineering/engineering-runtime/release-check.mjs +93 -0
- package/skills/engineering/engineering-runtime/scripts/exact-head-artifact.mjs +131 -0
- package/skills/engineering/engineering-runtime/scripts/head-check-set.mjs +398 -0
- package/skills/engineering/engineering-runtime/scripts/invocation-policy.mjs +187 -0
- package/skills/engineering/engineering-runtime/scripts/invocation-policy.test.mjs +95 -0
- package/skills/engineering/engineering-runtime/scripts/main-module.mjs +79 -0
- package/skills/engineering/engineering-runtime/scripts/main-module.test.mjs +288 -0
- package/skills/engineering/engineering-runtime/scripts/mergify-yaml.mjs +11 -0
- package/skills/engineering/engineering-runtime/scripts/package-lock.json +43 -0
- package/skills/engineering/engineering-runtime/scripts/package.json +10 -0
- package/skills/engineering/engineering-runtime/scripts/required-check-plan.mjs +223 -0
- package/skills/engineering/engineering-runtime/scripts/required-check-plan.test.mjs +96 -0
- package/skills/engineering/engineering-runtime/scripts/review-completion.mjs +56 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +595 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +189 -0
- package/skills/engineering/engineering-runtime/scripts/yaml-mapping.mjs +18 -0
- package/skills/engineering/ensure-coverage/LICENSE +3 -0
- package/skills/engineering/ensure-coverage/SKILL.md +129 -0
- package/skills/engineering/ensure-coverage/references/breadth/coverage-ledger.md +92 -0
- package/skills/engineering/ensure-coverage/references/breadth/inventory-contract.md +85 -0
- package/skills/engineering/ensure-coverage/references/breadth/surface-baseline.md +44 -0
- package/skills/engineering/ensure-coverage/references/breadth/surface-discovery.md +16 -0
- package/skills/engineering/ensure-coverage/references/depth/characterization.md +68 -0
- package/skills/engineering/ensure-coverage/references/depth/coverage.config.example.json +19 -0
- package/skills/engineering/ensure-coverage/references/depth/grading.md +35 -0
- package/skills/engineering/ensure-coverage/references/depth/mock-policy.md +57 -0
- package/skills/engineering/ensure-coverage/references/depth/test-smells.md +39 -0
- package/skills/engineering/ensure-coverage/references/enforcement/ci-contract.md +44 -0
- package/skills/engineering/ensure-coverage/references/examples/coverage-ledger.md +110 -0
- package/skills/engineering/ensure-coverage/references/examples/refund-flow.md +35 -0
- package/skills/engineering/ensure-coverage/references/presentation/axis.md +64 -0
- package/skills/engineering/ensure-coverage/references/process/audit-mode.md +27 -0
- package/skills/engineering/ensure-coverage/references/process/output-template.md +139 -0
- package/skills/engineering/ensure-coverage/references/process/test-strategy.md +56 -0
- package/skills/engineering/ensure-coverage/release-check.mjs +93 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-config.schema.json +67 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-file.schema.json +140 -0
- package/skills/engineering/ensure-coverage/scripts/README.md +99 -0
- package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.mjs +182 -0
- package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.test.mjs +96 -0
- package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.mjs +105 -0
- package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.test.mjs +47 -0
- package/skills/engineering/ensure-coverage/scripts/ci-audit.mjs +137 -0
- package/skills/engineering/ensure-coverage/scripts/ci-audit.test.mjs +86 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-ledger.mjs +674 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-ledger.test.mjs +447 -0
- package/skills/engineering/ensure-coverage/scripts/design-parity.mjs +591 -0
- package/skills/engineering/ensure-coverage/scripts/design-parity.test.mjs +552 -0
- package/skills/engineering/ensure-coverage/scripts/lint-tests.mjs +282 -0
- package/skills/engineering/ensure-coverage/scripts/lint-tests.test.mjs +289 -0
- package/skills/engineering/ensure-coverage/scripts/mock-policy-config.mjs +176 -0
- package/skills/engineering/ensure-coverage/scripts/mock-policy-config.test.mjs +119 -0
- package/skills/engineering/ensure-coverage/scripts/package.json +19 -0
- package/skills/engineering/golden-path/LICENSE +3 -0
- package/skills/engineering/golden-path/SKILL.md +230 -0
- package/skills/engineering/golden-path/agents/openai.yaml +3 -0
- package/skills/engineering/golden-path/assets/golden-paths.example.json +57 -0
- package/skills/engineering/golden-path/references/contract.md +239 -0
- package/skills/engineering/golden-path/references/migration.md +111 -0
- package/skills/engineering/golden-path/release-check.mjs +93 -0
- package/skills/engineering/golden-path/scripts/golden-path-core.mjs +1779 -0
- package/skills/engineering/golden-path/scripts/golden-path.mjs +6 -0
- package/skills/engineering/golden-path/scripts/golden-path.test.mjs +1457 -0
- package/skills/engineering/harness-runtime/LICENSE +3 -0
- package/skills/engineering/harness-runtime/SKILL.md +19 -0
- package/skills/engineering/harness-runtime/agents/openai.yaml +6 -0
- package/skills/engineering/harness-runtime/bin/discover-models.mjs +4 -0
- package/skills/engineering/harness-runtime/bin/model-catalog.mjs +4 -0
- package/skills/engineering/harness-runtime/contracts.md +15 -0
- package/skills/engineering/harness-runtime/discover-models.mjs +392 -0
- package/skills/engineering/harness-runtime/discover-models.test.mjs +363 -0
- package/skills/engineering/harness-runtime/fixtures/native-question-schemas.json +33 -0
- package/skills/engineering/harness-runtime/fixtures/question-responses.json +54 -0
- package/skills/engineering/harness-runtime/harness-runtime.test.mjs +967 -0
- package/skills/engineering/harness-runtime/index.mjs +767 -0
- package/skills/engineering/harness-runtime/model-catalog-seed.test.mjs +829 -0
- package/skills/engineering/harness-runtime/model-catalog.mjs +787 -0
- package/skills/engineering/harness-runtime/model-catalog.test.mjs +366 -0
- package/skills/engineering/harness-runtime/native-question-contracts.md +37 -0
- package/skills/engineering/harness-runtime/references/model-catalog-seed.json +408 -0
- package/skills/engineering/harness-runtime/references/model-catalog.md +57 -0
- package/skills/engineering/harness-runtime/release-check.mjs +93 -0
- package/skills/engineering/resolve-issues/LICENSE +3 -0
- package/skills/engineering/resolve-issues/SKILL.md +250 -0
- package/skills/engineering/resolve-issues/agents/openai.yaml +9 -0
- package/skills/engineering/resolve-issues/plugin-hooks.json +17 -0
- package/skills/engineering/resolve-issues/references/canary.md +28 -0
- package/skills/engineering/resolve-issues/references/ci.md +105 -0
- package/skills/engineering/resolve-issues/references/done.md +25 -0
- package/skills/engineering/resolve-issues/references/dropbox.md +90 -0
- package/skills/engineering/resolve-issues/references/expire.md +318 -0
- package/skills/engineering/resolve-issues/references/exploration.md +202 -0
- package/skills/engineering/resolve-issues/references/implementation.md +303 -0
- package/skills/engineering/resolve-issues/references/preflight.md +445 -0
- package/skills/engineering/resolve-issues/references/review.md +228 -0
- package/skills/engineering/resolve-issues/references/shared-modules.md +44 -0
- package/skills/engineering/resolve-issues/references/task-plan.md +264 -0
- package/skills/engineering/resolve-issues/release-check.mjs +93 -0
- package/skills/engineering/resolve-issues/scripts/cleanup-runs.mjs +364 -0
- package/skills/engineering/resolve-issues/scripts/cleanup-runs.test.mjs +280 -0
- package/skills/engineering/resolve-issues/scripts/discover-models.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/dropbox.mjs +473 -0
- package/skills/engineering/resolve-issues/scripts/dropbox.test.mjs +346 -0
- package/skills/engineering/resolve-issues/scripts/findings-reuse.mjs +98 -0
- package/skills/engineering/resolve-issues/scripts/findings-reuse.test.mjs +88 -0
- package/skills/engineering/resolve-issues/scripts/github-reviews.mjs +384 -0
- package/skills/engineering/resolve-issues/scripts/github-reviews.test.mjs +264 -0
- package/skills/engineering/resolve-issues/scripts/install-hooks.mjs +135 -0
- package/skills/engineering/resolve-issues/scripts/install-hooks.test.mjs +79 -0
- package/skills/engineering/resolve-issues/scripts/issue-tree.mjs +162 -0
- package/skills/engineering/resolve-issues/scripts/issue-tree.test.mjs +107 -0
- package/skills/engineering/resolve-issues/scripts/manual-invocation.test.mjs +14 -0
- package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/next-actions-capacity.test.mjs +149 -0
- package/skills/engineering/resolve-issues/scripts/next-actions.mjs +856 -0
- package/skills/engineering/resolve-issues/scripts/next-actions.test.mjs +915 -0
- package/skills/engineering/resolve-issues/scripts/plan-sync.mjs +269 -0
- package/skills/engineering/resolve-issues/scripts/plan-sync.test.mjs +156 -0
- package/skills/engineering/resolve-issues/scripts/preflight-models.mjs +736 -0
- package/skills/engineering/resolve-issues/scripts/preflight-models.test.mjs +448 -0
- package/skills/engineering/resolve-issues/scripts/ready-check.mjs +185 -0
- package/skills/engineering/resolve-issues/scripts/ready-check.test.mjs +217 -0
- package/skills/engineering/resolve-issues/scripts/rehydrate.mjs +98 -0
- package/skills/engineering/resolve-issues/scripts/rehydrate.test.mjs +91 -0
- package/skills/engineering/resolve-issues/scripts/review-verdict.mjs +509 -0
- package/skills/engineering/resolve-issues/scripts/review-verdict.test.mjs +1060 -0
- package/skills/engineering/resolve-issues/scripts/size-check.mjs +492 -0
- package/skills/engineering/resolve-issues/scripts/size-check.test.mjs +458 -0
- package/skills/engineering/resolve-release/LICENSE +3 -0
- package/skills/engineering/resolve-release/SKILL.md +215 -0
- package/skills/engineering/resolve-release/agents/openai.yaml +8 -0
- package/skills/engineering/resolve-release/flows/cloud-run-canary.md +13 -0
- package/skills/engineering/resolve-release/flows/cloud-run.md +7 -0
- package/skills/engineering/resolve-release/flows/root-tag-npm.md +13 -0
- package/skills/engineering/resolve-release/flows/workspace-npm.md +22 -0
- package/skills/engineering/resolve-release/references/canary.md +51 -0
- package/skills/engineering/resolve-release/references/candidate.md +41 -0
- package/skills/engineering/resolve-release/references/cut.md +131 -0
- package/skills/engineering/resolve-release/references/dark-launch.md +66 -0
- package/skills/engineering/resolve-release/references/flows.md +150 -0
- package/skills/engineering/resolve-release/references/preflight.md +154 -0
- package/skills/engineering/resolve-release/references/prepared-metadata.md +260 -0
- package/skills/engineering/resolve-release/references/promotion.md +82 -0
- package/skills/engineering/resolve-release/references/publish.md +232 -0
- package/skills/engineering/resolve-release/references/workspace-npm.md +103 -0
- package/skills/engineering/resolve-release/release-check.mjs +93 -0
- package/skills/engineering/resolve-release/scripts/apply.mjs +212 -0
- package/skills/engineering/resolve-release/scripts/apply.test.mjs +99 -0
- package/skills/engineering/resolve-release/scripts/dark-flags.mjs +134 -0
- package/skills/engineering/resolve-release/scripts/dark-flags.test.mjs +100 -0
- package/skills/engineering/resolve-release/scripts/flow.mjs +500 -0
- package/skills/engineering/resolve-release/scripts/flow.test.mjs +340 -0
- package/skills/engineering/resolve-release/scripts/green-head.mjs +231 -0
- package/skills/engineering/resolve-release/scripts/green-head.test.mjs +101 -0
- package/skills/engineering/resolve-release/scripts/npm-version-absence.mjs +138 -0
- package/skills/engineering/resolve-release/scripts/npm-version-absence.test.mjs +426 -0
- package/skills/engineering/resolve-release/scripts/plan-npm.test.mjs +659 -0
- package/skills/engineering/resolve-release/scripts/plan-toml-boundary.test.mjs +317 -0
- package/skills/engineering/resolve-release/scripts/plan-uv.test.mjs +291 -0
- package/skills/engineering/resolve-release/scripts/plan.mjs +806 -0
- package/skills/engineering/resolve-release/scripts/plan.test.mjs +428 -0
- package/skills/engineering/rush-issues/LICENSE +3 -0
- package/skills/engineering/rush-issues/SKILL.md +58 -0
- package/skills/engineering/rush-issues/agents/openai.yaml +8 -0
- package/skills/engineering/rush-issues/rehydrate.mjs +10 -0
- package/skills/engineering/rush-issues/release-check.mjs +93 -0
- package/skills/engineering/rush-release/LICENSE +3 -0
- package/skills/engineering/rush-release/SKILL.md +35 -0
- package/skills/engineering/rush-release/agents/openai.yaml +8 -0
- package/skills/engineering/rush-release/release-check.mjs +93 -0
- package/skills/engineering/test-quality/LICENSE +3 -0
- package/skills/engineering/test-quality/SKILL.md +79 -0
- package/skills/engineering/test-quality/references/audit.md +80 -0
- package/skills/engineering/test-quality/references/lint.md +24 -0
- package/skills/engineering/test-quality/references/principles.md +143 -0
- package/skills/engineering/test-quality/references/testing-conventions.md +9 -0
- package/skills/engineering/test-quality/release-check.mjs +93 -0
- package/skills/engineering/test-quality/scripts/lint-tests.mjs +574 -0
- package/skills/engineering/test-quality/scripts/lint-tests.test.mjs +591 -0
- package/skills/engineering/test-quality/scripts/mock-policy-config.mjs +176 -0
- package/skills/engineering/test-quality/scripts/mock-policy-config.test.mjs +119 -0
- package/skills/engineering/test-quality/scripts/persist-conventions-core.mjs +117 -0
- package/skills/engineering/test-quality/scripts/persist-conventions.mjs +17 -0
- package/skills/engineering/test-quality/scripts/persist-conventions.test.mjs +104 -0
- package/skills/risk-compliance/compliance-audit/LICENSE +3 -0
- package/skills/risk-compliance/compliance-audit/SKILL.md +439 -0
- package/skills/risk-compliance/compliance-audit/references/findings-schema.md +293 -0
- package/skills/risk-compliance/compliance-audit/references/normalization-rules.md +45 -0
- package/skills/risk-compliance/compliance-audit/references/vars-checklist.md +1068 -0
- package/skills/risk-compliance/compliance-audit/references/vars-findings-schema.md +398 -0
- package/skills/risk-compliance/compliance-audit/release-check.mjs +93 -0
- package/skills/risk-compliance/compliance-audit/scripts/compliance-audit.test.mjs +14 -0
- package/skills/risk-compliance/compliance-audit/scripts/export_tracker_xlsx.py +221 -0
- package/skills/risk-compliance/compliance-audit/scripts/reconcile_tracker.py +458 -0
- package/skills/risk-compliance/compliance-audit/scripts/test_export_tracker_xlsx.py +97 -0
- package/skills/risk-compliance/compliance-audit/scripts/test_validate_tracker.py +157 -0
- package/skills/risk-compliance/compliance-audit/scripts/validate_tracker.py +829 -0
- package/skills/risk-compliance/contract-compare/LICENSE +3 -0
- package/skills/risk-compliance/contract-compare/SKILL.md +199 -0
- package/skills/risk-compliance/contract-compare/references/comparison-dimensions.md +209 -0
- package/skills/risk-compliance/contract-compare/release-check.mjs +93 -0
- package/skills/risk-compliance/contract-review/LICENSE +3 -0
- package/skills/risk-compliance/contract-review/SKILL.md +240 -0
- package/skills/risk-compliance/contract-review/references/review-criteria.md +223 -0
- package/skills/risk-compliance/contract-review/release-check.mjs +93 -0
- package/skills/risk-compliance/doc-authenticity/LICENSE +3 -0
- package/skills/risk-compliance/doc-authenticity/SKILL.md +160 -0
- package/skills/risk-compliance/doc-authenticity/agents/openai.yaml +8 -0
- package/skills/risk-compliance/doc-authenticity/manual-invocation.test.mjs +12 -0
- package/skills/risk-compliance/doc-authenticity/references/agreement.md +66 -0
- package/skills/risk-compliance/doc-authenticity/references/bank-statement.md +150 -0
- package/skills/risk-compliance/doc-authenticity/references/forensic-signals.md +157 -0
- package/skills/risk-compliance/doc-authenticity/references/image-signals.md +114 -0
- package/skills/risk-compliance/doc-authenticity/references/invoice.md +66 -0
- package/skills/risk-compliance/doc-authenticity/references/issuer-profiles.md +86 -0
- package/skills/risk-compliance/doc-authenticity/references/verdict-and-report.md +95 -0
- package/skills/risk-compliance/doc-authenticity/references/verdict.schema.json +81 -0
- package/skills/risk-compliance/doc-authenticity/release-check.mjs +93 -0
- package/skills/risk-compliance/doc-authenticity/scripts/image_forensics.py +294 -0
- package/skills/risk-compliance/doc-authenticity/scripts/pdf_forensics.py +401 -0
- package/skills/risk-compliance/doc-authenticity/scripts/validate_codes.py +224 -0
- package/skills/risk-compliance/doc-authenticity/scripts/validate_verdict.py +308 -0
- package/skills/risk-compliance/doc-authenticity/scripts/validate_verdict.test.mjs +212 -0
- package/skills/risk-compliance/fraud-analysis/LICENSE +3 -0
- package/skills/risk-compliance/fraud-analysis/SKILL.md +114 -0
- package/skills/risk-compliance/fraud-analysis/references/archetypes/authorized-payment-scam.md +41 -0
- package/skills/risk-compliance/fraud-analysis/references/archetypes/first-party-fraud.md +44 -0
- package/skills/risk-compliance/fraud-analysis/references/archetypes/third-party-fraud.md +27 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/bank-transfer.md +24 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/card-payment.md +30 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/payment-collection.md +20 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/payout.md +20 -0
- package/skills/risk-compliance/fraud-analysis/references/feature-engineering.md +158 -0
- package/skills/risk-compliance/fraud-analysis/references/mechanisms/account-takeover.md +36 -0
- package/skills/risk-compliance/fraud-analysis/references/report-rationale.md +45 -0
- package/skills/risk-compliance/fraud-analysis/references/report-template.md +190 -0
- package/skills/risk-compliance/fraud-analysis/references/review-checklist.md +175 -0
- package/skills/risk-compliance/fraud-analysis/references/taxonomy.md +79 -0
- package/skills/risk-compliance/fraud-analysis/references/terminology.md +108 -0
- package/skills/risk-compliance/fraud-analysis/references/workflow.md +175 -0
- package/skills/risk-compliance/fraud-analysis/release-check.mjs +93 -0
- package/skills/risk-compliance/payment-analysis/LICENSE +3 -0
- package/skills/risk-compliance/payment-analysis/SKILL.md +180 -0
- package/skills/risk-compliance/payment-analysis/references/auth-rate-actions.md +30 -0
- package/skills/risk-compliance/payment-analysis/references/chargebacks.md +208 -0
- package/skills/risk-compliance/payment-analysis/references/chinese-polish.md +51 -0
- package/skills/risk-compliance/payment-analysis/references/event-layers.md +127 -0
- package/skills/risk-compliance/payment-analysis/references/fx.md +59 -0
- package/skills/risk-compliance/payment-analysis/references/journey.md +79 -0
- package/skills/risk-compliance/payment-analysis/references/metrics.md +67 -0
- package/skills/risk-compliance/payment-analysis/references/report-template.md +119 -0
- package/skills/risk-compliance/payment-analysis/references/terminology.md +95 -0
- package/skills/risk-compliance/payment-analysis/references/visualization.md +56 -0
- package/skills/risk-compliance/payment-analysis/release-check.mjs +93 -0
- package/skills/risk-compliance/report-writing/LICENSE +3 -0
- package/skills/risk-compliance/report-writing/SKILL.md +220 -0
- package/skills/risk-compliance/report-writing/references/audit-report-template.md +121 -0
- package/skills/risk-compliance/report-writing/references/external-assessment-template.md +167 -0
- package/skills/risk-compliance/report-writing/references/management-report-template.md +145 -0
- package/skills/risk-compliance/report-writing/references/vars-report-template.md +224 -0
- package/skills/risk-compliance/report-writing/release-check.mjs +93 -0
- package/skills/risk-compliance/similar-domain/LICENSE +3 -0
- package/skills/risk-compliance/similar-domain/SKILL.md +203 -0
- package/skills/risk-compliance/similar-domain/references/entities.md +67 -0
- package/skills/risk-compliance/similar-domain/references/fingerprints.md +134 -0
- package/skills/risk-compliance/similar-domain/references/pivots.md +82 -0
- package/skills/risk-compliance/similar-domain/references/report-template.md +93 -0
- package/skills/risk-compliance/similar-domain/references/scoring.md +130 -0
- package/skills/risk-compliance/similar-domain/references/terminology.md +41 -0
- package/skills/risk-compliance/similar-domain/references/workflow.md +85 -0
- package/skills/risk-compliance/similar-domain/release-check.mjs +93 -0
- package/skills/risk-compliance/tld-detection/LICENSE +3 -0
- package/skills/risk-compliance/tld-detection/SKILL.md +245 -0
- package/skills/risk-compliance/tld-detection/agents/openai.yaml +9 -0
- package/skills/risk-compliance/tld-detection/references/chinese-polish.md +55 -0
- package/skills/risk-compliance/tld-detection/references/clean.md +51 -0
- package/skills/risk-compliance/tld-detection/references/clustering.md +235 -0
- package/skills/risk-compliance/tld-detection/references/decision.md +189 -0
- package/skills/risk-compliance/tld-detection/references/fx-conversion.md +232 -0
- package/skills/risk-compliance/tld-detection/references/report-template.md +272 -0
- package/skills/risk-compliance/tld-detection/references/streams.md +141 -0
- package/skills/risk-compliance/tld-detection/references/terminology.md +95 -0
- package/skills/risk-compliance/tld-detection/references/workflow.md +95 -0
- package/skills/risk-compliance/tld-detection/release-check.mjs +93 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_ladders.py +390 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_ladders.test.mjs +14 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_streams.py +650 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_streams.test.mjs +14 -0
- package/skills/risk-compliance/tld-detection/tests/test_detect_ladders.py +134 -0
- package/skills/risk-compliance/tld-detection/tests/test_detect_streams.py +520 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: android-foundation
|
|
3
|
+
description: "Prove an Expo / React Native app on a native Android emulator, and fix it when that proof fails. Use before you fix and re-run or re-dispatch a failed Android CI job (`gh workflow run android.yml`, `gh run rerun`): a re-run is not a debugger, so reproduce the failing journey checkpoint off CI first. Also use when a UiAutomator journey or its Python harness tests fail (a CHECK/FAIL line, a wait that timed out, a control not found, adb offline, a lost Metro bridge, a fixture failing on the runner), to build the debug APK and run the device journey, to set up a fresh Android workspace (SDK/NDK/JDK, Gradle caches, private AVD, disposable PostgreSQL), or to add the emulator job to CI. NOT for workflow YAML, CI speed or runner design (github-actions), browser tests (e2e-test), iOS (ios-foundation), plain Jest component tests, or signing and store release."
|
|
4
|
+
release-version: 0.36.0
|
|
5
|
+
---
|
|
6
|
+
**Updates:** Once/session run `node <skill-base-dir>/release-check.mjs`.
|
|
7
|
+
# Android foundation
|
|
8
|
+
|
|
9
|
+
Take a native Expo / React Native Android workspace from a fresh checkout to a passing
|
|
10
|
+
device journey, then record the evidence. Use the repo's existing build scripts, native
|
|
11
|
+
project, device harness and journey wrapper. For CI, add one job to the repo's `ci.yml`
|
|
12
|
+
from the template; do not write a separate release runbook.
|
|
13
|
+
|
|
14
|
+
Pick the mode first:
|
|
15
|
+
|
|
16
|
+
- **Setup proof:** a new workspace or CI job, a toolchain, dependency, native or harness
|
|
17
|
+
change, or a broken build-to-device path. Run every stage and write the
|
|
18
|
+
[evidence record](#evidence-record).
|
|
19
|
+
- **Feature work:** proving a product change on the emulator in a workspace already set
|
|
20
|
+
up. Follow [Feature work](#feature-work) and report only the journey result.
|
|
21
|
+
|
|
22
|
+
## Routing
|
|
23
|
+
|
|
24
|
+
| Step | Read |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| Shell snippets for every stage below | [references/setup.md](references/setup.md) |
|
|
27
|
+
| Stages 6–8 in one command | [scripts/device-run.sh](scripts/device-run.sh) |
|
|
28
|
+
| Adding the Android job to CI | [references/ci.md](references/ci.md), template [assets/android-ci-job.yml](assets/android-ci-job.yml) |
|
|
29
|
+
| Proving a product change on the emulator | [Feature work](#feature-work) |
|
|
30
|
+
| A stage failed | [Triage](#triage), then [references/gotchas.md](references/gotchas.md) |
|
|
31
|
+
| Writing up setup proof | [Evidence record](#evidence-record) |
|
|
32
|
+
|
|
33
|
+
## Rules
|
|
34
|
+
|
|
35
|
+
- Work in a dedicated worktree on a new branch from `origin/main`. Never overwrite or reuse
|
|
36
|
+
another checkout, and never symlink another worktree's `node_modules`.
|
|
37
|
+
- Tool shells keep no variables, functions or traps between calls. Write the environment
|
|
38
|
+
to `.cache/android-env.sh` once and source it at the start of every command. Run stages
|
|
39
|
+
6–8 as one `scripts/device-run.sh` command, never as separate calls.
|
|
40
|
+
- Keep every cache private to the worktree under `.cache/`: Gradle home, Android user home,
|
|
41
|
+
AVD home, `TMPDIR`, npm, node-gyp and pnpm store. Keep them between runs.
|
|
42
|
+
- Read toolchain versions from the repo: the root `packageManager` and `engines`, the
|
|
43
|
+
native Gradle config, and the CI preflight. The repo is the source of truth, not this skill.
|
|
44
|
+
- Check that every required SDK component (platform, build-tools, NDK, CMake,
|
|
45
|
+
platform-tools, emulator, system image) is already installed. If one is missing, stop and
|
|
46
|
+
provision it separately. Never upgrade or install into a shared SDK during a journey;
|
|
47
|
+
build with `-Pandroid.builder.sdkDownload=false`.
|
|
48
|
+
- Install with `--frozen-lockfile`. Do not routinely run `clean`, reinstall dependencies or
|
|
49
|
+
run `expo prebuild`. The native project is tracked, and prebuild needs a reviewed native
|
|
50
|
+
change.
|
|
51
|
+
- Build every configured ABI for setup proof and release acceptance. An x86_64-only CI
|
|
52
|
+
APK only proves the emulator ABI. For feature work, the emulator ABI is enough unless the
|
|
53
|
+
change touches native code or ABI configuration.
|
|
54
|
+
- A debug APK needs Metro. A successful export or build does not prove the app works on
|
|
55
|
+
a device. Only the device journey does.
|
|
56
|
+
|
|
57
|
+
## Stages
|
|
58
|
+
|
|
59
|
+
Run them in this order. Stop at the first failure and triage it.
|
|
60
|
+
|
|
61
|
+
1. **Checkout and environment.** Add the worktree and export the private cache paths,
|
|
62
|
+
`JAVA_HOME` (JDK 17), `ANDROID_HOME` and `ANDROID_SDK_ROOT`. Print the versions of
|
|
63
|
+
node, pnpm, java, python3, adb and the emulator. Assert that each SDK component
|
|
64
|
+
directory exists. Read the journey wrapper and device harness for the names they expect:
|
|
65
|
+
the venv path, the port variables, the database variables and the database-name prefix
|
|
66
|
+
the harness accepts.
|
|
67
|
+
2. **Install and check.** Run a frozen install, the app's unit tests, typecheck, and
|
|
68
|
+
`expo export --platform android` with a placeholder `EXPO_PUBLIC_API_URL`. Create a
|
|
69
|
+
Python venv for UI automation at the path the journey wrapper reads, and pin the
|
|
70
|
+
`uiautomator2` version the harness expects.
|
|
71
|
+
3. **Gradle dependencies.** Pick one:
|
|
72
|
+
- Seed: `rsync --ignore-existing` only `caches/modules-2/files-2.1/` from a trusted
|
|
73
|
+
Gradle home, excluding `*.lock`, `*.lck` and `*.tmp`. Never share writable caches,
|
|
74
|
+
metadata, credentials or APKs.
|
|
75
|
+
- Proxy: a private Gradle home does not inherit `~/.gradle/init.d`. Install the proxy's
|
|
76
|
+
init script into `$GRADLE_USER_HOME/init.d/` and export a route for every repository
|
|
77
|
+
the build uses, JitPack included. Ping the proxy first.
|
|
78
|
+
- Neither: build against upstream and expect a long cold build.
|
|
79
|
+
If the opted-in proxy fails, treat it as an error. Never fall back to direct downloads
|
|
80
|
+
and never disable TLS checks. The proxy covers Gradle Maven repositories only. Route the
|
|
81
|
+
Gradle wrapper ZIP and pnpm as the repo's CONTRIBUTING says.
|
|
82
|
+
4. **Build.** Run the repo's Android build script with `--max-workers=2
|
|
83
|
+
-Dorg.gradle.parallel=false -Pandroid.builder.sdkDownload=false --console=plain
|
|
84
|
+
--info`, keeping the log. For setup proof, hash the APK and list its `lib/<abi>/`
|
|
85
|
+
entries.
|
|
86
|
+
5. **Owned emulator.** Create a new private AVD in `$ANDROID_AVD_HOME` by copying only
|
|
87
|
+
`config.ini` from an installed AVD. Never copy its user data or snapshots. Check that
|
|
88
|
+
`image.sysdir.1` points to an installed, host-compatible image, and set `target` to
|
|
89
|
+
match it. Writing `config.ini` from scratch needs the hardware keys:
|
|
90
|
+
[gotchas](references/gotchas.md#a-hand-written-avd-misses-the-screen). Give the guest
|
|
91
|
+
4 GB: replace any `hw.ramSize` with `hw.ramSize=4096` (`device-run.sh` also passes
|
|
92
|
+
`-memory 4096`). At 2 GB, the usual `avdmanager` value, adb drops mid-journey ([gotchas](references/gotchas.md#the-adb-transport-drops-mid-journey)).
|
|
93
|
+
6. **Register cleanup before starting anything.** `device-run.sh` installs the `EXIT`
|
|
94
|
+
trap and the `INT`/`TERM` handlers first.
|
|
95
|
+
7. **Start resources.** The script refuses an emulator console port outside 5554–5584
|
|
96
|
+
(adb scans only that range) and any busy port, starts the ADB server, then the emulator
|
|
97
|
+
(PID recorded) and `postgres` (`--cidfile`, random loopback port), and waits for
|
|
98
|
+
`sys.boot_completed=1` and `pg_isready` with a time limit on every command.
|
|
99
|
+
8. **Journey.** The script hands the harness a database named with its accepted prefix and
|
|
100
|
+
runs the journey wrapper. Expect every scenario's `PASS` marker, plus screenshots, the
|
|
101
|
+
backend log and the Metro log.
|
|
102
|
+
|
|
103
|
+
## Owned-resource cleanup
|
|
104
|
+
|
|
105
|
+
- Clean up only what this run started: the emulator child PID, the container ID from the
|
|
106
|
+
CID file, and the named database. Signal the PID with `TERM`, wait up to 10 seconds, then
|
|
107
|
+
`KILL`. Then `wait` for it and confirm nothing is left. Count wait status 0 or 143 (ended
|
|
108
|
+
by your `TERM`) as a clean stop; count a needed `KILL` or any other status as a failure.
|
|
109
|
+
- Never use `adb kill-server`, `adb -s <serial> emu kill`, broad `pkill`, or
|
|
110
|
+
`docker system prune`. An ADB serial can be reused by another process; a PID you own
|
|
111
|
+
cannot.
|
|
112
|
+
- Give every startup, readiness and cleanup command a 30-second limit that kills the
|
|
113
|
+
command's whole process group. Treat exit 124 (timeout) as a terminal failure, not as
|
|
114
|
+
"not ready yet".
|
|
115
|
+
- Preserve the stage's original non-zero exit status even when cleanup succeeds. Print
|
|
116
|
+
`original_stage_exit=<n> cleanup_exit=<n>`.
|
|
117
|
+
- After a `SIGKILL` or a host crash, the trap cannot run. Remove only this run's recorded
|
|
118
|
+
PID and container ID by hand, and keep the failure logs.
|
|
119
|
+
- Point the database URL only at the disposable loopback container. Never at development,
|
|
120
|
+
production or another worker's database.
|
|
121
|
+
- Expo may rewrite `android/tsconfig.json` or delete `android/expo-env.d.ts` while it runs.
|
|
122
|
+
Inspect those changes and restore them before you commit.
|
|
123
|
+
|
|
124
|
+
## Triage
|
|
125
|
+
|
|
126
|
+
Name the earliest stage that failed. In CI, that is the first failed step. If the same
|
|
127
|
+
journey passed on another run of the same commit, suspect the run or the journey before
|
|
128
|
+
the product.
|
|
129
|
+
|
|
130
|
+
| Stage | Typical signal |
|
|
131
|
+
| --- | --- |
|
|
132
|
+
| Prerequisites / install | missing SDK directory, wrong JDK, lockfile drift |
|
|
133
|
+
| Harness unit tests (CI, before the APK) | a harness test fails on host state its fixture should fake (`requires 2 GiB reserve`) |
|
|
134
|
+
| Export / APK | Metro bundling error, Gradle compile or dependency-resolution error |
|
|
135
|
+
| Gradle network | Maven download or TLS-handshake errors on a cold build: fix routing, not code |
|
|
136
|
+
| Emulator boot / ADB | `sys.boot_completed` never reaches 1, device offline, exit 124 |
|
|
137
|
+
| Device to Metro | red box, "unable to load script", missing `adb reverse` mapping |
|
|
138
|
+
| Device to Metro, mid-journey | a screen's first Metro asset fails (`Unable to download asset from url: http://127.0.0.1:8081/assets/…`) while API calls still succeed |
|
|
139
|
+
| Backend / Login | backend log errors, verification code not found in the database |
|
|
140
|
+
| Backend tool, CI only | a Backend-backed step gets a 5xx in CI only; the log names a missing program (`Browser was not found at the configured executablePath`) |
|
|
141
|
+
| adb transport, mid-journey | `connection terminated: read failed` in the adb trace after boot, then lost `adb reverse`: usually guest RAM |
|
|
142
|
+
| UiAutomator server | `RemoteDisconnected` while the adb transport stays up: the on-device server was relaunched |
|
|
143
|
+
| Journey harness | a wait right after a navigation times out while the destination is on screen |
|
|
144
|
+
| Journey harness, short screen | a wait for a label times out only on a short or landscape screen, which shows the content above it |
|
|
145
|
+
| Product assertion | a screen or state mismatch with a screenshot |
|
|
146
|
+
|
|
147
|
+
Then match the signal against [references/gotchas.md](references/gotchas.md). If nothing
|
|
148
|
+
matches, [confirm the suspected cause](references/gotchas.md#confirm-a-suspected-cause)
|
|
149
|
+
before changing code.
|
|
150
|
+
|
|
151
|
+
Preserve the failure evidence. Do not blindly replay steps that send codes, verify sessions
|
|
152
|
+
or charge payments just to get a passing screenshot. One passing run does not prove the
|
|
153
|
+
build is reliable.
|
|
154
|
+
|
|
155
|
+
## Feature work
|
|
156
|
+
|
|
157
|
+
- Reuse the workspace's caches, venv and AVD configuration. Rerun a setup stage only when
|
|
158
|
+
the change touches what it proves (toolchain, dependencies, native code, harness).
|
|
159
|
+
- Build the emulator ABI and run `scripts/device-run.sh` once per candidate HEAD.
|
|
160
|
+
- After a failed journey, local or a CI dispatch, reproduce the failing checkpoint off CI
|
|
161
|
+
before you run it again: in the harness unit tests with the fake UI scripted to the
|
|
162
|
+
failing screen, or on the owned emulator. Show the fix passes there, then run the journey
|
|
163
|
+
once to confirm. Never send a guessed fix to CI to see whether it passes; a failure you
|
|
164
|
+
cannot reproduce earns one more run, with added diagnostics, then goes in the report as
|
|
165
|
+
unreproduced.
|
|
166
|
+
- Report the source SHA, the journey command, its `PASS` markers or the failing stage,
|
|
167
|
+
and the cleanup exit. Nothing else: no APK hash, version inventory, screenshots, copied
|
|
168
|
+
logs or earlier attempts.
|
|
169
|
+
- Integrated device acceptance (all ABIs, tablet, TalkBack, physical devices, a release
|
|
170
|
+
device campaign) runs at the release or campaign gate the spec or repo assigns it. Do
|
|
171
|
+
not recreate it per feature. Record it once, as pending, in its owning issue, never as
|
|
172
|
+
passed.
|
|
173
|
+
|
|
174
|
+
## Evidence record
|
|
175
|
+
|
|
176
|
+
For setup proof only. Record:
|
|
177
|
+
|
|
178
|
+
- Source SHA, host OS and architecture, the Expo SDK, and the node, pnpm, JDK, Python and
|
|
179
|
+
emulator versions.
|
|
180
|
+
- System image API, image type and ABI. The AVD name, serial and ports are run
|
|
181
|
+
identifiers, not shared resources.
|
|
182
|
+
- Each stage's exit status and duration.
|
|
183
|
+
- The APK's SHA-256 (`shasum -a 256` or `sha256sum`) and its per-ABI `lib/` entries
|
|
184
|
+
(`unzip -l`), checked on the APK itself rather than inferred from Gradle flags.
|
|
185
|
+
- The journey's `PASS` markers and the cleanup results: database dropped, emulator exited,
|
|
186
|
+
container removed, no listeners left on the backend or Metro ports.
|
|
187
|
+
- Earlier failed or incomplete attempts. A later pass does not erase them.
|
|
188
|
+
|
|
189
|
+
State what the run does not prove: tablet, accessibility (TalkBack), physical devices,
|
|
190
|
+
signing, distribution, and any feature acceptance beyond the journey. Publish only
|
|
191
|
+
sanitized evidence: no authentication codes, session cookies, customer data or raw
|
|
192
|
+
payment payloads.
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Android job for the repo's ci.yml. Merge these pieces into the existing workflow:
|
|
2
|
+
# 1. the `android` filter into the `changes` job (and its output),
|
|
3
|
+
# 2. the `android` job,
|
|
4
|
+
# 3. the `android` lines into `gate`.
|
|
5
|
+
# Replace every <placeholder>. See references/ci.md.
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
changes:
|
|
9
|
+
# ...existing changes job...
|
|
10
|
+
outputs:
|
|
11
|
+
android: ${{ steps.filter.outputs.android }}
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- id: filter
|
|
15
|
+
uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
|
|
16
|
+
with:
|
|
17
|
+
filters: |
|
|
18
|
+
shared: &shared
|
|
19
|
+
- 'package.json'
|
|
20
|
+
- 'pnpm-lock.yaml'
|
|
21
|
+
- '.github/workflows/ci.yml'
|
|
22
|
+
android:
|
|
23
|
+
- *shared
|
|
24
|
+
- '<android-workspace>/**'
|
|
25
|
+
- '<backend-paths-the-journey-drives>/**'
|
|
26
|
+
- '<device-harness-and-journey-scripts>'
|
|
27
|
+
|
|
28
|
+
android:
|
|
29
|
+
name: Android foundation (APK + device journey)
|
|
30
|
+
needs: changes
|
|
31
|
+
# Fork guard: fork code must never reach the self-hosted Android runners.
|
|
32
|
+
if: >-
|
|
33
|
+
needs.changes.outputs.android == 'true' &&
|
|
34
|
+
(github.event_name != 'pull_request' ||
|
|
35
|
+
github.event.pull_request.head.repo.full_name == github.repository)
|
|
36
|
+
runs-on: [<self-hosted-android-runner-labels>]
|
|
37
|
+
timeout-minutes: 60
|
|
38
|
+
services:
|
|
39
|
+
postgres:
|
|
40
|
+
image: postgres:<major>
|
|
41
|
+
env:
|
|
42
|
+
POSTGRES_USER: postgres
|
|
43
|
+
POSTGRES_PASSWORD: postgres
|
|
44
|
+
POSTGRES_DB: <ci-db-name>
|
|
45
|
+
ports: ['5432/tcp']
|
|
46
|
+
options: >-
|
|
47
|
+
--health-cmd "pg_isready -U postgres"
|
|
48
|
+
--health-interval 10s --health-timeout 5s --health-retries 5
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@v4
|
|
51
|
+
with:
|
|
52
|
+
persist-credentials: false
|
|
53
|
+
- uses: actions/setup-node@v4
|
|
54
|
+
with:
|
|
55
|
+
node-version: '<node-major>'
|
|
56
|
+
- uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
|
|
57
|
+
with:
|
|
58
|
+
version: '<pnpm-version>'
|
|
59
|
+
run_install: false
|
|
60
|
+
- uses: actions/setup-java@v4
|
|
61
|
+
with:
|
|
62
|
+
distribution: temurin
|
|
63
|
+
java-version: '17'
|
|
64
|
+
|
|
65
|
+
- name: Preflight Android runner
|
|
66
|
+
run: |
|
|
67
|
+
echo "runner=$RUNNER_NAME nproc=$(nproc)"
|
|
68
|
+
test -c /dev/kvm || { echo "runner has no /dev/kvm device" >&2; exit 1; }
|
|
69
|
+
test -r /dev/kvm
|
|
70
|
+
test -w /dev/kvm
|
|
71
|
+
node -e 'const fs = require("node:fs"); fs.accessSync("/dev/kvm", fs.constants.R_OK | fs.constants.W_OK)'
|
|
72
|
+
for component in platform-tools/adb platforms/android-<api> build-tools/<build-tools> \
|
|
73
|
+
ndk/<ndk> cmake/<cmake> emulator system-images/android-<emulator-api>/<target>/x86_64; do
|
|
74
|
+
test -e "$ANDROID_SDK_ROOT/$component" || { echo "runner image lacks $component" >&2; exit 1; }
|
|
75
|
+
done
|
|
76
|
+
|
|
77
|
+
- name: Allocate per-slot Android ports
|
|
78
|
+
run: |
|
|
79
|
+
if [[ "$RUNNER_NAME" =~ -([0-9]+)$ ]]; then slot=$((10#${BASH_REMATCH[1]})); else
|
|
80
|
+
echo "cannot derive a slot from $RUNNER_NAME" >&2; exit 2; fi
|
|
81
|
+
(( slot >= 1 && slot <= 15 )) || { echo "slot out of range: $slot" >&2; exit 2; }
|
|
82
|
+
emulator_port=$((5554 + 2 * slot))
|
|
83
|
+
{
|
|
84
|
+
echo "ANDROID_ADB_SERVER_PORT=$((5037 + slot))"
|
|
85
|
+
echo "ANDROID_EMULATOR_PORT=$emulator_port"
|
|
86
|
+
echo "ANDROID_EMULATOR_SERIAL=emulator-$emulator_port"
|
|
87
|
+
echo "ANDROID_BACKEND_PORT=$((<backend-base-port> + 10 * slot))"
|
|
88
|
+
echo "ANDROID_METRO_PORT=$((<metro-base-port> + 10 * slot))"
|
|
89
|
+
} | tee -a "$GITHUB_ENV"
|
|
90
|
+
|
|
91
|
+
# Optional: only on runners with a Gradle distribution mirror.
|
|
92
|
+
- name: Route the Gradle wrapper through the mirror
|
|
93
|
+
run: |
|
|
94
|
+
mirror="${GRADLE_DISTRIBUTIONS_MIRROR:?runner must set GRADLE_DISTRIBUTIONS_MIRROR}"
|
|
95
|
+
props=<android-project>/gradle/wrapper/gradle-wrapper.properties
|
|
96
|
+
node -e '
|
|
97
|
+
const fs = require("node:fs")
|
|
98
|
+
const [file, raw] = process.argv.slice(1)
|
|
99
|
+
const mirror = raw.replace(/\/?$/, "/")
|
|
100
|
+
const text = fs.readFileSync(file, "utf8")
|
|
101
|
+
const next = text.replace(
|
|
102
|
+
/^distributionUrl=https\\:\/\/services\.gradle\.org\/distributions\//m,
|
|
103
|
+
"distributionUrl=" + mirror.replace(/:/g, "\\:"),
|
|
104
|
+
)
|
|
105
|
+
if (next === text) throw new Error("distributionUrl was not rewritten")
|
|
106
|
+
fs.writeFileSync(file, next)
|
|
107
|
+
' "$props" "$mirror"
|
|
108
|
+
grep '^distributionUrl=' "$props"
|
|
109
|
+
|
|
110
|
+
- name: Install dependencies
|
|
111
|
+
timeout-minutes: 12
|
|
112
|
+
run: pnpm install --frozen-lockfile
|
|
113
|
+
|
|
114
|
+
- name: Native tests and typecheck
|
|
115
|
+
run: |
|
|
116
|
+
pnpm --filter <android-workspace-package> test
|
|
117
|
+
pnpm --filter <android-workspace-package> typecheck
|
|
118
|
+
|
|
119
|
+
- name: Relax durability on the disposable Postgres
|
|
120
|
+
env:
|
|
121
|
+
PG_CONTAINER: ${{ job.services.postgres.id }}
|
|
122
|
+
run: |
|
|
123
|
+
docker exec "$PG_CONTAINER" psql -U postgres -v ON_ERROR_STOP=1 \
|
|
124
|
+
-c "ALTER SYSTEM SET synchronous_commit = off" -c "ALTER SYSTEM SET fsync = off" \
|
|
125
|
+
-c "SELECT pg_reload_conf()"
|
|
126
|
+
|
|
127
|
+
- name: Native auth against real PostgreSQL
|
|
128
|
+
env:
|
|
129
|
+
DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:${{ job.services.postgres.ports['5432'] }}/<ci-db-name>
|
|
130
|
+
run: <native-auth-integration-test-command>
|
|
131
|
+
|
|
132
|
+
- name: Bundle Android JavaScript
|
|
133
|
+
env:
|
|
134
|
+
EXPO_PUBLIC_API_URL: https://app.invalid
|
|
135
|
+
run: pnpm --filter <android-workspace-package> exec expo export --platform android
|
|
136
|
+
|
|
137
|
+
- name: Build x86_64 debug APK
|
|
138
|
+
timeout-minutes: 30
|
|
139
|
+
env:
|
|
140
|
+
EXPO_PUBLIC_API_URL: https://app.invalid
|
|
141
|
+
ANDROID_USER_HOME: ${{ github.workspace }}/.cache/android-user
|
|
142
|
+
run: |
|
|
143
|
+
mkdir -p "$ANDROID_USER_HOME"
|
|
144
|
+
cpus="$(nproc)"
|
|
145
|
+
if [ -r /sys/fs/cgroup/cpu.max ]; then
|
|
146
|
+
read -r quota period < /sys/fs/cgroup/cpu.max
|
|
147
|
+
if [ "$quota" != max ]; then cpus=$(( (quota + period - 1) / period )); fi
|
|
148
|
+
fi
|
|
149
|
+
echo "gradle max-workers=$cpus (nproc=$(nproc))"
|
|
150
|
+
<android-project>/gradlew --project-dir <android-project> :app:assembleDebug --no-daemon \
|
|
151
|
+
-PreactNativeArchitectures=x86_64 --max-workers="$cpus"
|
|
152
|
+
|
|
153
|
+
- uses: actions/setup-python@v5
|
|
154
|
+
with:
|
|
155
|
+
python-version: '3.12'
|
|
156
|
+
|
|
157
|
+
- name: Test device orchestration
|
|
158
|
+
run: <orchestration-unit-test-commands>
|
|
159
|
+
|
|
160
|
+
- name: Install UI automation
|
|
161
|
+
run: |
|
|
162
|
+
# Create the venv where the journey wrapper looks for it.
|
|
163
|
+
python3 -m venv <venv-dir-the-wrapper-reads>
|
|
164
|
+
<venv-dir-the-wrapper-reads>/bin/python3 -m pip install uiautomator2==<harness-pinned-version>
|
|
165
|
+
|
|
166
|
+
- name: Start the slot's ADB server
|
|
167
|
+
run: |
|
|
168
|
+
adb="$ANDROID_SDK_ROOT/platform-tools/adb"
|
|
169
|
+
"$adb" -P "$ANDROID_ADB_SERVER_PORT" start-server
|
|
170
|
+
"$adb" -P "$ANDROID_ADB_SERVER_PORT" version | head -1
|
|
171
|
+
|
|
172
|
+
- name: Device journey
|
|
173
|
+
uses: reactivecircus/android-emulator-runner@a421e43855164a8197daf9d8d40fe71c6996bb0d # v2.38.0
|
|
174
|
+
env:
|
|
175
|
+
SHARD_ADMIN_URL: postgresql://postgres:postgres@127.0.0.1:${{ job.services.postgres.ports['5432'] }}/postgres
|
|
176
|
+
SHARD_DB_NAME: <ci-db-name>
|
|
177
|
+
with:
|
|
178
|
+
api-level: <emulator-api>
|
|
179
|
+
arch: x86_64
|
|
180
|
+
target: <target>
|
|
181
|
+
disable-animations: true
|
|
182
|
+
enable-hw-keyboard: true
|
|
183
|
+
emulator-port: ${{ env.ANDROID_EMULATOR_PORT }}
|
|
184
|
+
cores: 4
|
|
185
|
+
# At 2 GB (the usual AVD value) the guest kernel's vsock allocations fail and adb drops
|
|
186
|
+
# mid-journey, taking every adb reverse with it (references/gotchas.md).
|
|
187
|
+
ram-size: 4096M
|
|
188
|
+
disable-linux-hw-accel: false
|
|
189
|
+
script: bash <path/to/foundation-journey-wrapper.sh>
|
|
190
|
+
|
|
191
|
+
# The sanitized capture (screenshots, UI dumps, backend and Metro logs; no auth codes,
|
|
192
|
+
# cookies or payment payloads), so a failure is diagnosed from the run, not the runner.
|
|
193
|
+
# <device-capture-dir> must be the directory the journey wrapper actually writes.
|
|
194
|
+
- uses: actions/upload-artifact@v4
|
|
195
|
+
if: always()
|
|
196
|
+
with:
|
|
197
|
+
name: android-device-capture
|
|
198
|
+
path: <device-capture-dir>/
|
|
199
|
+
if-no-files-found: warn
|
|
200
|
+
retention-days: 7
|
|
201
|
+
- uses: actions/upload-artifact@v4
|
|
202
|
+
with:
|
|
203
|
+
name: android-debug-apk
|
|
204
|
+
path: <android-project>/app/build/outputs/apk/debug/*.apk
|
|
205
|
+
if-no-files-found: error
|
|
206
|
+
retention-days: 7
|
|
207
|
+
|
|
208
|
+
gate:
|
|
209
|
+
# ...existing gate job; add:
|
|
210
|
+
needs: [changes, android] # plus the existing jobs
|
|
211
|
+
steps:
|
|
212
|
+
- env:
|
|
213
|
+
ANDROID: ${{ needs.changes.outputs.android }}
|
|
214
|
+
ANDROID_RESULT: ${{ needs.android.result }}
|
|
215
|
+
run: |
|
|
216
|
+
# inside the existing check script:
|
|
217
|
+
check android "$ANDROID_RESULT" "$ANDROID"
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Android CI
|
|
2
|
+
|
|
3
|
+
Add an Android job to the repo's one `ci.yml`: build the debug APK and run the foundation
|
|
4
|
+
journey on an emulator. Copy [assets/android-ci-job.yml](../assets/android-ci-job.yml) and
|
|
5
|
+
fill every `<placeholder>`. Follow the `github-actions` skill for the `changes` job, the
|
|
6
|
+
`gate` job, runner labels, pinning and hardening; this file covers only what is Android-
|
|
7
|
+
specific.
|
|
8
|
+
|
|
9
|
+
## Wire it in
|
|
10
|
+
|
|
11
|
+
1. Add an `android` filter to the `changes` job: the app workspace, the native project,
|
|
12
|
+
the backend code the journey drives, the device harness and journey scripts, the
|
|
13
|
+
lockfile, and `ci.yml`. Leave docs out.
|
|
14
|
+
2. Add the `android` job with `needs: changes` and
|
|
15
|
+
`if: needs.changes.outputs.android == 'true'` plus the fork guard: fork pull requests
|
|
16
|
+
never run on the self-hosted Android runners.
|
|
17
|
+
3. Add `android` to `gate`'s `needs:` and a `check android "$ANDROID_RESULT" "$ANDROID"`
|
|
18
|
+
line. Require only `gate`.
|
|
19
|
+
4. Before merging, open one Android-only PR and one docs-only PR. Confirm the job runs on
|
|
20
|
+
the first, is skipped on the second, and `gate` passes on both.
|
|
21
|
+
|
|
22
|
+
## Runner
|
|
23
|
+
|
|
24
|
+
- Run on a self-hosted Linux x64 runner class that has `/dev/kvm` mapped in and the SDK
|
|
25
|
+
preinstalled: platform-tools, the platform, build-tools, NDK, CMake, emulator and the
|
|
26
|
+
x86_64 system image the job boots. Never download SDK components in the job.
|
|
27
|
+
- Preflight before any slow step: assert `/dev/kvm` is a character device, readable and
|
|
28
|
+
writable, and check it with Node's `fs.accessSync(R_OK | W_OK)`. The emulator action uses
|
|
29
|
+
that check; a host where `test -r/-w` passes but `accessSync` fails boots the emulator in
|
|
30
|
+
software for 10+ minutes. Assert each SDK component path exists.
|
|
31
|
+
- Never let the emulator fall back to software: set `disable-linux-hw-accel: false`.
|
|
32
|
+
- Derive per-slot ports from the runner's slot number when slots share a host network:
|
|
33
|
+
ADB server, emulator console (even port, 5554–5584), backend and Metro. Export them to
|
|
34
|
+
`$GITHUB_ENV` and start the ADB server on its own port.
|
|
35
|
+
- Size Gradle from the cgroup CPU quota (`/sys/fs/cgroup/cpu.max`), not `nproc`. `nproc`
|
|
36
|
+
reports every host core and thrashes the native build.
|
|
37
|
+
- Route the Gradle wrapper distribution and Maven repositories through the runner's
|
|
38
|
+
dependency proxy when it has one. Fail when the proxy variable is missing; never fall
|
|
39
|
+
back to direct downloads.
|
|
40
|
+
|
|
41
|
+
## Build
|
|
42
|
+
|
|
43
|
+
- Build `x86_64` only (`-PreactNativeArchitectures=x86_64`), with `--no-daemon`. Report
|
|
44
|
+
this APK as emulator evidence only. The all-ABI build stays a local or release step.
|
|
45
|
+
- Bundle the JavaScript with `expo export --platform android` before the native build so
|
|
46
|
+
bundling errors fail fast.
|
|
47
|
+
- Give the job `timeout-minutes: 60`, the install step its own short timeout, and the
|
|
48
|
+
APK build `timeout-minutes: 30`.
|
|
49
|
+
|
|
50
|
+
## Database and journey
|
|
51
|
+
|
|
52
|
+
- Run PostgreSQL as a job service on a random host port, with a health check. Turn off
|
|
53
|
+
`fsync` and `synchronous_commit` on it: the database is disposable.
|
|
54
|
+
- Run the native auth/integration tests against that service before the device journey.
|
|
55
|
+
- Unit-test the device orchestration scripts (journey wrapper, slot allocator, code
|
|
56
|
+
lookup) before booting the emulator.
|
|
57
|
+
- Pin the UI automation package in a venv at the path the journey wrapper reads; use the
|
|
58
|
+
Python version the harness supports (3.12 on CI).
|
|
59
|
+
- Boot the emulator with the SHA-pinned `reactivecircus/android-emulator-runner`, or the
|
|
60
|
+
runner's preinstalled emulator under an owned process group. Use the API level, target
|
|
61
|
+
and ABI of the preinstalled image, `disable-animations: true`, `ram-size: 4096M` (or
|
|
62
|
+
`-memory 4096` when launching the emulator directly), and the slot's console port. Run
|
|
63
|
+
the journey wrapper as its `script`. At 2 GB, the usual `avdmanager` value, adb drops
|
|
64
|
+
mid-journey
|
|
65
|
+
([gotchas](gotchas.md#the-adb-transport-drops-mid-journey)).
|
|
66
|
+
|
|
67
|
+
## Evidence
|
|
68
|
+
|
|
69
|
+
- Upload the sanitized device capture (screenshots, UI dumps, backend and Metro logs) with
|
|
70
|
+
`if: always()` and a 7-day retention, from the directory the journey wrapper actually
|
|
71
|
+
writes. Sanitize before upload: no authentication codes, session cookies, customer data or
|
|
72
|
+
payment payloads. Diagnose a CI failure from this artifact; never require runner access.
|
|
73
|
+
- Print enough to name the cause from the log alone: the message of the wait that timed
|
|
74
|
+
out (not only its exception class), the screen size and orientation, the labels on screen
|
|
75
|
+
and whether it scrolls, and the runner's free disk at preflight. A repo that uploads no
|
|
76
|
+
capture needs these in the log.
|
|
77
|
+
- Upload the APK with `if-no-files-found: error`.
|
|
78
|
+
- Treat one green run as one run. Fix flaky device failures at their cause instead of
|
|
79
|
+
rerunning, and do not change product code for them. An adb drop after boot means guest
|
|
80
|
+
RAM ([gotchas](gotchas.md#the-adb-transport-drops-mid-journey)). A `RemoteDisconnected`
|
|
81
|
+
with the adb transport still up means the uiautomator2 server was relaunched
|
|
82
|
+
([gotchas](gotchas.md#remotedisconnected-right-after-a-new-process-connects)).
|
|
83
|
+
|
|
84
|
+
## Traps
|
|
85
|
+
|
|
86
|
+
Known CI symptoms and their fixes are in [gotchas.md](gotchas.md#ci-runners), along with
|
|
87
|
+
the emulator and adb traps that also hit CI.
|