@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,325 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: python-backend
|
|
3
|
+
description: "Python backend architecture for FastAPI, Tortoise ORM, Pydantic Settings, loguru, and uv. Also: uv.lock installs in CI/Docker via a proxy or mirror (`uv sync --frozen` bypasses it), slow uv installs on runners, relocking."
|
|
4
|
+
release-version: 0.36.0
|
|
5
|
+
---
|
|
6
|
+
**Updates:** Once/session run `node <skill-base-dir>/release-check.mjs`.
|
|
7
|
+
# Python Backend Conventions
|
|
8
|
+
**Stack:** Python 3.12 | FastAPI | Tortoise-ORM | Aerich | Pydantic v2 | loguru | uv | pytest
|
|
9
|
+
|
|
10
|
+
## Critical Rule
|
|
11
|
+
|
|
12
|
+
Use **uv** for all environment, dependency, and tool commands. No raw `pip`, `poetry`, `pipenv`, or manual `venv`.
|
|
13
|
+
|
|
14
|
+
CI/image installs: `uv sync --frozen` bypasses proxies and mirrors; use the hash-checked
|
|
15
|
+
script; relock on PyPI only: [references/uv-installs.md](references/uv-installs.md).
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Tooling & Commands
|
|
20
|
+
|
|
21
|
+
### Dependencies
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Runtime deps
|
|
25
|
+
uv add fastapi tortoise-orm aerich pydantic pydantic-settings loguru
|
|
26
|
+
|
|
27
|
+
# Dev deps
|
|
28
|
+
uv add --dev pytest ruff mypy
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Running Commands
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
uv run uvicorn app.main:app --reload # Start app
|
|
35
|
+
uv run pytest # Run tests
|
|
36
|
+
uv run ruff check . # Lint
|
|
37
|
+
uv run mypy app # Type check
|
|
38
|
+
uv run aerich migrate # Run migrations
|
|
39
|
+
uv run aerich upgrade # Apply migrations
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Architecture
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
app/
|
|
48
|
+
├── api/ # API Layer - routes, endpoints
|
|
49
|
+
├── services/ # Service Layer - business logic
|
|
50
|
+
├── dal/ # Data Access Layer - Tortoise queries
|
|
51
|
+
├── models/ # Tortoise ORM models
|
|
52
|
+
├── schemas/ # Pydantic schemas
|
|
53
|
+
└── core/ # Infrastructure
|
|
54
|
+
├── config.py # Pydantic Settings
|
|
55
|
+
├── logging.py # loguru configuration
|
|
56
|
+
├── tortoise.py # DB init/close
|
|
57
|
+
├── errors.py # Domain exceptions
|
|
58
|
+
└── security.py # Auth utilities
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Export Rule
|
|
62
|
+
|
|
63
|
+
All modules in `core`, `dal`, `services`, `schemas`, `api` must define `__all__`.
|
|
64
|
+
All packages (`__init__.py`) re-export the public API using `__all__`.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Config Management
|
|
69
|
+
|
|
70
|
+
Location: `app/core/config.py`
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from __future__ import annotations
|
|
74
|
+
|
|
75
|
+
from functools import lru_cache
|
|
76
|
+
from typing import Literal
|
|
77
|
+
|
|
78
|
+
from pydantic import AnyUrl
|
|
79
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
80
|
+
|
|
81
|
+
__all__ = ["Settings", "get_settings"]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class Settings(BaseSettings):
|
|
85
|
+
model_config = SettingsConfigDict(
|
|
86
|
+
env_file=".env",
|
|
87
|
+
env_file_encoding="utf-8",
|
|
88
|
+
extra="ignore",
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
ENV: Literal["local", "dev", "staging", "prod"] = "local"
|
|
92
|
+
DATABASE_URL: AnyUrl
|
|
93
|
+
LOG_LEVEL: str = "INFO"
|
|
94
|
+
APP_NAME: str = "Backend"
|
|
95
|
+
API_V1_PREFIX: str = "/api/v1"
|
|
96
|
+
JWT_SECRET_KEY: str
|
|
97
|
+
JWT_ALGORITHM: str = "HS256"
|
|
98
|
+
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@lru_cache(maxsize=1)
|
|
102
|
+
def get_settings() -> Settings:
|
|
103
|
+
"""Global, cached settings accessor."""
|
|
104
|
+
return Settings()
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Rule:** Never create new `Settings()` manually; always use `get_settings()`.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Logging
|
|
112
|
+
|
|
113
|
+
Location: `app/core/logging.py`
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from __future__ import annotations
|
|
117
|
+
|
|
118
|
+
import sys
|
|
119
|
+
from loguru import logger
|
|
120
|
+
|
|
121
|
+
from app.core.config import get_settings
|
|
122
|
+
|
|
123
|
+
__all__ = ["logger", "configure_logging"]
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def configure_logging() -> None:
|
|
127
|
+
"""Configure global loguru logger. Call once at app startup."""
|
|
128
|
+
settings = get_settings()
|
|
129
|
+
|
|
130
|
+
logger.remove()
|
|
131
|
+
logger.add(
|
|
132
|
+
sys.stderr,
|
|
133
|
+
level=settings.LOG_LEVEL,
|
|
134
|
+
enqueue=True,
|
|
135
|
+
backtrace=False,
|
|
136
|
+
diagnose=False,
|
|
137
|
+
serialize=settings.ENV in ("staging", "prod"),
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Rule:** Import `logger` from `app.core.logging` (not `loguru` directly).
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Tortoise-ORM & Aerich
|
|
146
|
+
|
|
147
|
+
Location: `app/core/tortoise.py`
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from __future__ import annotations
|
|
151
|
+
|
|
152
|
+
from tortoise import Tortoise
|
|
153
|
+
|
|
154
|
+
from app.core.config import get_settings
|
|
155
|
+
|
|
156
|
+
__all__ = ["TORTOISE_ORM", "init_db", "close_db"]
|
|
157
|
+
|
|
158
|
+
settings = get_settings()
|
|
159
|
+
|
|
160
|
+
TORTOISE_ORM = {
|
|
161
|
+
"connections": {
|
|
162
|
+
"default": str(settings.DATABASE_URL),
|
|
163
|
+
},
|
|
164
|
+
"apps": {
|
|
165
|
+
"models": {
|
|
166
|
+
"models": ["app.models.user", "app.models.order", "aerich.models"],
|
|
167
|
+
"default_connection": "default",
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
async def init_db() -> None:
|
|
174
|
+
await Tortoise.init(config=TORTOISE_ORM)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
async def close_db() -> None:
|
|
178
|
+
await Tortoise.close_connections()
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Data Access Layer (DAL)
|
|
184
|
+
|
|
185
|
+
Location: `app/dal/**`
|
|
186
|
+
|
|
187
|
+
- Functional style, Tortoise only
|
|
188
|
+
- No FastAPI, no Pydantic, no auth, no logging
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
# app/dal/order_dal.py
|
|
192
|
+
from __future__ import annotations
|
|
193
|
+
|
|
194
|
+
from tortoise.transactions import in_transaction
|
|
195
|
+
from app.models.order import Order, OrderItem
|
|
196
|
+
|
|
197
|
+
__all__ = ["get_user_orders_with_items", "create_order_with_items"]
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
async def get_user_orders_with_items(
|
|
201
|
+
user_id: int,
|
|
202
|
+
limit: int = 20,
|
|
203
|
+
offset: int = 0,
|
|
204
|
+
) -> list[Order]:
|
|
205
|
+
return await (
|
|
206
|
+
Order
|
|
207
|
+
.filter(user_id=user_id)
|
|
208
|
+
.prefetch_related("items")
|
|
209
|
+
.order_by("-created_at")
|
|
210
|
+
.offset(offset)
|
|
211
|
+
.limit(limit)
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
async def create_order_with_items(
|
|
216
|
+
user_id: int,
|
|
217
|
+
items: list[dict],
|
|
218
|
+
) -> Order:
|
|
219
|
+
async with in_transaction() as conn:
|
|
220
|
+
order = await Order.using_db(conn).create(user_id=user_id)
|
|
221
|
+
for item in items:
|
|
222
|
+
await OrderItem.using_db(conn).create(order=order, **item)
|
|
223
|
+
return order
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Complexity Rule
|
|
227
|
+
|
|
228
|
+
- **Simple / one-off** queries: Direct Tortoise in services
|
|
229
|
+
- **Complex / reused / transactional**: DAL functions
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Service Layer
|
|
234
|
+
|
|
235
|
+
Location: `app/services/**`
|
|
236
|
+
|
|
237
|
+
- Center of business logic
|
|
238
|
+
- Uses DAL for complex queries
|
|
239
|
+
- Raises domain exceptions from `app/core/errors.py`
|
|
240
|
+
- Uses `logger` for business-level events
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
# app/services/order_service.py
|
|
244
|
+
from __future__ import annotations
|
|
245
|
+
|
|
246
|
+
from app.schemas.order import OrderRead
|
|
247
|
+
from app.dal import get_user_orders_with_items
|
|
248
|
+
from app.core.logging import logger
|
|
249
|
+
|
|
250
|
+
__all__ = ["list_my_orders", "get_order_detail", "create_order"]
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
async def list_my_orders(
|
|
254
|
+
user_id: int,
|
|
255
|
+
limit: int = 20,
|
|
256
|
+
offset: int = 0,
|
|
257
|
+
) -> list[OrderRead]:
|
|
258
|
+
orders = await get_user_orders_with_items(user_id, limit, offset)
|
|
259
|
+
logger.info("Listed orders", user_id=user_id, count=len(orders))
|
|
260
|
+
return [OrderRead.model_validate(o) for o in orders]
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## API Layer
|
|
266
|
+
|
|
267
|
+
Location: `app/api/**`
|
|
268
|
+
|
|
269
|
+
- Uses `APIRouter`, `Depends`, `HTTPException`
|
|
270
|
+
- Converts domain exceptions to HTTP status codes
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
# app/api/v1/orders.py
|
|
274
|
+
from __future__ import annotations
|
|
275
|
+
|
|
276
|
+
from fastapi import APIRouter, Depends, HTTPException
|
|
277
|
+
from app.schemas.order import OrderRead
|
|
278
|
+
from app.services import list_my_orders, get_order_detail
|
|
279
|
+
from app.core.errors import OrderNotFoundError, PermissionDeniedError
|
|
280
|
+
from app.api.deps import get_current_user
|
|
281
|
+
|
|
282
|
+
__all__ = ["router"]
|
|
283
|
+
|
|
284
|
+
router = APIRouter(prefix="/orders", tags=["orders"])
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
@router.get("/", response_model=list[OrderRead])
|
|
288
|
+
async def list_orders(current_user=Depends(get_current_user)) -> list[OrderRead]:
|
|
289
|
+
return await list_my_orders(user_id=current_user.id)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
@router.get("/{order_id}", response_model=OrderRead)
|
|
293
|
+
async def get_order(
|
|
294
|
+
order_id: int,
|
|
295
|
+
current_user=Depends(get_current_user),
|
|
296
|
+
) -> OrderRead:
|
|
297
|
+
try:
|
|
298
|
+
return await get_order_detail(current_user.id, order_id)
|
|
299
|
+
except OrderNotFoundError as e:
|
|
300
|
+
raise HTTPException(status_code=404, detail=str(e))
|
|
301
|
+
except PermissionDeniedError as e:
|
|
302
|
+
raise HTTPException(status_code=403, detail=str(e))
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Do / Don't
|
|
308
|
+
|
|
309
|
+
### Do
|
|
310
|
+
|
|
311
|
+
- Use **Pydantic Settings** with `get_settings()` for config
|
|
312
|
+
- Use **loguru** via `app.core.logging.logger`
|
|
313
|
+
- Keep API -> Service -> DAL separation
|
|
314
|
+
- Use DAL for complex/reused DB logic
|
|
315
|
+
- Use `__all__` and package `__init__.py` for explicit exports
|
|
316
|
+
- Use pytest for all tests
|
|
317
|
+
|
|
318
|
+
### Don't
|
|
319
|
+
|
|
320
|
+
- Don't use raw `pip`, `venv`, or `pytest` outside `uv run`
|
|
321
|
+
- Don't import `loguru.logger` directly
|
|
322
|
+
- Don't instantiate `Settings()` directly
|
|
323
|
+
- Don't call Tortoise from API routes
|
|
324
|
+
- Don't let DAL log or handle business logic
|
|
325
|
+
- Don't raise `HTTPException` outside the API layer
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Install a locked selection of a uv project or workspace, downloading
|
|
3
|
+
# third-party packages through the configured package index instead of the
|
|
4
|
+
# file URLs recorded in uv.lock.
|
|
5
|
+
#
|
|
6
|
+
# Usage, from the directory that holds uv.lock:
|
|
7
|
+
# uv-install.sh [uv export selection args...]
|
|
8
|
+
# uv-install.sh --package api --extra dev
|
|
9
|
+
# uv-install.sh --package engine --no-dev --no-emit-package nvidia-nccl-cu12
|
|
10
|
+
# Then run commands with `uv run --no-sync`.
|
|
11
|
+
#
|
|
12
|
+
# Why not `uv sync --frozen`: it downloads every locked file from the URL in
|
|
13
|
+
# uv.lock (files.pythonhosted.org) and ignores UV_DEFAULT_INDEX, so a proxy or
|
|
14
|
+
# mirror never serves the package files. Instead:
|
|
15
|
+
# 1. export the selection's third-party pins with their sha256 hashes,
|
|
16
|
+
# 2. `uv pip sync --require-hashes` them through the configured index, which
|
|
17
|
+
# rejects any file whose hash differs from uv.lock,
|
|
18
|
+
# 3. install the selected workspace members editable with --no-deps.
|
|
19
|
+
# The environment matches what `uv sync --frozen <args>` would install. With
|
|
20
|
+
# no index configured, step 2 uses PyPI, so the same script works anywhere.
|
|
21
|
+
set -euo pipefail
|
|
22
|
+
|
|
23
|
+
[[ -f uv.lock ]] || {
|
|
24
|
+
echo "uv-install.sh: run from the directory that holds uv.lock" >&2
|
|
25
|
+
exit 2
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
tmp="$(mktemp -d "${RUNNER_TEMP:-${TMPDIR:-/tmp}}/uv-install.XXXXXX")"
|
|
29
|
+
trap 'rm -rf "$tmp"' EXIT
|
|
30
|
+
|
|
31
|
+
export_args=(--frozen --format requirements.txt --no-header --no-annotate "$@")
|
|
32
|
+
uv export "${export_args[@]}" --no-emit-workspace -o "$tmp/third-party.txt" >/dev/null
|
|
33
|
+
uv export "${export_args[@]}" --no-hashes -o "$tmp/all.txt" >/dev/null
|
|
34
|
+
|
|
35
|
+
editables=()
|
|
36
|
+
while IFS= read -r path; do
|
|
37
|
+
editables+=(-e "$path")
|
|
38
|
+
done < <(sed -n 's/^-e //p' "$tmp/all.txt")
|
|
39
|
+
|
|
40
|
+
venv="${UV_PROJECT_ENVIRONMENT:-.venv}"
|
|
41
|
+
[[ "$venv" == /* ]] || venv="$PWD/$venv"
|
|
42
|
+
uv venv --quiet --allow-existing "$venv"
|
|
43
|
+
export VIRTUAL_ENV="$venv"
|
|
44
|
+
|
|
45
|
+
uv pip sync --require-hashes "$tmp/third-party.txt"
|
|
46
|
+
if ((${#editables[@]})); then
|
|
47
|
+
uv pip install --no-deps "${editables[@]}"
|
|
48
|
+
fi
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Installing a uv lockfile in CI and images
|
|
2
|
+
|
|
3
|
+
> Read when: a CI job or Dockerfile installs a uv project, installs are slow on the
|
|
4
|
+
> self-hosted runners, a package proxy or mirror "isn't being used", or someone is about
|
|
5
|
+
> to relock `uv.lock`.
|
|
6
|
+
|
|
7
|
+
## `uv sync --frozen` bypasses the proxy
|
|
8
|
+
|
|
9
|
+
`uv sync --frozen` (and `--locked`) downloads every locked file from the URL recorded in
|
|
10
|
+
`uv.lock`, normally `files.pythonhosted.org`. It ignores `UV_DEFAULT_INDEX`, so a LAN
|
|
11
|
+
proxy or regional mirror sees only index lookups and build-backend fetches, never the
|
|
12
|
+
package files. On the self-hosted runners this cost about 2m20s each for spaCy and SciPy
|
|
13
|
+
(~0.2 MB/s) on files the proxy already had; one measured sync sent 31 wheel downloads
|
|
14
|
+
to PyPI and 14 to the proxy.
|
|
15
|
+
|
|
16
|
+
Dropping `--frozen` is not the fix: plain `uv sync` against a different index can
|
|
17
|
+
re-resolve and rewrite `uv.lock`, so what gets installed is no longer what was locked.
|
|
18
|
+
|
|
19
|
+
## The pattern: export, then hash-checked install through the index
|
|
20
|
+
|
|
21
|
+
[`assets/uv-install.sh`](../assets/uv-install.sh) does it in three steps. Copy it into
|
|
22
|
+
the repo (for example `scripts/ci/uv-install.sh`), run it from the directory that holds
|
|
23
|
+
`uv.lock`, and pass the same selection flags you would give `uv sync`:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bash scripts/ci/uv-install.sh --package api --extra dev
|
|
27
|
+
uv run --no-sync pytest # --no-sync, or uv run re-syncs from uv.lock URLs
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
1. `uv export --frozen --no-emit-workspace` writes the selection's third-party pins with
|
|
31
|
+
their sha256 hashes and no URLs.
|
|
32
|
+
2. `uv pip sync --require-hashes` installs them through whatever index is configured.
|
|
33
|
+
A file whose hash differs from `uv.lock` is rejected, so integrity matches `--frozen`.
|
|
34
|
+
3. `uv pip install --no-deps -e …` installs the selected workspace members, taken from
|
|
35
|
+
the `-e` lines of a `--no-hashes` export.
|
|
36
|
+
|
|
37
|
+
The result is the environment `uv sync --frozen <same args>` would build. With no index
|
|
38
|
+
configured, step 2 uses PyPI, so the same script works on GitHub-hosted runners and
|
|
39
|
+
laptops. Measured with an empty cache: 11.8s with `uv sync --frozen`, 1.6s through the
|
|
40
|
+
proxy (all 47 files from the proxy).
|
|
41
|
+
|
|
42
|
+
This is the one place `uv pip` and `uv venv` are the right tools; everywhere else use
|
|
43
|
+
`uv sync`, `uv add` and `uv run`.
|
|
44
|
+
|
|
45
|
+
In a Dockerfile the same idea needs only steps 1 and 2 (the `docker` skill's template).
|
|
46
|
+
|
|
47
|
+
## Caches and Python on the self-hosted runners
|
|
48
|
+
|
|
49
|
+
- **Put uv's cache and managed Pythons on the persistent work disk.** The runner home is
|
|
50
|
+
ephemeral, so the default `UV_CACHE_DIR` starts cold every job. `_work` is reused per
|
|
51
|
+
slot and is on the same filesystem as the venv, so uv hardlinks instead of copying:
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
- name: Persist uv cache per runner slot
|
|
55
|
+
run: |
|
|
56
|
+
base="$(dirname "$RUNNER_WORKSPACE")/.uv"
|
|
57
|
+
echo "UV_CACHE_DIR=$base/cache" >> "$GITHUB_ENV"
|
|
58
|
+
echo "UV_PYTHON_INSTALL_DIR=$base/python" >> "$GITHUB_ENV"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
- **`actions/setup-python` breaks subprocesses that get a minimal environment.** Its
|
|
62
|
+
toolcache Python finds `libpython3.12.so` through `LD_LIBRARY_PATH`; a test that spawns
|
|
63
|
+
`python3` with a stripped env fails with `error while loading shared libraries`.
|
|
64
|
+
uv-managed CPython (`UV_PYTHON_PREFERENCE=only-managed`) is self-contained, but it
|
|
65
|
+
downloads ~33 MB from GitHub per job unless `UV_PYTHON_INSTALL_DIR` persists it (above).
|
|
66
|
+
|
|
67
|
+
## Keep CI installs lean
|
|
68
|
+
|
|
69
|
+
- Skip heavy packages a test never loads. xgboost on Linux pulls `nvidia-nccl-cu12`
|
|
70
|
+
(276 MB, ~6.5 min); it is loaded only for multi-GPU training, so
|
|
71
|
+
`--no-emit-package nvidia-nccl-cu12` is safe in CI.
|
|
72
|
+
- Pass `--no-dev` when the dev group is notebook or editor tooling the job does not run.
|
|
73
|
+
|
|
74
|
+
## Relocking
|
|
75
|
+
|
|
76
|
+
Lock against official PyPI, never the proxy:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
UV_DEFAULT_INDEX=https://pypi.org/simple uv lock
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Relocking through the proxy has hung, and the committed lock's URLs must stay official
|
|
83
|
+
PyPI: `pip-audit` and other provenance checks read them.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
9
|
+
const WEEK_MS = 7 * DAY_MS;
|
|
10
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
|
|
12
|
+
function readJson(path, fallback = {}) {
|
|
13
|
+
try { return JSON.parse(readFileSync(path, 'utf8')); } catch { return fallback; }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function frontmatterValue(text, key) {
|
|
17
|
+
const frontmatter = /^---\n([\s\S]*?)\n---/.exec(text)?.[1] ?? '';
|
|
18
|
+
const match = new RegExp('^' + key + ':\\s*([^\\n]+)$', 'm').exec(frontmatter);
|
|
19
|
+
return match?.[1].trim().replace(/^['"]|['"]$/g, '') ?? null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function repositoryOf(source) {
|
|
23
|
+
const value = String(source ?? '').trim();
|
|
24
|
+
const match = /^(?:git@github\.com:|https:\/\/github\.com\/)?([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?$/.exec(value);
|
|
25
|
+
return match?.[1] ?? null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function stableVersion(value) {
|
|
29
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(String(value ?? '').trim());
|
|
30
|
+
return match ? match.slice(1).map(Number) : null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function newer(left, right) {
|
|
34
|
+
for (let index = 0; index < 3; index += 1) {
|
|
35
|
+
if (left[index] !== right[index]) return left[index] > right[index];
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function writeCache(path, value) {
|
|
41
|
+
try {
|
|
42
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
43
|
+
writeFileSync(path, JSON.stringify(value));
|
|
44
|
+
} catch { /* A read-only cache must not block skill use. */ }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function main(now = Date.now()) {
|
|
48
|
+
if (process.env.ONEABOVEIO_NO_UPDATE_CHECK) return;
|
|
49
|
+
const skill = readFileSync(join(here, 'SKILL.md'), 'utf8');
|
|
50
|
+
const name = frontmatterValue(skill, 'name');
|
|
51
|
+
const localVersion = stableVersion(frontmatterValue(skill, 'release-version'));
|
|
52
|
+
if (!name || !localVersion) return;
|
|
53
|
+
|
|
54
|
+
const lock = readJson(join(process.env.HOME || homedir(), '.agents', '.skill-lock.json'));
|
|
55
|
+
const entry = lock.skills?.[name];
|
|
56
|
+
const repository = repositoryOf(entry?.sourceUrl || entry?.source);
|
|
57
|
+
if (!repository) return;
|
|
58
|
+
|
|
59
|
+
const cacheRoot = process.env.XDG_CACHE_HOME || join(process.env.HOME || homedir(), '.cache');
|
|
60
|
+
const cachePath = join(cacheRoot, '1aboveio-skills', 'release-check.json');
|
|
61
|
+
const all = readJson(cachePath);
|
|
62
|
+
const cache = all[repository] && typeof all[repository] === 'object' ? all[repository] : {};
|
|
63
|
+
|
|
64
|
+
if (!cache.lastCheck || now - cache.lastCheck >= DAY_MS) {
|
|
65
|
+
const result = spawnSync('gh', ['api', 'repos/' + repository + '/releases/latest', '--jq', '.tag_name'], {
|
|
66
|
+
encoding: 'utf8',
|
|
67
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
68
|
+
timeout: 1500,
|
|
69
|
+
});
|
|
70
|
+
cache.lastCheck = now;
|
|
71
|
+
if (result.status === 0 && stableVersion(result.stdout)) cache.latestTag = result.stdout.trim();
|
|
72
|
+
else delete cache.latestTag;
|
|
73
|
+
all[repository] = cache;
|
|
74
|
+
writeCache(cachePath, all);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const latestVersion = stableVersion(cache.latestTag);
|
|
78
|
+
if (!latestVersion || !newer(latestVersion, localVersion)) return;
|
|
79
|
+
if (cache.notifiedTag === cache.latestTag && cache.notifiedAt && now - cache.notifiedAt < WEEK_MS) return;
|
|
80
|
+
|
|
81
|
+
cache.notifiedTag = cache.latestTag;
|
|
82
|
+
cache.notifiedAt = now;
|
|
83
|
+
all[repository] = cache;
|
|
84
|
+
writeCache(cachePath, all);
|
|
85
|
+
const command = `npx skills@1.5.23 add '${repository}#${cache.latestTag}' --global --agent universal claude-code --skill ${name} --yes`;
|
|
86
|
+
process.stdout.write(
|
|
87
|
+
`UPDATE_AVAILABLE: A newer 1AboveIO skills release (${cache.latestTag}) is available; this skill is `
|
|
88
|
+
+ `v${localVersion.join('.')}. Ask once whether to refresh ${name}. On approval run \`${command}\`. `
|
|
89
|
+
+ 'The refreshed instructions apply next session. Either way, continue the current task and do not ask again this session.\n',
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
try { main(); } catch { /* Update checks are advisory and always fail silent. */ }
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: shadcn
|
|
3
|
+
description: "Add or debug shadcn/ui in a React/Next.js project: components.json, shadcn init/add, presets, registries, Tailwind styling, base/radix/aria composition, component fixes, and list-index pages — where the default is the DiceUI data table with filter/sort/pagination in the URL via nuqs, not a bare shadcn Table."
|
|
4
|
+
allowed-tools: Bash(npx shadcn@latest *), Bash(pnpm dlx shadcn@latest *), Bash(bunx --bun shadcn@latest *)
|
|
5
|
+
release-version: 0.36.0
|
|
6
|
+
---
|
|
7
|
+
**Updates:** Once/session run `node <skill-base-dir>/release-check.mjs`.
|
|
8
|
+
# shadcn/ui
|
|
9
|
+
|
|
10
|
+
Components are added as **source code** via the CLI — you edit them like your own files.
|
|
11
|
+
|
|
12
|
+
**This page is an index.** Each rule below is the short form; the linked file carries the reasoning and the Incorrect/Correct pairs. Read the row for your task before acting — the rules are stated flat here and the *why* is what stops you misapplying them.
|
|
13
|
+
|
|
14
|
+
> Run every CLI command with the project's runner: `npx shadcn@latest`, `pnpm dlx shadcn@latest`, or `bunx --bun shadcn@latest`. Pick from the lockfile or `package.json`'s `packageManager` — `shadcn info` does not report it.
|
|
15
|
+
|
|
16
|
+
## Current Project Context
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
!`npx shadcn@latest info --json`
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Blocks: `project`, `config`, `preset`, `components`, `links`. Names are exact — `config.rsc` not `isRSC`, `project.tailwindCss` not `tailwindCssFile`, `project.importAlias` not `aliasPrefix`, and there is no `packageManager`. Full table: [cli.md](./cli.md#info--project-information).
|
|
23
|
+
|
|
24
|
+
Four fields change what you write: **`config.base`** (`radix` | `base` | `aria` — different APIs), **`config.rsc`** (`"use client"` needed?), **`config.iconLibrary`** (never assume `lucide-react`), **`config.aliases`**/`resolvedPaths` (never hardcode `@/`).
|
|
25
|
+
|
|
26
|
+
## Routing
|
|
27
|
+
|
|
28
|
+
| Task | Read |
|
|
29
|
+
|---|---|
|
|
30
|
+
| Pick a component; the core code patterns | [rules/component-selection.md](./rules/component-selection.md) |
|
|
31
|
+
| Forms — layout, validation, errors, inputs | [rules/forms.md](./rules/forms.md) |
|
|
32
|
+
| Compose — groups, overlays, Card, Tabs, Avatar | [rules/composition.md](./rules/composition.md) |
|
|
33
|
+
| Style — colors, spacing, variants, `cn()`, dark mode | [rules/styling.md](./rules/styling.md) |
|
|
34
|
+
| Icons — `data-icon`, sizing, icons as props | [rules/icons.md](./rules/icons.md) |
|
|
35
|
+
| A list/index page or any data table | [rules/data-table.md](./rules/data-table.md) |
|
|
36
|
+
| `asChild` vs `render`; `base`/`radix`/`aria` splits | [rules/base-vs-radix.md](./rules/base-vs-radix.md) |
|
|
37
|
+
| Any CLI command, flag, preset, registry | [cli.md](./cli.md) |
|
|
38
|
+
| Theming, CSS variables, extending a component | [customization.md](./customization.md) |
|
|
39
|
+
| MCP server | [mcp.md](./mcp.md) |
|
|
40
|
+
|
|
41
|
+
## Principles
|
|
42
|
+
|
|
43
|
+
1. **Use an existing component first** (`npx shadcn@latest search`), and **compose rather than reinvent** — a settings page is Tabs + Card + form controls.
|
|
44
|
+
2. **Built-in variants before custom styles; semantic colors only** — never `bg-blue-500`.
|
|
45
|
+
3. **Read the docs before writing a component** — `npx shadcn@latest docs <component>`, then fetch the URLs. APIs differ per base and shift between releases, so guessing yields code that looks right and isn't.
|
|
46
|
+
|
|
47
|
+
## Critical Rules
|
|
48
|
+
|
|
49
|
+
**Styling** → [styling.md](./rules/styling.md)
|
|
50
|
+
|
|
51
|
+
- `className` for layout only — never component colors or typography, and no manual `dark:` overrides.
|
|
52
|
+
- `gap-*` not `space-x-*`/`space-y-*`; `size-*` when width and height match; `truncate` not the longhand.
|
|
53
|
+
- `cn()` for conditional classes, never template literals. No manual `z-index` on overlays.
|
|
54
|
+
- `Badge` variants are exactly `default`, `secondary`, `destructive`, `outline`, `ghost` — no `success`.
|
|
55
|
+
|
|
56
|
+
**Forms** → [forms.md](./rules/forms.md)
|
|
57
|
+
|
|
58
|
+
- `FieldGroup` + `Field` for layout, never a raw `div`.
|
|
59
|
+
- Errors go in `FieldError`, never `FieldDescription`. Validation is `data-invalid` on `Field` **and** `aria-invalid` on the control; disabled likewise.
|
|
60
|
+
- `InputGroup` takes `InputGroupInput`/`InputGroupTextarea`; buttons inside it use `InputGroupButton` in an `InputGroupAddon`, and a trailing one needs `align="inline-end"`.
|
|
61
|
+
- Option sets (2–7) use `ToggleGroup`; `FieldSet` + `FieldLegend` group related checkboxes/radios.
|
|
62
|
+
|
|
63
|
+
**Composition** → [composition.md](./rules/composition.md)
|
|
64
|
+
|
|
65
|
+
- Items live inside their Group — `SelectItem`→`SelectGroup`, `DropdownMenuItem`→`DropdownMenuGroup`, `CommandItem`→`CommandGroup`.
|
|
66
|
+
- `asChild` (radix) or `render` (base) for custom triggers; check `config.base` → [base-vs-radix.md](./rules/base-vs-radix.md).
|
|
67
|
+
- Dialog/Sheet/Drawer need a Title (`sr-only` if hidden); `TabsTrigger` belongs in `TabsList`; `Avatar` needs `AvatarFallback`.
|
|
68
|
+
- Full Card composition, not everything in `CardContent`. `Button` has no `isPending`/`isLoading` — compose `Spinner` + `data-icon` + `disabled`.
|
|
69
|
+
- Prefer the component over markup: `Alert`, `Empty`, `sonner`'s `toast()`, `Separator`, `Skeleton`, `Badge`.
|
|
70
|
+
|
|
71
|
+
**Icons** → [icons.md](./rules/icons.md)
|
|
72
|
+
|
|
73
|
+
- `data-icon="inline-start"`/`"inline-end"` on icons inside `Button`; pass icons as components (`icon={CheckIcon}`), not string keys.
|
|
74
|
+
- No sizing classes on icons inside components — a `size-*` class *opts out* of the component's sizing rather than matching it.
|
|
75
|
+
|
|
76
|
+
**CLI** → [cli.md](./cli.md)
|
|
77
|
+
|
|
78
|
+
- Never decode or fetch a preset code by hand — `preset decode <code>` shows what it encodes. Swap icon libraries with `migrate icons --from <a> --to <b>`.
|
|
79
|
+
- Never `--overwrite` without explicit approval → [smart merge](./cli.md#smart-merge-from-upstream). Never guess an unnamed registry, and read every file one adds → [third-party registries](./cli.md#working-with-third-party-registries).
|
|
80
|
+
|
|
81
|
+
## Data Tables & List Pages
|
|
82
|
+
|
|
83
|
+
**On a portal list/index page the data table is DiceUI's — the default, not a suggestion.** A bare `Table` there is the choice that needs justifying. Elsewhere: DiceUI once a table needs server-side filter/sort/paginate, plain `Table` when it's display.
|
|
84
|
+
|
|
85
|
+
**List-page state belongs in the URL, via `nuqs`** — not `useState`, and never mirrored into both. `useDataTable` calls `useQueryState` internally, so `nuqs` is a hard dependency and the app must be wrapped once in `NuqsAdapter` or the hook throws.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npx shadcn@latest add "https://tablecn.com/r/data-table.json" # .json required; extensionless 404s
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Why URL state is the point, the install traps (undeclared `zod` / `@dnd-kit/*`), the server-side parsing pattern, and the column contract: [rules/data-table.md](./rules/data-table.md). Surrounding state & data-flow conventions: the project's `nextjs-fullstack` skill.
|
|
92
|
+
|
|
93
|
+
## Starting a New Project
|
|
94
|
+
|
|
95
|
+
Canonical config: **Base UI + nova + lucide** — `components.json` ends up with `style: "base-nova"`. Install the whole library up front so feature work never stalls on a missing component.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Single app — same result as `init --defaults`, which resolves to next + base-nova.
|
|
99
|
+
npx shadcn@latest init --template next --base base --preset nova
|
|
100
|
+
# Turborepo workspace.
|
|
101
|
+
npx shadcn@latest init --template next --base base --preset nova --monorepo
|
|
102
|
+
npx shadcn@latest add --all
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Two consequences to carry into everything you write afterwards:
|
|
106
|
+
|
|
107
|
+
- **The base is `base`, so component APIs are Base UI's** — `render` not `asChild`, `multiple` not `type="single"`, a scalar `Slider`, and `Select` needs an `items` prop → [base-vs-radix.md](./rules/base-vs-radix.md). Registry items and most examples online are written for radix; expect to convert.
|
|
108
|
+
- **In a monorepo the UI alias is `@workspace/ui/components`, not `@/components/ui`** — so third-party registry items land with imports that resolve to nothing. Rewrite them against `config.aliases`.
|
|
109
|
+
|
|
110
|
+
`--all` is a setup step, not an update path — what that means when upstream moves: [cli.md](./cli.md#installing-everything-up-front).
|
|
111
|
+
|
|
112
|
+
## Workflow
|
|
113
|
+
|
|
114
|
+
1. Read the injected context; re-run `npx shadcn@latest info` to refresh.
|
|
115
|
+
2. Check `components` (or list `resolvedPaths.ui`) before importing. On a project set up as above everything is already there, so this is usually a one-line confirmation — but don't assume it: older projects and ones initialised elsewhere may have been added to piecemeal, and importing a component that was never added fails at build, not at review.
|
|
116
|
+
3. Find components — `npx shadcn@latest search`.
|
|
117
|
+
4. Read the docs — `npx shadcn@latest docs <component>`, then fetch. `view` browses uninstalled items; `add --diff` previews changes to installed ones.
|
|
118
|
+
5. Install or update — `npx shadcn@latest add`; [smart merge](./cli.md#smart-merge-from-upstream) anything with local edits.
|
|
119
|
+
6. Ask which registry when the user didn't name one, then review every added file → [third-party registries](./cli.md#working-with-third-party-registries).
|
|
120
|
+
7. Switching presets — ask first: **overwrite** / **merge** / **skip**, or `apply --only theme` to re-theme alone → [cli.md](./cli.md#switching-presets).
|
|
Binary file
|
|
Binary file
|