@1aboveio/skills 0.0.0-stage → 1.0.1
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 +207 -0
- package/skills/app-dev/data-catalog/agents/openai.yaml +3 -0
- package/skills/app-dev/data-catalog/references/data-catalog-conventions.md +76 -0
- package/skills/app-dev/data-catalog/references/field-definitions.md +123 -0
- package/skills/app-dev/data-catalog/references/format.md +130 -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 +1435 -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 +603 -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,87 @@
|
|
|
1
|
+
# Pipeline, lanes, and the required check
|
|
2
|
+
|
|
3
|
+
> Read when: setting up CI in a new repo, choosing a merge queue, or a check is missing, stuck
|
|
4
|
+
> "expected", or skipped.
|
|
5
|
+
|
|
6
|
+
## Lanes
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
PR (non-draft) ──► PR lane: change-scoped checks ──► gate
|
|
10
|
+
│
|
|
11
|
+
[optional merge queue: Mergify, GitHub merge_group, or none]
|
|
12
|
+
▼
|
|
13
|
+
Queue candidate ──► queue lane: merged result + slow suites ──► gate
|
|
14
|
+
▼
|
|
15
|
+
merge to main ────► Cloud Build: build → push by digest → migrate (if changed) → deploy dev
|
|
16
|
+
▼
|
|
17
|
+
post-deploy lane (Actions): wait for Cloud Build's check on this SHA →
|
|
18
|
+
confirm the serving revision is this SHA → smoke/e2e → status + incident issue
|
|
19
|
+
▼
|
|
20
|
+
rc tag ───────────► Cloud Build: prod candidate at 0% traffic ──► rush-release verifies, shifts traffic
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
- **PR lane:** prove the change. Mergify admission < 2 min; no queue < 7 min (excluding E2E).
|
|
24
|
+
- **Queue lane:** prove the merged result; run slow suites here. Mergify queue < 5 min
|
|
25
|
+
(excluding E2E). Without a queue, run slow suites on the PR and require an up-to-date branch.
|
|
26
|
+
- **No main test lane with a queue:** the queue already tested the tree that lands on `main`;
|
|
27
|
+
a merge to `main` triggers deploy, not a CI rerun. Without a queue, `push: main` tests it.
|
|
28
|
+
- **Post-deploy lane:** test the deployed revision, never a local build.
|
|
29
|
+
→ [post-deploy-and-publishing.md](post-deploy-and-publishing.md)
|
|
30
|
+
- **Scheduled lanes:** alert on failure (issue or chat ping).
|
|
31
|
+
|
|
32
|
+
## Merge queue: optional, pick one
|
|
33
|
+
|
|
34
|
+
| Option | When | Wire |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| **None** | Low PR volume, one author | Require `gate` + "require branch up to date". |
|
|
37
|
+
| **Mergify** (most repos) | Batching, scopes, priorities | Candidates are draft PRs on `mergify/merge-queue/*` via `pull_request`. Let them through: `if: ${{ !github.event.pull_request.draft \|\| startsWith(github.head_ref, 'mergify/merge-queue/') }}`. Config: `mergify` skill. |
|
|
38
|
+
| **GitHub native** | No third-party app | Add `on: merge_group:` to every workflow that reports `gate`. |
|
|
39
|
+
|
|
40
|
+
Queue-only jobs: `if: startsWith(github.head_ref, 'mergify/merge-queue/')` (Mergify) or
|
|
41
|
+
`if: github.event_name == 'merge_group'` (native). Make `gate` lane-aware.
|
|
42
|
+
|
|
43
|
+
## The one required check
|
|
44
|
+
|
|
45
|
+
Require exactly one check, `gate`, in branch protection and the queue. Template:
|
|
46
|
+
[conditional-ci.md](conditional-ci.md#template).
|
|
47
|
+
|
|
48
|
+
1. Put no `paths:` / `paths-ignore:` on a workflow that reports `gate`. Filter inside a
|
|
49
|
+
`changes` job.
|
|
50
|
+
2. Give `gate` `if: always()` and `needs:` every job it covers.
|
|
51
|
+
3. Skip area jobs, never `gate`. Allow a skip only for a named job whose condition was false;
|
|
52
|
+
fail on a skip caused by anything else (a missing secret, a failed dependency).
|
|
53
|
+
4. Keep the name stable. Rename `gate` only together with the queue and branch-protection config.
|
|
54
|
+
5. Put matrix and sharded jobs behind `gate`; never require a leg by name.
|
|
55
|
+
|
|
56
|
+
## Workflow layout
|
|
57
|
+
|
|
58
|
+
- Keep one `ci.yml` with the PR and queue lanes. Split files only by trigger:
|
|
59
|
+
`post-deploy.yml`, `nightly.yml`, `security.yml`, `publish.yml`.
|
|
60
|
+
- Move repeated setup (install, Postgres start, workspace reset, container cleanup) into a
|
|
61
|
+
local composite action, `.github/actions/<name>/action.yml`.
|
|
62
|
+
- Share across repos with a reusable workflow (`on: workflow_call`), called by a pinned ref,
|
|
63
|
+
never `@main`, with named secrets, never `secrets: inherit`.
|
|
64
|
+
- Add `workflow_dispatch` where a manual re-run may be needed; guard it ([security.md](security.md)).
|
|
65
|
+
|
|
66
|
+
## AI review jobs
|
|
67
|
+
|
|
68
|
+
- Use a review bot to inform a merge, never as the only gate.
|
|
69
|
+
- Never auto-pass a review gate on timeout.
|
|
70
|
+
- Keep the trigger in one reusable workflow, not copied per repo.
|
|
71
|
+
|
|
72
|
+
## New-workflow checklist
|
|
73
|
+
|
|
74
|
+
- [ ] `permissions:` at top, `contents: read`
|
|
75
|
+
- [ ] Every job has `timeout-minutes`
|
|
76
|
+
- [ ] `concurrency` set; cancels only on PRs
|
|
77
|
+
- [ ] No `paths:` on a workflow that reports `gate`
|
|
78
|
+
- [ ] One `gate` job with `if: always()`; it is the only required check
|
|
79
|
+
- [ ] Area jobs gate on `changes` outputs; `gate` allows a skip only when that filter was false
|
|
80
|
+
- [ ] Non-E2E timings meet the SLA (Mergify admission < 2 min, queue < 5 min; else PR CI < 7 min)
|
|
81
|
+
- [ ] Queue trigger handled (Mergify draft prefix or `merge_group`), if the repo uses a queue
|
|
82
|
+
- [ ] Self-hosted: fork guard, canonical labels, `persist-credentials: false`, dynamic service ports
|
|
83
|
+
- [ ] Third-party actions SHA-pinned (at least in jobs with secrets or `id-token`)
|
|
84
|
+
- [ ] No `${{ }}` inside `run:`/`script:`; inputs go through `env:`
|
|
85
|
+
- [ ] Missing secrets fail; no `continue-on-error` on tests
|
|
86
|
+
- [ ] Schedules alert on failure
|
|
87
|
+
- [ ] `actionlint` clean
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Post-deploy verification and publishing
|
|
2
|
+
|
|
3
|
+
> Read when: wiring tests that run after Cloud Build deploys, or a workflow that publishes a package.
|
|
4
|
+
|
|
5
|
+
## Post-deploy verification
|
|
6
|
+
|
|
7
|
+
After Cloud Build deploys dev, Actions verifies. There are two ways to start it.
|
|
8
|
+
|
|
9
|
+
- **Preferred: poll Cloud Build's check run for the exact SHA** from a job triggered by
|
|
10
|
+
`push: main`. Don't rely on the `check_run` event: GitHub suppresses it for SHAs that
|
|
11
|
+
Actions already runs on. No Cloud Build → GitHub token needed.
|
|
12
|
+
- **Alternative: `repository_dispatch`** from Cloud Build. The `event_type` must match
|
|
13
|
+
`on.repository_dispatch.types` exactly. Two repos send one name and listen for another.
|
|
14
|
+
A dispatch failure in Cloud Build must fail loudly, not `|| true`.
|
|
15
|
+
|
|
16
|
+
Then:
|
|
17
|
+
|
|
18
|
+
1. **Correlate.** Confirm the serving revision reports this commit (`/health` returns the SHA,
|
|
19
|
+
or the revision's env). Re-check after the tests; a newer deploy may have landed.
|
|
20
|
+
2. **Target from an allowlist** keyed by environment name, never a URL from the payload.
|
|
21
|
+
3. **One verdict step** that rolls up every step outcome. Never `continue-on-error` on the
|
|
22
|
+
tests themselves.
|
|
23
|
+
4. **Report**: a commit status (`dev-post-deploy`), plus a deduplicated incident issue that
|
|
24
|
+
auto-closes on the next green run, plus a chat ping.
|
|
25
|
+
5. **No concurrency cancellation** on this lane.
|
|
26
|
+
|
|
27
|
+
## Publishing
|
|
28
|
+
|
|
29
|
+
npm packages: trusted publishing (OIDC, no token): `environment: npm-publish`,
|
|
30
|
+
`permissions: id-token: write`, the full verify suite first, an idempotency check (version
|
|
31
|
+
already published? then assert its provenance matches this commit), a pack-contents check,
|
|
32
|
+
publish, poll the registry until visible, then create the tag and release idempotently.
|
|
33
|
+
Restrict to the default branch; pin the npm version; keep `contents: write` off the install step.
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# Runners
|
|
2
|
+
|
|
3
|
+
> Read when: adding or moving a job onto the self-hosted fleet, writing a job that starts its own
|
|
4
|
+
> containers, a host process that needs a browser, or a job is queued and never starts. Source of truth for the fleet itself: the
|
|
5
|
+
> `github-runner` repo (its README and `AGENTS.md`); change the fleet there, not in a workflow.
|
|
6
|
+
|
|
7
|
+
## What a job actually gets
|
|
8
|
+
|
|
9
|
+
Know this model before writing a step; most self-hosted failures come from assuming a
|
|
10
|
+
GitHub-hosted VM.
|
|
11
|
+
|
|
12
|
+
Fleet snapshot checked 2026-10-07: [runner README at 81f5dbd](https://github.com/1aboveio/github-runner/blob/81f5dbdd39da49b17addd7fd8f355257bc430224/README.md).
|
|
13
|
+
Re-read the fleet contract and actual quota before tuning; these are defaults, not
|
|
14
|
+
permission for a job to consume more than its assigned slot.
|
|
15
|
+
|
|
16
|
+
| Property | Fleet | Consequence for the workflow |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| Runner | the official `actions-runner` image in a rootless Podman container, **ephemeral**: replaced after every job | no tool state carries between jobs; install what you need per job |
|
|
19
|
+
| Workspace (`_work`) | **bind-mounted host disk, reused across jobs** | a fresh runner is not a fresh workspace: stale checkouts, `node_modules`, build output and git lock files can be there |
|
|
20
|
+
| Size | configured default 8 CPUs / 16 GiB per slot, several slots per host | verify actual quotas; bound workers below the allotment and measure throttling/memory |
|
|
21
|
+
| Network | host networking; all slots on a host share it | fixed ports collide between concurrent jobs |
|
|
22
|
+
| `docker` | the host's rootless Podman API through `DOCKER_HOST` | `docker run`, `docker build` and `services:` work; native `container:` jobs do not reliably (below) |
|
|
23
|
+
| Browsers | none in the runner image | Playwright runs in its own image; a host process gets a [wrapper](#a-host-process-that-needs-a-browser-binary) |
|
|
24
|
+
| Package installs | npm, PyPI/uv index, Prisma engines and Docker Hub pulls go through LAN caches the runner injects; `uv sync --frozen` bypasses them | don't set registry env in workflows; install uv projects with `python-backend`'s `uv-install.sh` |
|
|
25
|
+
| Capacity | one small pool shared by every repo in the org | every parallel job holds a slot another PR is waiting for |
|
|
26
|
+
|
|
27
|
+
## Placement and labels
|
|
28
|
+
|
|
29
|
+
Every slot carries `self-hosted, linux, x64, host, docker`; the fast host's slots add
|
|
30
|
+
`premium`, the others add `general`.
|
|
31
|
+
|
|
32
|
+
| Job | `runs-on` |
|
|
33
|
+
|---|---|
|
|
34
|
+
| Default (tests, builds, Postgres, Playwright) | `[self-hosted, linux, x64, docker]` |
|
|
35
|
+
| Heavy or timing-sensitive (Spark, timing baselines) | `[self-hosted, linux, x64, docker, premium]` |
|
|
36
|
+
| Needs Windows/macOS, or public/fork-facing | `ubuntu-latest` / `windows-latest` / `macos-latest` |
|
|
37
|
+
|
|
38
|
+
- Spell labels lowercase, in this order, everywhere. A label no slot carries (a typo, a
|
|
39
|
+
retired per-host or per-slot label) queues the job forever, silently.
|
|
40
|
+
- Target a class of runner, never a named slot or host. Slots are replaced constantly.
|
|
41
|
+
- Ask for `premium` only when the job measurably needs it; it is the scarcest class.
|
|
42
|
+
|
|
43
|
+
## Workspace: reused, so clean it
|
|
44
|
+
|
|
45
|
+
- **Fork guard on every job**, before a runner is allocated. Fork code must never reach
|
|
46
|
+
our hosts:
|
|
47
|
+
`if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository`
|
|
48
|
+
- **Wipe the workspace as the first step** when a job must not see a previous job's files
|
|
49
|
+
(anything that builds, installs, or globs the tree):
|
|
50
|
+
`ws="${GITHUB_WORKSPACE:?}"; find "$ws" -mindepth 1 -maxdepth 1 -exec rm -rf {} +`.
|
|
51
|
+
- **Checkout with `persist-credentials: false`**; the token must not stay in `.git/config`
|
|
52
|
+
on a disk the next job reads.
|
|
53
|
+
- Never write secrets, `.env` files or credentials files into the workspace; if a tool
|
|
54
|
+
insists, delete them in an `if: always()` step.
|
|
55
|
+
- A checkout failing on `index.lock` or a `refs/*.lock` is a job killed mid-git on that
|
|
56
|
+
slot. The runner clears locks older than five minutes when it starts; a repeat is a
|
|
57
|
+
fleet bug to report, not a reason to add `rm .git/*.lock` to workflows.
|
|
58
|
+
|
|
59
|
+
## Services and networking
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
services:
|
|
63
|
+
postgres:
|
|
64
|
+
image: postgres:17
|
|
65
|
+
env: { POSTGRES_USER: test, POSTGRES_PASSWORD: test, POSTGRES_DB: app }
|
|
66
|
+
ports: ['5432/tcp'] # dynamic host port; never '5432:5432'
|
|
67
|
+
options: >-
|
|
68
|
+
--tmpfs /var/lib/postgresql/data:rw,noexec,nosuid,size=1g
|
|
69
|
+
--health-cmd pg_isready --health-interval 2s --health-timeout 5s --health-retries 25
|
|
70
|
+
env:
|
|
71
|
+
DATABASE_URL: postgresql://test:test@127.0.0.1:${{ job.services.postgres.ports['5432'] }}/app
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
- **Dynamic ports only**, reached at `127.0.0.1` plus `job.services.<name>.ports[...]`.
|
|
76
|
+
Concurrent jobs on one host share its network, so a fixed port works in isolation and
|
|
77
|
+
fails under load.
|
|
78
|
+
- **Give every service a health check** so steps start after it is ready. Poll every
|
|
79
|
+
1–2 s and raise the retries to keep the total timeout; a 10 s interval idles each job
|
|
80
|
+
for up to one interval after the service is ready.
|
|
81
|
+
- **Put disposable databases on tmpfs, with a size.** Every slot on a host shares its
|
|
82
|
+
disks, so an on-disk scratch Postgres contends with every other job's I/O (slow
|
|
83
|
+
start, readiness probes timing out). tmpfs takes it off the disk: start-up went
|
|
84
|
+
13.5 s → 1.8 s ([case study](ci-case-studies.md)). Always set `size=`: tmpfs memory
|
|
85
|
+
comes from the slot budget, and an unbounded one can grow until the host swaps.
|
|
86
|
+
Example: `--tmpfs /var/lib/postgresql/data:rw,noexec,nosuid,size=1g` (raise it only
|
|
87
|
+
for a large seed). Same flag for `docker run`. The path is the image's `PGDATA`:
|
|
88
|
+
`postgres:18` and later use `/var/lib/postgresql`; a tmpfs on the old path leaves
|
|
89
|
+
the data on an anonymous disk volume.
|
|
90
|
+
- **Keep durability on unless measured.** Disabling `fsync`, `synchronous_commit` and
|
|
91
|
+
`full_page_writes` is optional, only for disposable tests not proving
|
|
92
|
+
persistence/recovery, and only when measurement supports it; on tmpfs it added
|
|
93
|
+
no start-up benefit. The baseline above retains default durability. For an explicitly measured exception,
|
|
94
|
+
`services:` takes no server flags; use `ALTER SYSTEM` + reload, or pass
|
|
95
|
+
`-c fsync=off -c synchronous_commit=off -c full_page_writes=off` to `docker run`.
|
|
96
|
+
- Don't depend on runner-specific names (`host.containers.internal`, a host's name, a
|
|
97
|
+
regional mirror). They differ per host and do not exist on GitHub-hosted runners.
|
|
98
|
+
|
|
99
|
+
## Containers the job starts itself
|
|
100
|
+
|
|
101
|
+
Native `container:` jobs make the runner auto-mount `/var/run/docker.sock` into the job
|
|
102
|
+
container, which fails on this fleet before checkout
|
|
103
|
+
(`statfs /var/run/docker.sock: permission denied`). Treat them as unsupported here; they
|
|
104
|
+
remain fine on GitHub-hosted runners. Instead keep the job on the runner and `docker run`
|
|
105
|
+
the tool image:
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
- name: E2E in the Playwright image
|
|
109
|
+
run: |
|
|
110
|
+
docker run --name "e2e-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${GITHUB_JOB}" --rm \
|
|
111
|
+
--network host --ipc=host --cpus 8 --memory 16g \
|
|
112
|
+
-e CI=true -e E2E_WORKERS=4 -e DATABASE_URL \
|
|
113
|
+
-v "${GITHUB_WORKSPACE}:/work:z" -w /work \
|
|
114
|
+
"${PLAYWRIGHT_IMAGE}" \
|
|
115
|
+
bash -lc 'npm ci && timeout 20m npx playwright test'
|
|
116
|
+
- name: Remove the E2E container
|
|
117
|
+
if: always()
|
|
118
|
+
run: docker rm -f "e2e-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${GITHUB_JOB}" 2>/dev/null || true
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
- **`--rm` is not cleanup.** It fires only when the container exits; a hung container never
|
|
122
|
+
exits and keeps a CPU busy after the job is cancelled (found on the fleet: two leaked
|
|
123
|
+
containers at ~100% CPU for 12 and 15 days). Name every container uniquely per run and
|
|
124
|
+
remove it in an `if: always()` step.
|
|
125
|
+
- **Bound the command inside the container** (`timeout 20m …` in the container command),
|
|
126
|
+
never by wrapping the client (`timeout 20m docker run …`): killing the client detaches
|
|
127
|
+
the container, which then outlives the job.
|
|
128
|
+
- **Stay inside the measured slot**: the current configured default is
|
|
129
|
+
`--cpus 8 --memory 16g`; use a lower cap when assigned one. Start Playwright at
|
|
130
|
+
`E2E_WORKERS=4`, not eight merely because eight CPUs are available, and drop to
|
|
131
|
+
`2` for a memory-heavy app. See [ci-case-studies.md](ci-case-studies.md) for why
|
|
132
|
+
worker increases need before/after evidence.
|
|
133
|
+
- `--network host` so the container reaches `services:` at the same `127.0.0.1` port;
|
|
134
|
+
`:z` on the workspace mount for SELinux.
|
|
135
|
+
- The fleet reaps CI containers older than about two hours. Keep every job well under that.
|
|
136
|
+
- Playwright image and version matching: `e2e-test`'s `ci-playwright-container.md`.
|
|
137
|
+
|
|
138
|
+
### A host process that needs a browser binary
|
|
139
|
+
|
|
140
|
+
Sometimes the browser is launched by something that must stay on the runner: the app's own
|
|
141
|
+
Backend rendering PDFs with Puppeteer (`executablePath`), started by an emulator or device
|
|
142
|
+
harness that cannot move into a container. The runner has no browser, so the launch fails
|
|
143
|
+
with "Browser was not found at the configured executablePath" (or missing `libnss3`/
|
|
144
|
+
`libnspr4` if a binary is copied out of an image). Don't install Chromium on the runner,
|
|
145
|
+
and don't copy the binary out of the image. Give the process a wrapper that runs the
|
|
146
|
+
Playwright image's browser, and point the browser path variable at it:
|
|
147
|
+
|
|
148
|
+
```yaml
|
|
149
|
+
- name: Prepare host browser wrapper
|
|
150
|
+
id: host-browser
|
|
151
|
+
run: |
|
|
152
|
+
set -euo pipefail
|
|
153
|
+
# The image's own browser path, resolved by the repo's installed @playwright/test.
|
|
154
|
+
chrome=$(docker run --rm --pull=never --user "$(id -u):$(id -g)" \
|
|
155
|
+
-v "$PWD:/work:ro" -w /work "$PLAYWRIGHT_IMAGE" \
|
|
156
|
+
node -e 'process.stdout.write(require("/work/node_modules/@playwright/test").chromium.executablePath())')
|
|
157
|
+
case "$chrome" in /*) ;; *) echo "unresolved image browser: $chrome" >&2; exit 1 ;; esac
|
|
158
|
+
umask 077
|
|
159
|
+
dir=$(mktemp -d "$RUNNER_TEMP/host-browser.XXXXXXXX")
|
|
160
|
+
label="host-browser=${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
|
|
161
|
+
{
|
|
162
|
+
printf '#!/usr/bin/env bash\nset -euo pipefail\n'
|
|
163
|
+
printf 'case "${TMPDIR:-}" in /*) ;; *) echo "needs an absolute TMPDIR" >&2; exit 1 ;; esac\n'
|
|
164
|
+
printf 'exec docker run --rm --init --pull=never --label %q --user %q --network host --ipc=host -e HOME="$TMPDIR" -v "$TMPDIR:$TMPDIR" %q %q "$@"\n' \
|
|
165
|
+
"$label" "$(id -u):$(id -g)" "$PLAYWRIGHT_IMAGE" "$chrome"
|
|
166
|
+
} > "$dir/chromium"
|
|
167
|
+
chmod 700 "$dir/chromium"
|
|
168
|
+
printf 'path=%s\nlabel=%s\n' "$dir/chromium" "$label" >> "$GITHUB_OUTPUT"
|
|
169
|
+
- name: Journey
|
|
170
|
+
env:
|
|
171
|
+
CHROMIUM_PATH: ${{ steps.host-browser.outputs.path }}
|
|
172
|
+
TMPDIR: ${{ runner.temp }}/journey-tmp # private, absolute; the wrapper shares only this
|
|
173
|
+
run: |
|
|
174
|
+
mkdir -m 700 -p "$TMPDIR" # Puppeteer's mkdtemp fails on a missing TMPDIR
|
|
175
|
+
./run-journey
|
|
176
|
+
- name: Remove host browser containers
|
|
177
|
+
if: always() && steps.host-browser.outputs.label != ''
|
|
178
|
+
env:
|
|
179
|
+
LABEL: ${{ steps.host-browser.outputs.label }}
|
|
180
|
+
run: docker ps -aq --filter "label=$LABEL" | xargs -r docker rm -f
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
- **Why it works:** Puppeteer starts the "binary" (the wrapper), reads Chrome's
|
|
184
|
+
`DevTools listening on ws://127.0.0.1:<port>` line from stderr, and connects. With
|
|
185
|
+
`--network host` that port is the runner's loopback. Puppeteer keeps the profile in
|
|
186
|
+
`$TMPDIR`, so mounting that same path into the container at the same location is all
|
|
187
|
+
the host the browser sees. `--user` keeps the profile files owned by the runner user.
|
|
188
|
+
- **Same version as the tests:** resolve the path through the repo's `@playwright/test`
|
|
189
|
+
inside the pinned image, the same way an in-container test would. A mismatch fails as
|
|
190
|
+
"not found", never silently.
|
|
191
|
+
- **One label per run, cleaned in `always()`.** A normal `browser.close()` exits Chrome
|
|
192
|
+
and the container. A force-killed launch only kills the `docker` client and leaves
|
|
193
|
+
the container running, which is the `--rm`-is-not-cleanup trap above. You can't trap
|
|
194
|
+
SIGKILL in the wrapper, so remove containers by label after the step instead.
|
|
195
|
+
- **Linux runners only.** On Docker Desktop (macOS), `--network host` does not reach the
|
|
196
|
+
Mac's loopback. Locally, Chrome starts and prints its endpoint, but the connection is
|
|
197
|
+
refused. Prove the wrapper in CI.
|
|
198
|
+
- Use this for a process that has to stay on the host. When the whole tool can run in the
|
|
199
|
+
image (the test runner, a CLI check), put it in the image instead (above).
|
|
200
|
+
|
|
201
|
+
## Resources, capacity and time
|
|
202
|
+
|
|
203
|
+
- **Every job has `timeout-minutes`** sized to its lane; the fleet's longest planned
|
|
204
|
+
budget is a 35-minute browser lane. Self-hosted jobs do not get GitHub-hosted runners'
|
|
205
|
+
six-hour cap, so a hung step with no timeout holds a shared slot for hours to days
|
|
206
|
+
(jobs have been seen cancelled only after 24 hours).
|
|
207
|
+
- **Parallel jobs cost the org, not just the PR.** The pool is shared; fanning one PR into
|
|
208
|
+
eight small jobs takes eight slots. Fold short static checks into one job (one checkout,
|
|
209
|
+
one install), and shard only where the wall-clock gain is real. `ci-run-audit.mjs` shows
|
|
210
|
+
both the setup share and the queue wait.
|
|
211
|
+
- `concurrency: cancel-in-progress` on PR workflows frees slots from superseded pushes.
|
|
212
|
+
|
|
213
|
+
## Packages and caches
|
|
214
|
+
|
|
215
|
+
- The runner injects the npm, PyPI/uv and Prisma mirror settings, and Docker Hub pulls go
|
|
216
|
+
through a pull-through proxy. **Don't set `NPM_CONFIG_REGISTRY`, `PIP_INDEX_URL`,
|
|
217
|
+
`UV_DEFAULT_INDEX` or mirror hosts in workflows**: they break the same workflow on
|
|
218
|
+
GitHub-hosted runners and drift when the fleet changes.
|
|
219
|
+
- **uv lockfile installs do not use that proxy on their own.** `uv sync --frozen` fetches
|
|
220
|
+
every package from the URL in `uv.lock` (`files.pythonhosted.org`) and ignores
|
|
221
|
+
`UV_DEFAULT_INDEX`. Install with the export + `uv pip sync --require-hashes` script from
|
|
222
|
+
`python-backend` (`assets/uv-install.sh`), then `uv run --no-sync`. Its
|
|
223
|
+
`references/uv-installs.md` also covers per-slot uv caches, toolcache vs uv-managed
|
|
224
|
+
Python, and trimming heavy packages.
|
|
225
|
+
- Prefer the runner-local pnpm store over `actions/cache`; a network restore can cost more
|
|
226
|
+
than a cold install from the LAN mirror. Measure before adding a cache. uv's default
|
|
227
|
+
cache is in the ephemeral runner home, so it starts cold every job: point
|
|
228
|
+
`UV_CACHE_DIR` at the reused `_work` disk instead (`python-backend`'s
|
|
229
|
+
`references/uv-installs.md`).
|
|
230
|
+
- Persist framework build caches (`.next/cache` and similar) the same way: in the
|
|
231
|
+
slot-local tool cache on the reused disk, one directory per lane, restored into the
|
|
232
|
+
checkout before the build. A fresh checkout otherwise rebuilds from cold every job.
|
|
233
|
+
- Pin `postgres:17`, the Playwright tag and other images to a version, never `latest`,
|
|
234
|
+
so every slot runs the same thing and a bump is a reviewed one-line change.
|
|
235
|
+
- `pnpm/action-setup` failing with `self-installer exits with code 1` before repo code runs
|
|
236
|
+
is a runner store-dir problem, not the repo's. Report it to the fleet.
|
|
237
|
+
|
|
238
|
+
## When a job misbehaves
|
|
239
|
+
|
|
240
|
+
| Symptom | Likely cause | Check |
|
|
241
|
+
|---|---|---|
|
|
242
|
+
| Queued, never starts | no online slot matches the label set, or every slot is busy | `gh api orgs/<org>/actions/runners --jq '.runners[] \| "\(.name) \(.status) \([.labels[].name] \| join(","))"'` |
|
|
243
|
+
| Fewer slots online than usual | a host drained itself (its work disk went read-only) or the runner service is down | the fleet repo's health log; nothing to fix in the workflow |
|
|
244
|
+
| Checkout fails on a `.lock` file | a previous job was killed mid-git on that slot | rerun once; report repeats |
|
|
245
|
+
| `statfs /var/run/docker.sock: permission denied` | native `container:` job | switch to `docker run` (above) |
|
|
246
|
+
| Service unreachable | fixed port, `localhost` name resolution, or no health check | dynamic port + `127.0.0.1` + `--health-cmd` |
|
|
247
|
+
| `libnspr4.so` / missing browser libraries | Playwright running on the runner image | run it in the Playwright image |
|
|
248
|
+
| `Browser was not found at the configured executablePath` | a host process (Puppeteer in the app's Backend) launches a browser the runner lacks | [host browser wrapper](#a-host-process-that-needs-a-browser-binary) |
|
|
249
|
+
| Job fails only on one host | host drift (image, package or network helper versions) | note the runner name from the job log and report it with the run URL |
|
|
250
|
+
|
|
251
|
+
Fleet problems (labels, lock files, stores, networking, capacity) are fixed in the
|
|
252
|
+
`github-runner` repo and rolled to every host. A workflow that works around one hides it
|
|
253
|
+
from every other repo.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Workflow security
|
|
2
|
+
|
|
3
|
+
> Read when: writing or reviewing any workflow that holds secrets, writes, or runs on PR input.
|
|
4
|
+
|
|
5
|
+
1. **`permissions:` at the top of every workflow**, `contents: read`; widen per job only
|
|
6
|
+
(`id-token: write` for OIDC, `issues: write` for an alert job, `statuses: write` for a
|
|
7
|
+
post-deploy verdict). A workflow with no block gets the repo default, often write-all.
|
|
8
|
+
2. **Pin third-party actions to a full commit SHA** with the tag in a comment:
|
|
9
|
+
`uses: google-github-actions/auth@<40-hex sha> # v2.1.7`. Mandatory for any action in a job
|
|
10
|
+
holding secrets or `id-token: write`. Pair with Dependabot/Renovate for `github-actions` so
|
|
11
|
+
pins get updated (no repo has either today).
|
|
12
|
+
3. **Never paste `${{ }}` into `run:` or `script:`.** Pass through `env:` and quote:
|
|
13
|
+
```yaml
|
|
14
|
+
- env: { TARGET_SHA: "${{ github.event.client_payload.sha }}" }
|
|
15
|
+
run: git checkout "$TARGET_SHA"
|
|
16
|
+
```
|
|
17
|
+
Applies to inputs, PR titles, branch names, dispatch payloads, and secrets.
|
|
18
|
+
4. **Missing secret → fail, don't skip green.** A gate that silently passes when its
|
|
19
|
+
credential is absent proves nothing.
|
|
20
|
+
5. **GCP from Actions: Workload Identity Federation**, never a JSON key. Least role, an
|
|
21
|
+
attribute condition on repo + workflow + ref, and delete the credentials file before
|
|
22
|
+
mounting the workspace into a container.
|
|
23
|
+
6. **GitHub App tokens** (`actions/create-github-app-token`) over PATs for cross-repo writes
|
|
24
|
+
and dispatch. Cloud Build → GitHub dispatch: token from Secret Manager, scoped to one repo.
|
|
25
|
+
7. **`pull_request_target`**: avoid. If unavoidable (for example, a queue bot's PR needs a
|
|
26
|
+
privileged check), verify the actor id and login and the branch prefix, check out as data
|
|
27
|
+
with `persist-credentials: false`, never run PR code, never expose secrets.
|
|
28
|
+
8. **`workflow_dispatch` that can write**: reject non-default refs before any write job runs.
|
|
29
|
+
9. **Deploy/publish jobs use `environment:`** so secrets are scoped and protection rules apply.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Auditing and speeding up CI
|
|
2
|
+
|
|
3
|
+
> Read when: CI feels slow, or you suspect redundant jobs. Profile the bottleneck, optimize, then verify.
|
|
4
|
+
|
|
5
|
+
The fix-first procedure is [audit-profile-optimize.md](audit-profile-optimize.md).
|
|
6
|
+
Optional examples are in [ci-case-studies.md](ci-case-studies.md).
|
|
7
|
+
|
|
8
|
+
## Inspecting CI
|
|
9
|
+
|
|
10
|
+
Start with a representative successful run and identify the required-check critical path
|
|
11
|
+
or runner-consumption bottleneck. Read that job and its commands first; expand to the
|
|
12
|
+
workflow graph for parallelism, repeated setup, placement, or unnecessary work. Failures
|
|
13
|
+
matter when they explain delays or block valid measurement, not merely because they are
|
|
14
|
+
red. Expand history only for an unresolved symptom or an explicit audit.
|
|
15
|
+
`scripts/ci-run-audit.mjs` reads through `gh`; it never edits workflows. Implement a
|
|
16
|
+
justified scoped optimization, or stop with no change needed. Saving runs is optional:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
node <github-actions>/scripts/ci-run-audit.mjs --repo <owner/repo> --profile-run <run-id> --json
|
|
20
|
+
node <github-actions>/scripts/ci-run-audit.mjs --repo <owner/repo> --runs 60
|
|
21
|
+
# Optional replay:
|
|
22
|
+
node <github-actions>/scripts/ci-run-audit.mjs --repo <owner/repo> --runs 60 --save runs.json
|
|
23
|
+
node <github-actions>/scripts/ci-run-audit.mjs --from runs.json --json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
| Section | Finds | Typical fix |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| Re-proved trees | matching workflow/job run-tree metadata: PR → queue → main; tested checkout unverified | queue → main: drop the `push: main` trigger, don't build reuse; PR → queue: run each heavy check in one lane; changed queue trees still validate |
|
|
29
|
+
| Catch yield | per job: failures, sole catches, flakes; jobs with no sole catch over 20+ code states | merge, move off the PR lane, or retire |
|
|
30
|
+
| Overlap | a job whose every failure coincided with another job failing | read one log of each; merge or fix the shared fixture |
|
|
31
|
+
| Setup share | jobs that are ≥70% overhead | fold them into one job |
|
|
32
|
+
| Critical path | PR wait p50/p90 and which job finishes last | inspect that job's dependency chain; optimize the evidenced execution or scheduling bottleneck |
|
|
33
|
+
| Stuck + queue | jobs past 6h; runner queue time | fix the runner; add `timeout-minutes` |
|
|
34
|
+
|
|
35
|
+
Read it as candidates, not verdicts. A job with no catches may guard a rare, costly path
|
|
36
|
+
(security, money); a date- or network-dependent job (quarantine expiry, live smoke) may
|
|
37
|
+
repeat on the same tree on purpose. Pass `--ignore-job <regex>` for repo-specific roll-up
|
|
38
|
+
jobs so they do not make every failure look shared. First org run (2026-09-27): four of
|
|
39
|
+
seven repos spent 40–48% of passing job-minutes re-proving identical trees, and one had 14
|
|
40
|
+
jobs hung for 24h.
|
|
41
|
+
|
|
42
|
+
## Speed
|
|
43
|
+
|
|
44
|
+
- **Caching.** GitHub-hosted: `setup-node` with `cache: pnpm`, `setup-uv` with
|
|
45
|
+
`enable-cache: true`. Self-hosted: prefer the runner-local pnpm store and uv cache over
|
|
46
|
+
`actions/cache`. A restore over the network measured 5m30s against a 21 s cold install.
|
|
47
|
+
Measure before adding a cache; `actions/cache` is remote, so on a LAN fleet it is
|
|
48
|
+
usually the wrong fix. Read each job's warm/cold status from its install log (the
|
|
49
|
+
store's reused-package count) before blaming downloads. With a LAN proxy and warm
|
|
50
|
+
per-slot stores, installs took 4–19 s; the rest was repeated work (duplicate type
|
|
51
|
+
checks, sequential DB prepare scripts, cold framework builds), not downloads.
|
|
52
|
+
- **One type-check gate.** A framework build that type-checks (`next build`) inside every
|
|
53
|
+
test shard repeats the standalone, incremental `tsc` gate: 49 s × 5 shards plus 22 s in
|
|
54
|
+
the build job, against ~5 s for the gate. Disable the build's type check with a CI-only
|
|
55
|
+
flag in those jobs, keep the standalone gate required, and confirm its tsconfig covers
|
|
56
|
+
the same files. Never drop type checking from CI: local checks get skipped. Same for
|
|
57
|
+
lint-during-build versus a lint gate.
|
|
58
|
+
- **Lockfile policy checks.** A supply-chain or policy check over the lockfile can be most
|
|
59
|
+
of the install (35–41 s, ~80%). Run it when the lockfile or its policy inputs differ
|
|
60
|
+
from an already-verified base, including in the queue when the batch changes them;
|
|
61
|
+
skip it on PRs whose lockfile matches base. Or give it a persistent metadata cache if
|
|
62
|
+
it supports one.
|
|
63
|
+
- **Build once, fan out.** Build in one job, `upload-artifact` (with `include-hidden-files: true`
|
|
64
|
+
for `.next`), shard e2e with `--shard=${{ matrix.shard }}/N`, `fail-fast: false`, and roll up
|
|
65
|
+
in the gate.
|
|
66
|
+
- **Timeout ladder.** Every job has `timeout-minutes`. Install budget < step timeout < job
|
|
67
|
+
timeout, with measured headroom for startup, diagnostics and cleanup between the inner
|
|
68
|
+
and outer limits. The job timeout is the only hang limit: the merge queue sets none
|
|
69
|
+
(`mergify` skill: `checks_timeout: null`). A job without
|
|
70
|
+
a timeout on a self-hosted slot can hold it for hours to days; self-hosted jobs lack
|
|
71
|
+
the six-hour cap GitHub-hosted jobs have.
|
|
72
|
+
- **Concurrency.**
|
|
73
|
+
```yaml
|
|
74
|
+
concurrency:
|
|
75
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
76
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
77
|
+
```
|
|
78
|
+
Never cancel deploy, publish, or post-deploy runs; builds can finish out of order.
|
|
79
|
+
- **Retries** only in the queue lane, at most once, and log a `[flake-retry]` marker so a
|
|
80
|
+
pass-on-retry is visible. None on PRs.
|
|
81
|
+
- **No redundant repeats.** Run each check once per tree: with a merge queue, drop
|
|
82
|
+
`push: main` and gate reruns on `schedule:` instead of building evidence reuse, and keep
|
|
83
|
+
a heavy check in one lane (PR or queue), not both. A changed queue tree still needs
|
|
84
|
+
validation. Build once and pass the artifact to dependent jobs.
|
|
85
|
+
- **Workers.** Set the count from the slot size; `os.cpus()` inside a `--cpus 4` container
|
|
86
|
+
reports host cores. The values below are starting examples, not workers-equals-cores
|
|
87
|
+
policy; memory and shared fixtures can require fewer workers even with spare CPUs.
|
|
88
|
+
```yaml
|
|
89
|
+
- env:
|
|
90
|
+
E2E_WORKERS: '4' # playwright.config: workers: Number(process.env.E2E_WORKERS) || 4
|
|
91
|
+
run: pnpm exec playwright test
|
|
92
|
+
- run: pnpm vitest run --maxWorkers=4 # or: pytest -n 4
|
|
93
|
+
```
|
|
94
|
+
- **Disposable Postgres.** Size-bounded tmpfs by default (`size=1g`); it changes no
|
|
95
|
+
durability setting. Profile launch, readiness and schema preparation separately. Turn
|
|
96
|
+
durability off only when measured and not testing persistence/recovery. Poll health
|
|
97
|
+
every 1–2 s, not 10 s (a 10 s interval wasted ~15 s per job), with retries that keep
|
|
98
|
+
the total timeout. Many sequential SQL prepare scripts (27–49 s per job) are CPU and
|
|
99
|
+
round-trip bound, so tmpfs does not fix them: run them in one session, parallelize the
|
|
100
|
+
independent ones, or restore a snapshot keyed on a hash of the schema and prepare
|
|
101
|
+
inputs. [runners.md](runners.md#services-and-networking).
|
|
102
|
+
- **Failure artifacts only.** Playwright: `screenshot: 'only-on-failure'`,
|
|
103
|
+
`trace: 'retain-on-failure'`, `video: 'off'`. Upload artifacts `if: failure()`.
|
|
104
|
+
|
|
105
|
+
## SLA
|
|
106
|
+
|
|
107
|
+
Excluding E2E jobs, measured push → `gate` result:
|
|
108
|
+
|
|
109
|
+
| Setup | Lane | Budget |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| Mergify | PR admission | < 2 min |
|
|
112
|
+
| Mergify | merge queue | < 5 min |
|
|
113
|
+
| No queue | total PR CI | < 7 min |
|
|
114
|
+
|
|
115
|
+
Over budget -> inspect the critical-path job, fix its cause, and verify the improvement.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Two-pass reading example
|
|
2
|
+
|
|
3
|
+
Fetch what the parser needs; print only what the decision needs. These commands are
|
|
4
|
+
read-only and create no report files. Run in Bash with Node, `gh`, `jq`, and the `yaml`
|
|
5
|
+
Node package available (`node -e 'require("yaml")'` checks it). Use the repository's
|
|
6
|
+
existing parser dependency; if absent, arrange it outside an audit-only target checkout.
|
|
7
|
+
Do not parse workflow YAML with line-based regexes or execute workflow expressions.
|
|
8
|
+
|
|
9
|
+
Set `SKILL_DIR` to the installed github-actions skill directory and fill in:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
set -o pipefail
|
|
13
|
+
REPO=owner/repo
|
|
14
|
+
RUN=123456
|
|
15
|
+
SHA=full-source-commit-sha
|
|
16
|
+
WORKFLOW=.github/workflows/ci.yml
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Pass 1: Timings and job map
|
|
20
|
+
|
|
21
|
+
Start with a representative successful run. Print one row per non-skipped job and its
|
|
22
|
+
longest measured step, not the whole profile:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
node "$SKILL_DIR/scripts/ci-run-audit.mjs" --repo "$REPO" --profile-run "$RUN" --json |
|
|
26
|
+
jq -r '
|
|
27
|
+
(["job", "runner", "created-to-start (s)", "execution (s)", "longest step", "step (s)"],
|
|
28
|
+
(.jobs | sort_by(.elapsedS // -1) | reverse | .[] |
|
|
29
|
+
select(.conclusion != "skipped") |
|
|
30
|
+
(.steps | map(select(.conclusion != "skipped" and .durationS != null)) |
|
|
31
|
+
max_by(.durationS)) as $step |
|
|
32
|
+
[.name, (.runnerName // "unknown"), (.queueS // "unknown"),
|
|
33
|
+
(.elapsedS // "unknown"), ($step.name // "unknown"),
|
|
34
|
+
($step.durationS // "unknown")])) | @tsv'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For saved inputs, replace `--repo "$REPO"` with `--from /path/to/runs.json`. Null timings
|
|
38
|
+
stay unknown; zero stays zero. Created-to-start is an observed scheduling interval, not
|
|
39
|
+
proof of runner contention. Longest execution alone does not establish the critical path.
|
|
40
|
+
|
|
41
|
+
Get a compact map from the pinned workflow using a YAML parser:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
gh api "repos/$REPO/contents/$WORKFLOW?ref=$SHA" \
|
|
45
|
+
-H 'Accept: application/vnd.github.raw+json' |
|
|
46
|
+
node -e '
|
|
47
|
+
const fs = require("node:fs"), YAML = require("yaml");
|
|
48
|
+
const workflow = YAML.parse(fs.readFileSync(0, "utf8"));
|
|
49
|
+
if (!workflow?.jobs) throw new Error("Workflow has no jobs");
|
|
50
|
+
for (const [id, job] of Object.entries(workflow.jobs)) {
|
|
51
|
+
console.log(JSON.stringify({id, name: job.name ?? id,
|
|
52
|
+
needs: job.needs ?? [], if: job.if ?? null,
|
|
53
|
+
runner: job["runs-on"] ?? null, concurrency: job.concurrency ?? null}));
|
|
54
|
+
}'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Connect timings to this graph and the established required checks before picking the
|
|
58
|
+
target. Job IDs are not display names; a matrix job may correspond to several timing
|
|
59
|
+
rows. Read top-level concurrency separately if start delay makes it relevant. Do not
|
|
60
|
+
assume the sampled run used this SHA: check source correspondence when needed.
|
|
61
|
+
|
|
62
|
+
## Pass 2: Selected job and command
|
|
63
|
+
|
|
64
|
+
Set `JOB` to an ID from the map (for example, `JOB=functional`). Print only that job's
|
|
65
|
+
configuration; absent IDs fail visibly:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
: "${JOB:?Set JOB to an ID from the map}"
|
|
69
|
+
gh api "repos/$REPO/contents/$WORKFLOW?ref=$SHA" \
|
|
70
|
+
-H 'Accept: application/vnd.github.raw+json' |
|
|
71
|
+
node -e '
|
|
72
|
+
const fs = require("node:fs"), YAML = require("yaml");
|
|
73
|
+
const workflow = YAML.parse(fs.readFileSync(0, "utf8"));
|
|
74
|
+
const id = process.argv[1];
|
|
75
|
+
if (!Object.hasOwn(workflow?.jobs ?? {}, id)) throw new Error(`Unknown job: ${id}`);
|
|
76
|
+
process.stdout.write(YAML.stringify(workflow.jobs[id]));
|
|
77
|
+
' "$JOB"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
If that job is itself large, emit a step index first, then only the chosen step plus
|
|
81
|
+
relevant job defaults. Follow its `run` command or local `uses` action to the invoked
|
|
82
|
+
script and relevant function. Search function names to locate code; do not dump the
|
|
83
|
+
whole repository tree. Expand to prerequisites, shared inputs, or selectors only when
|
|
84
|
+
they affect the proposed change. Protect literal secrets/private URLs before printing.
|
|
85
|
+
|
|
86
|
+
Stop when a bounded optimization is justified, or name the single missing check:
|
|
87
|
+
|
|
88
|
+
> Start delay dominates, but its cause is unknown. Check whether eligible runner slots
|
|
89
|
+
> or the concurrency lock were occupied. No workflow patch is justified yet.
|
|
90
|
+
|
|
91
|
+
The same distinction applies to caching: visible install cost is an opportunity, not
|
|
92
|
+
predicted savings; restore/install/save cost determines whether the candidate pays off.
|