@dsalazardev/ai-hub-cli 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/NOTICE.md +34 -0
- package/README.md +64 -2
- package/agents/cpp-build-resolver.md +25 -0
- package/agents/cpp-reviewer.md +28 -0
- package/agents/csharp-reviewer.md +28 -0
- package/agents/django-build-resolver.md +25 -0
- package/agents/django-reviewer.md +28 -0
- package/agents/explorer-domain.md +28 -0
- package/agents/fastapi-reviewer.md +28 -0
- package/agents/flutter-build-resolver.md +25 -0
- package/agents/flutter-reviewer.md +28 -0
- package/agents/go-build-resolver.md +25 -0
- package/agents/go-reviewer.md +28 -0
- package/agents/implementer-backend.md +30 -0
- package/agents/implementer-frontend.md +30 -0
- package/agents/java-build-resolver.md +26 -0
- package/agents/java-reviewer.md +29 -0
- package/agents/kotlin-build-resolver.md +25 -0
- package/agents/kotlin-reviewer.md +28 -0
- package/agents/mle-reviewer.md +28 -0
- package/agents/php-reviewer.md +29 -0
- package/agents/postgres-reviewer.md +28 -0
- package/agents/python-reviewer.md +28 -0
- package/agents/pytorch-build-resolver.md +25 -0
- package/agents/rag-reviewer.md +28 -0
- package/agents/react-build-resolver.md +26 -0
- package/agents/react-reviewer.md +29 -0
- package/agents/reviewer-architecture.md +32 -0
- package/agents/reviewer-tests.md +31 -0
- package/agents/rust-build-resolver.md +25 -0
- package/agents/rust-reviewer.md +28 -0
- package/agents/spec-author.md +36 -0
- package/agents/spec-miner.md +14 -0
- package/agents/swift-build-resolver.md +25 -0
- package/agents/swift-reviewer.md +28 -0
- package/agents/typescript-reviewer.md +28 -0
- package/agents/vue-reviewer.md +28 -0
- package/dist/backup/snapshots.d.ts +24 -0
- package/dist/backup/snapshots.js +171 -0
- package/dist/bin/ai-hub.d.ts +2 -0
- package/dist/bin/ai-hub.js +11 -0
- package/dist/cli/args.d.ts +4 -0
- package/dist/cli/args.js +63 -0
- package/dist/cli/context.d.ts +7 -0
- package/dist/cli/context.js +74 -0
- package/dist/cli/doctor.d.ts +14 -0
- package/dist/cli/doctor.js +200 -0
- package/dist/cli/drift.d.ts +2 -0
- package/dist/cli/drift.js +34 -0
- package/dist/cli/items.d.ts +5 -0
- package/dist/cli/items.js +10 -0
- package/dist/cli/legacy.d.ts +3 -0
- package/dist/cli/legacy.js +18 -0
- package/dist/cli/maintenance.d.ts +8 -0
- package/dist/cli/maintenance.js +262 -0
- package/dist/cli/memory.d.ts +2 -0
- package/dist/cli/memory.js +84 -0
- package/dist/cli/onboarding.d.ts +17 -0
- package/dist/cli/onboarding.js +234 -0
- package/dist/cli/run.d.ts +15 -0
- package/dist/cli/run.js +183 -0
- package/dist/cli/source.d.ts +5 -0
- package/dist/cli/source.js +22 -0
- package/dist/cli/trunk.d.ts +8 -0
- package/dist/cli/trunk.js +54 -0
- package/dist/cli/types.d.ts +17 -0
- package/dist/cli/types.js +4 -0
- package/dist/cli/worktrees.d.ts +11 -0
- package/dist/cli/worktrees.js +141 -0
- package/dist/engine/engine.d.ts +48 -0
- package/dist/engine/engine.js +114 -0
- package/dist/engine/gates.d.ts +2 -0
- package/dist/engine/gates.js +93 -0
- package/dist/frontmatter.d.ts +11 -0
- package/dist/frontmatter.js +30 -0
- package/dist/harness/guards/adapters/context.d.ts +19 -0
- package/dist/harness/guards/adapters/context.js +153 -0
- package/dist/harness/guards/adapters/hermes.d.ts +13 -0
- package/dist/harness/guards/adapters/hermes.js +18 -0
- package/dist/harness/guards/adapters/hooks.d.ts +25 -0
- package/dist/harness/guards/adapters/hooks.js +52 -0
- package/dist/harness/guards/branch.d.ts +5 -0
- package/dist/harness/guards/branch.js +43 -0
- package/dist/harness/guards/danger.d.ts +13 -0
- package/dist/harness/guards/danger.js +157 -0
- package/dist/harness/guards/index.d.ts +6 -0
- package/dist/harness/guards/index.js +6 -0
- package/dist/harness/guards/preflight.d.ts +14 -0
- package/dist/harness/guards/preflight.js +37 -0
- package/dist/harness/guards/ship.d.ts +2 -0
- package/dist/harness/guards/ship.js +35 -0
- package/dist/harness/guards/trunk.d.ts +5 -0
- package/dist/harness/guards/trunk.js +41 -0
- package/dist/harness/guards/types.d.ts +50 -0
- package/dist/harness/guards/types.js +1 -0
- package/dist/harness/memory/ledger.d.ts +53 -0
- package/dist/harness/memory/ledger.js +136 -0
- package/dist/harness/memory/state.d.ts +35 -0
- package/dist/harness/memory/state.js +121 -0
- package/dist/harness/worktree/reaper.d.ts +32 -0
- package/dist/harness/worktree/reaper.js +54 -0
- package/dist/manifest/build.d.ts +1 -0
- package/dist/manifest/build.js +1 -0
- package/dist/manifest/cli.d.ts +2 -0
- package/dist/manifest/cli.js +44 -0
- package/dist/manifest/dispatch.d.ts +13 -0
- package/dist/manifest/dispatch.js +36 -0
- package/dist/manifest/labels.d.ts +15 -0
- package/dist/manifest/labels.js +70 -0
- package/dist/manifest/manifest.d.ts +113 -0
- package/dist/manifest/manifest.js +202 -0
- package/dist/package-info.d.ts +4 -0
- package/dist/package-info.js +7 -0
- package/dist/paths.d.ts +33 -0
- package/dist/paths.js +123 -0
- package/dist/presets/detect.d.ts +24 -0
- package/dist/presets/detect.js +116 -0
- package/dist/presets/materialize.d.ts +18 -0
- package/dist/presets/materialize.js +101 -0
- package/dist/presets/resolve.d.ts +37 -0
- package/dist/presets/resolve.js +83 -0
- package/dist/presets/schema.d.ts +57 -0
- package/dist/presets/schema.js +68 -0
- package/dist/source-checkout.d.ts +8 -0
- package/dist/source-checkout.js +19 -0
- package/dist/sync/config.d.ts +47 -0
- package/dist/sync/config.js +85 -0
- package/dist/sync/lock.d.ts +16 -0
- package/dist/sync/lock.js +43 -0
- package/dist/sync/render.d.ts +18 -0
- package/dist/sync/render.js +255 -0
- package/dist/sync/sync.d.ts +38 -0
- package/dist/sync/sync.js +288 -0
- package/dist/sync/targets.d.ts +24 -0
- package/dist/sync/targets.js +78 -0
- package/engine/coupling.json +4 -0
- package/engine/engine.yaml +250 -0
- package/engine/legacy-paths.json +4 -0
- package/engine/preflight.md +11 -0
- package/manifest.json +393 -0
- package/package.json +61 -4
- package/presets/angular-express/harness/rules/01-zero-any.sh +25 -0
- package/presets/angular-express/harness/rules/02-no-ng-module.sh +21 -0
- package/presets/angular-express/harness/rules/03-no-constructor-injection.sh +21 -0
- package/presets/angular-express/harness/rules/04-no-legacy-directives.sh +21 -0
- package/presets/angular-express/harness/rules/05-no-dolibarrdal-inheritance.sh +25 -0
- package/presets/angular-express/harness/rules/06-no-todos.sh +22 -0
- package/presets/angular-express/harness/run-all.sh +13 -0
- package/presets/angular-express/preset.yaml +55 -0
- package/presets/angular-express/references/common-imports-catalog.md +146 -0
- package/presets/angular-express/references/fichajes-migration-notes.md +57 -0
- package/presets/angular-express/references/module-implementation-flow.md +260 -0
- package/presets/angular-express/references/products-coding-standard.md +143 -0
- package/presets/angular-express/references/products-module-blueprint.md +860 -0
- package/presets/angular-express/references/replicate-module-checklist.md +72 -0
- package/presets/angular-express/references/users-migration-notes.md +172 -0
- package/presets/angular-express/rules/architecture.md +8 -0
- package/presets/angular-express/rules/backend.md +4 -0
- package/presets/angular-express/rules/frontend.md +53 -0
- package/presets/angular-express/skills/angular-developer/SKILL.md +130 -0
- package/presets/angular-express/skills/angular-developer/references/angular-animations.md +160 -0
- package/presets/angular-express/skills/angular-developer/references/angular-aria.md +410 -0
- package/presets/angular-express/skills/angular-developer/references/cli.md +86 -0
- package/presets/angular-express/skills/angular-developer/references/component-harnesses.md +59 -0
- package/presets/angular-express/skills/angular-developer/references/component-styling.md +91 -0
- package/presets/angular-express/skills/angular-developer/references/components.md +117 -0
- package/presets/angular-express/skills/angular-developer/references/creating-services.md +97 -0
- package/presets/angular-express/skills/angular-developer/references/data-resolvers.md +69 -0
- package/presets/angular-express/skills/angular-developer/references/define-routes.md +67 -0
- package/presets/angular-express/skills/angular-developer/references/defining-providers.md +72 -0
- package/presets/angular-express/skills/angular-developer/references/di-fundamentals.md +120 -0
- package/presets/angular-express/skills/angular-developer/references/e2e-testing.md +66 -0
- package/presets/angular-express/skills/angular-developer/references/effects.md +83 -0
- package/presets/angular-express/skills/angular-developer/references/hierarchical-injectors.md +43 -0
- package/presets/angular-express/skills/angular-developer/references/host-elements.md +80 -0
- package/presets/angular-express/skills/angular-developer/references/injection-context.md +63 -0
- package/presets/angular-express/skills/angular-developer/references/inputs.md +101 -0
- package/presets/angular-express/skills/angular-developer/references/linked-signal.md +59 -0
- package/presets/angular-express/skills/angular-developer/references/loading-strategies.md +61 -0
- package/presets/angular-express/skills/angular-developer/references/mcp.md +106 -0
- package/presets/angular-express/skills/angular-developer/references/migrations.md +30 -0
- package/presets/angular-express/skills/angular-developer/references/navigate-to-routes.md +69 -0
- package/presets/angular-express/skills/angular-developer/references/outputs.md +86 -0
- package/presets/angular-express/skills/angular-developer/references/reactive-forms.md +122 -0
- package/presets/angular-express/skills/angular-developer/references/rendering-strategies.md +44 -0
- package/presets/angular-express/skills/angular-developer/references/resource.md +74 -0
- package/presets/angular-express/skills/angular-developer/references/route-animations.md +56 -0
- package/presets/angular-express/skills/angular-developer/references/route-guards.md +52 -0
- package/presets/angular-express/skills/angular-developer/references/router-lifecycle.md +45 -0
- package/presets/angular-express/skills/angular-developer/references/router-testing.md +87 -0
- package/presets/angular-express/skills/angular-developer/references/show-routes-with-outlets.md +68 -0
- package/presets/angular-express/skills/angular-developer/references/signal-forms.md +897 -0
- package/presets/angular-express/skills/angular-developer/references/signals-overview.md +94 -0
- package/presets/angular-express/skills/angular-developer/references/tailwind-css.md +69 -0
- package/presets/angular-express/skills/angular-developer/references/template-driven-forms.md +114 -0
- package/presets/angular-express/skills/angular-developer/references/testing-fundamentals.md +66 -0
- package/presets/angular-express/skills/angular-new-app/SKILL.md +62 -0
- package/presets/angular-express/skills/frontend-design/LICENSE.txt +177 -0
- package/presets/angular-express/skills/frontend-design/SKILL.md +55 -0
- package/presets/angular-express/skills/onna-architecture-angular/SKILL.md +229 -0
- package/presets/angular-express/skills/onna-architecture-bff/SKILL.md +446 -0
- package/presets/angular-express/skills/onna-architecture-common/SKILL.md +313 -0
- package/presets/angular-express/skills/onna-design-system/SKILL.md +615 -0
- package/presets/base/preset.yaml +27 -0
- package/presets/base/rules/core.md +35 -0
- package/presets/generic-ts/preset.yaml +46 -0
- package/presets/python/preset.yaml +47 -0
- package/presets/python/rules/python.md +10 -0
- package/schema/engine.schema.json +73 -0
- package/schema/manifest.schema.json +140 -0
- package/schema/preset.schema.json +98 -0
- package/schema/state.schema.json +27 -0
- package/skills/shared/ab-testing/SKILL.md +159 -0
- package/skills/shared/ab-testing/evals/README.md +8 -0
- package/skills/shared/ab-testing/evals/cases.yaml +49 -0
- package/skills/shared/ab-testing/references/pitfalls.md +74 -0
- package/skills/shared/ab-testing/references/sample-size-and-cuped.md +128 -0
- package/skills/shared/ab-testing/scripts/verify.sh +89 -0
- package/skills/shared/accessibility/SKILL.md +216 -0
- package/skills/shared/accessibility/evals/README.md +3 -0
- package/skills/shared/accessibility/evals/cases.yaml +47 -0
- package/skills/shared/accessibility/references/aria-patterns.md +113 -0
- package/skills/shared/accessibility/references/wcag22-checklist.md +83 -0
- package/skills/shared/accessibility/scripts/verify.sh +103 -0
- package/skills/shared/agent-eval/SKILL.md +187 -0
- package/skills/shared/agent-eval/evals/README.md +12 -0
- package/skills/shared/agent-eval/evals/cases.yaml +45 -0
- package/skills/shared/agent-eval/references/judge-design.md +118 -0
- package/skills/shared/agent-eval/references/runner-and-gate.md +183 -0
- package/skills/shared/agent-eval/scripts/verify.sh +161 -0
- package/skills/shared/agent-safety/SKILL.md +169 -0
- package/skills/shared/agent-safety/evals/README.md +12 -0
- package/skills/shared/agent-safety/evals/cases.yaml +46 -0
- package/skills/shared/agent-safety/references/threat-model.md +51 -0
- package/skills/shared/analyze/SKILL.md +123 -0
- package/skills/shared/analyze/evals/README.md +72 -0
- package/skills/shared/analyze/evals/cases.yaml +74 -0
- package/skills/shared/angular/SKILL.md +275 -0
- package/skills/shared/angular/evals/README.md +3 -0
- package/skills/shared/angular/evals/cases.yaml +38 -0
- package/skills/shared/angular/references/migration.md +81 -0
- package/skills/shared/angular/references/signals-rxjs.md +92 -0
- package/skills/shared/angular/scripts/verify.sh +122 -0
- package/skills/shared/api-connector-builder/SKILL.md +268 -0
- package/skills/shared/api-connector-builder/evals/README.md +11 -0
- package/skills/shared/api-connector-builder/evals/cases.yaml +47 -0
- package/skills/shared/api-connector-builder/references/auth-flows.md +132 -0
- package/skills/shared/api-connector-builder/references/pagination.md +144 -0
- package/skills/shared/api-connector-builder/scripts/verify.sh +172 -0
- package/skills/shared/api-design/SKILL.md +182 -0
- package/skills/shared/api-design/evals/README.md +3 -0
- package/skills/shared/api-design/evals/cases.yaml +45 -0
- package/skills/shared/api-design/references/graphql-design.md +70 -0
- package/skills/shared/api-design/references/openapi-contract.md +86 -0
- package/skills/shared/api-design/references/rest-conventions.md +63 -0
- package/skills/shared/api-design/references/versioning-and-evolution.md +49 -0
- package/skills/shared/api-design/scripts/verify.sh +138 -0
- package/skills/shared/astro/SKILL.md +257 -0
- package/skills/shared/astro/evals/README.md +3 -0
- package/skills/shared/astro/evals/cases.yaml +41 -0
- package/skills/shared/astro/references/content-layer.md +118 -0
- package/skills/shared/astro/references/deploy-and-integrations.md +163 -0
- package/skills/shared/astro/scripts/verify.sh +137 -0
- package/skills/shared/author-skill/SKILL.md +194 -0
- package/skills/shared/author-skill/evals/README.md +66 -0
- package/skills/shared/author-skill/evals/cases.yaml +75 -0
- package/skills/shared/author-skill/references/description-recipe.md +85 -0
- package/skills/shared/author-skill/references/eval-authoring.md +108 -0
- package/skills/shared/author-skill/references/skill-conventions.md +95 -0
- package/skills/shared/automation-flows/SKILL.md +122 -0
- package/skills/shared/automation-flows/evals/README.md +5 -0
- package/skills/shared/automation-flows/evals/cases.yaml +44 -0
- package/skills/shared/automation-flows/references/error-handling.md +58 -0
- package/skills/shared/automation-flows/references/n8n-workflow-json.md +63 -0
- package/skills/shared/automation-flows/scripts/verify.sh +78 -0
- package/skills/shared/aws-essentials/SKILL.md +206 -0
- package/skills/shared/aws-essentials/evals/README.md +10 -0
- package/skills/shared/aws-essentials/evals/cases.yaml +44 -0
- package/skills/shared/aws-essentials/references/iam-least-privilege.md +134 -0
- package/skills/shared/aws-essentials/references/rds-cloudfront-recipes.md +127 -0
- package/skills/shared/aws-essentials/scripts/verify.sh +99 -0
- package/skills/shared/backups/SKILL.md +131 -0
- package/skills/shared/backups/evals/README.md +3 -0
- package/skills/shared/backups/evals/cases.yaml +42 -0
- package/skills/shared/backups/references/engine-recipes.md +121 -0
- package/skills/shared/backups/references/restore-runbook.md +65 -0
- package/skills/shared/backups/scripts/verify.sh +80 -0
- package/skills/shared/bash-scripting/SKILL.md +227 -0
- package/skills/shared/bash-scripting/evals/README.md +3 -0
- package/skills/shared/bash-scripting/evals/cases.yaml +45 -0
- package/skills/shared/bash-scripting/references/portability.md +97 -0
- package/skills/shared/bash-scripting/scripts/verify.sh +140 -0
- package/skills/shared/building-agents/SKILL.md +386 -0
- package/skills/shared/building-agents/evals/README.md +68 -0
- package/skills/shared/building-agents/evals/cases.yaml +60 -0
- package/skills/shared/building-agents/references/agent-loops-and-harness.md +371 -0
- package/skills/shared/building-agents/references/evals-and-observability.md +420 -0
- package/skills/shared/building-agents/references/mcp-servers.md +294 -0
- package/skills/shared/building-agents/references/provider-abstraction.md +489 -0
- package/skills/shared/building-agents/references/tools-and-rag.md +417 -0
- package/skills/shared/building-agents/scripts/verify.sh +121 -0
- package/skills/shared/chatbot/SKILL.md +151 -0
- package/skills/shared/chatbot/evals/README.md +13 -0
- package/skills/shared/chatbot/evals/cases.yaml +43 -0
- package/skills/shared/chatbot/references/handoff-and-sales.md +71 -0
- package/skills/shared/chatbot/references/system-prompt-and-guardrails.md +78 -0
- package/skills/shared/chatbot/scripts/verify.sh +162 -0
- package/skills/shared/chrome-extension/SKILL.md +169 -0
- package/skills/shared/chrome-extension/evals/README.md +12 -0
- package/skills/shared/chrome-extension/evals/cases.yaml +40 -0
- package/skills/shared/chrome-extension/references/store-and-migration.md +84 -0
- package/skills/shared/chrome-extension/scripts/verify.sh +62 -0
- package/skills/shared/clarify/SKILL.md +161 -0
- package/skills/shared/clarify/evals/README.md +70 -0
- package/skills/shared/clarify/evals/cases.yaml +71 -0
- package/skills/shared/clickhouse-analytics/SKILL.md +159 -0
- package/skills/shared/clickhouse-analytics/evals/README.md +3 -0
- package/skills/shared/clickhouse-analytics/evals/cases.yaml +45 -0
- package/skills/shared/clickhouse-analytics/references/ingestion-and-mvs.md +109 -0
- package/skills/shared/clickhouse-analytics/references/query-optimization.md +76 -0
- package/skills/shared/clickhouse-analytics/references/schema-and-engines.md +63 -0
- package/skills/shared/clickhouse-analytics/scripts/verify.sh +109 -0
- package/skills/shared/cloudflare/SKILL.md +186 -0
- package/skills/shared/cloudflare/evals/README.md +15 -0
- package/skills/shared/cloudflare/evals/cases.yaml +46 -0
- package/skills/shared/cloudflare/references/storage-primitives.md +104 -0
- package/skills/shared/cloudflare/references/wrangler-config.md +91 -0
- package/skills/shared/cloudflare/scripts/verify.sh +133 -0
- package/skills/shared/code-review/SKILL.md +132 -0
- package/skills/shared/code-review/evals/README.md +3 -0
- package/skills/shared/code-review/evals/cases.yaml +55 -0
- package/skills/shared/code-review/references/pr-workflow.md +67 -0
- package/skills/shared/codebase-onboarding/SKILL.md +128 -0
- package/skills/shared/codebase-onboarding/evals/README.md +3 -0
- package/skills/shared/codebase-onboarding/evals/cases.yaml +69 -0
- package/skills/shared/codebase-onboarding/references/recon-playbook.md +57 -0
- package/skills/shared/codebase-onboarding/scripts/verify.sh +54 -0
- package/skills/shared/compose-multiplatform/SKILL.md +198 -0
- package/skills/shared/compose-multiplatform/evals/README.md +3 -0
- package/skills/shared/compose-multiplatform/evals/cases.yaml +40 -0
- package/skills/shared/compose-multiplatform/references/ios-interop.md +91 -0
- package/skills/shared/compose-multiplatform/references/project-setup.md +96 -0
- package/skills/shared/compose-multiplatform/scripts/verify.sh +123 -0
- package/skills/shared/connect-tool/SKILL.md +163 -0
- package/skills/shared/connect-tool/evals/cases.yaml +58 -0
- package/skills/shared/constitution/SKILL.md +158 -0
- package/skills/shared/constitution/evals/README.md +68 -0
- package/skills/shared/constitution/evals/cases.yaml +72 -0
- package/skills/shared/constitution/references/constitution-template.md +100 -0
- package/skills/shared/context-budget/SKILL.md +114 -0
- package/skills/shared/context-budget/evals/README.md +11 -0
- package/skills/shared/context-budget/evals/cases.yaml +40 -0
- package/skills/shared/context-budget/references/handoff-and-compaction.md +96 -0
- package/skills/shared/continuous-learning/SKILL.md +106 -0
- package/skills/shared/continuous-learning/evals/README.md +16 -0
- package/skills/shared/continuous-learning/evals/cases.yaml +39 -0
- package/skills/shared/continuous-learning/references/lesson-routing.md +106 -0
- package/skills/shared/coolify/SKILL.md +194 -0
- package/skills/shared/coolify/evals/README.md +21 -0
- package/skills/shared/coolify/evals/cases.yaml +46 -0
- package/skills/shared/coolify/references/databases-and-backups.md +99 -0
- package/skills/shared/coolify/references/deploy-recipes.md +105 -0
- package/skills/shared/coolify/references/install-and-proxy.md +80 -0
- package/skills/shared/coolify/scripts/verify.sh +123 -0
- package/skills/shared/cost-tracking/SKILL.md +176 -0
- package/skills/shared/cost-tracking/evals/README.md +3 -0
- package/skills/shared/cost-tracking/evals/cases.yaml +45 -0
- package/skills/shared/cost-tracking/references/cloud-caps.md +52 -0
- package/skills/shared/cost-tracking/references/pricing-tables.md +51 -0
- package/skills/shared/cost-tracking/scripts/verify.sh +135 -0
- package/skills/shared/cpp/SKILL.md +302 -0
- package/skills/shared/cpp/evals/README.md +14 -0
- package/skills/shared/cpp/evals/cases.yaml +44 -0
- package/skills/shared/cpp/references/cmake.md +167 -0
- package/skills/shared/cpp/references/move-and-templates.md +130 -0
- package/skills/shared/cpp/references/undefined-behavior.md +86 -0
- package/skills/shared/cpp/scripts/verify.sh +165 -0
- package/skills/shared/csharp-dotnet/SKILL.md +272 -0
- package/skills/shared/csharp-dotnet/evals/README.md +3 -0
- package/skills/shared/csharp-dotnet/evals/cases.yaml +48 -0
- package/skills/shared/csharp-dotnet/references/aspnetcore.md +99 -0
- package/skills/shared/csharp-dotnet/references/async.md +82 -0
- package/skills/shared/csharp-dotnet/references/efcore.md +96 -0
- package/skills/shared/csharp-dotnet/scripts/verify.sh +90 -0
- package/skills/shared/data-cleaning/SKILL.md +259 -0
- package/skills/shared/data-cleaning/evals/README.md +16 -0
- package/skills/shared/data-cleaning/evals/cases.yaml +57 -0
- package/skills/shared/data-cleaning/references/normalization-recipes.md +136 -0
- package/skills/shared/data-cleaning/references/validation-patterns.md +134 -0
- package/skills/shared/data-cleaning/scripts/verify.sh +115 -0
- package/skills/shared/data-scraper/SKILL.md +130 -0
- package/skills/shared/data-scraper/evals/README.md +3 -0
- package/skills/shared/data-scraper/evals/cases.yaml +46 -0
- package/skills/shared/data-scraper/references/anti-bot.md +85 -0
- package/skills/shared/data-scraper/references/frameworks.md +116 -0
- package/skills/shared/data-scraper/references/legal-compliance.md +64 -0
- package/skills/shared/data-scraper/scripts/verify.sh +166 -0
- package/skills/shared/db-migrations/SKILL.md +237 -0
- package/skills/shared/db-migrations/evals/README.md +10 -0
- package/skills/shared/db-migrations/evals/cases.yaml +46 -0
- package/skills/shared/db-migrations/references/backfill-and-batching.md +105 -0
- package/skills/shared/db-migrations/references/expand-contract-playbook.md +152 -0
- package/skills/shared/db-migrations/references/tools-and-runners.md +88 -0
- package/skills/shared/db-migrations/scripts/verify.sh +112 -0
- package/skills/shared/debug/SKILL.md +188 -0
- package/skills/shared/debug/evals/README.md +88 -0
- package/skills/shared/debug/evals/cases.yaml +74 -0
- package/skills/shared/decision-challenge/SKILL.md +113 -0
- package/skills/shared/decision-challenge/evals/README.md +3 -0
- package/skills/shared/decision-challenge/evals/cases.yaml +42 -0
- package/skills/shared/decision-records/SKILL.md +202 -0
- package/skills/shared/decision-records/evals/README.md +3 -0
- package/skills/shared/decision-records/evals/cases.yaml +43 -0
- package/skills/shared/decision-records/references/templates.md +252 -0
- package/skills/shared/decision-records/scripts/verify.sh +105 -0
- package/skills/shared/deep-learning/SKILL.md +226 -0
- package/skills/shared/deep-learning/evals/README.md +11 -0
- package/skills/shared/deep-learning/evals/cases.yaml +48 -0
- package/skills/shared/deep-learning/references/distributed.md +105 -0
- package/skills/shared/deep-learning/references/training-recipes.md +135 -0
- package/skills/shared/deployment/SKILL.md +374 -0
- package/skills/shared/deployment/evals/README.md +50 -0
- package/skills/shared/deployment/evals/cases.yaml +53 -0
- package/skills/shared/deployment/references/coolify.md +216 -0
- package/skills/shared/deployment/references/dockerfiles-by-stack.md +319 -0
- package/skills/shared/deployment/references/github-actions.md +295 -0
- package/skills/shared/deployment/references/hosting-targets.md +272 -0
- package/skills/shared/deployment/scripts/verify.sh +134 -0
- package/skills/shared/deprecation/SKILL.md +123 -0
- package/skills/shared/deprecation/evals/README.md +3 -0
- package/skills/shared/deprecation/evals/cases.yaml +42 -0
- package/skills/shared/design/IMPECCABLE-LICENSE.txt +191 -0
- package/skills/shared/design/SKILL.md +111 -0
- package/skills/shared/design/THIRD_PARTY.md +26 -0
- package/skills/shared/design/engine/LICENSE +21 -0
- package/skills/shared/design/engine/RUN.md +515 -0
- package/skills/shared/design/engine/UPSTREAM.json +4 -0
- package/skills/shared/design/engine/assets/app.css +216 -0
- package/skills/shared/design/engine/assets/base.css +105 -0
- package/skills/shared/design/engine/assets/base.js +37 -0
- package/skills/shared/design/engine/assets/charts.js +617 -0
- package/skills/shared/design/engine/assets/scenes/stage.css +28 -0
- package/skills/shared/design/engine/assets/scenes/stage.js +133 -0
- package/skills/shared/design/engine/library/app.json +1327 -0
- package/skills/shared/design/engine/library/directions.json +1078 -0
- package/skills/shared/design/engine/library/heroes.json +1086 -0
- package/skills/shared/design/engine/library/motions.json +92 -0
- package/skills/shared/design/engine/library/palettes.json +1485 -0
- package/skills/shared/design/engine/library/photos.json +7240 -0
- package/skills/shared/design/engine/library/sections.json +4429 -0
- package/skills/shared/design/engine/library/sites.json +8350 -0
- package/skills/shared/design/engine/library/type.json +2024 -0
- package/skills/shared/design/engine/references/app-screens.md +1199 -0
- package/skills/shared/design/engine/references/colour.md +141 -0
- package/skills/shared/design/engine/references/copy.md +177 -0
- package/skills/shared/design/engine/references/critique.md +182 -0
- package/skills/shared/design/engine/references/imagery.md +791 -0
- package/skills/shared/design/engine/references/layout.md +292 -0
- package/skills/shared/design/engine/references/motion.md +980 -0
- package/skills/shared/design/engine/references/research.md +356 -0
- package/skills/shared/design/engine/references/scenes.md +174 -0
- package/skills/shared/design/engine/references/tells.md +115 -0
- package/skills/shared/design/engine/references/type.md +170 -0
- package/skills/shared/design/engine/scripts/assets.mjs +865 -0
- package/skills/shared/design/engine/scripts/draw.mjs +584 -0
- package/skills/shared/design/engine/scripts/inspect.mjs +303 -0
- package/skills/shared/design/engine/scripts/lib/app-draw.mjs +203 -0
- package/skills/shared/design/engine/scripts/lib/cdp.mjs +248 -0
- package/skills/shared/design/engine/scripts/lib/probe.mjs +909 -0
- package/skills/shared/design/engine/scripts/lib/rules.mjs +243 -0
- package/skills/shared/design/engine/scripts/lint.mjs +119 -0
- package/skills/shared/design/engine/scripts/scenes.mjs +124 -0
- package/skills/shared/design/evals/cases.yaml +45 -0
- package/skills/shared/design/references/design-md.md +49 -0
- package/skills/shared/design/references/finish-review.md +46 -0
- package/skills/shared/design/references/modes.md +51 -0
- package/skills/shared/digitalocean/SKILL.md +227 -0
- package/skills/shared/digitalocean/evals/README.md +10 -0
- package/skills/shared/digitalocean/evals/cases.yaml +37 -0
- package/skills/shared/digitalocean/references/app-spec.md +126 -0
- package/skills/shared/digitalocean/references/droplet-ops.md +95 -0
- package/skills/shared/digitalocean/scripts/verify.sh +102 -0
- package/skills/shared/django/SKILL.md +263 -0
- package/skills/shared/django/evals/README.md +11 -0
- package/skills/shared/django/evals/cases.yaml +47 -0
- package/skills/shared/django/references/drf.md +109 -0
- package/skills/shared/django/references/orm-performance.md +91 -0
- package/skills/shared/django/references/security.md +81 -0
- package/skills/shared/django/references/testing.md +86 -0
- package/skills/shared/django/scripts/verify.sh +115 -0
- package/skills/shared/docker/SKILL.md +251 -0
- package/skills/shared/docker/evals/README.md +10 -0
- package/skills/shared/docker/evals/cases.yaml +44 -0
- package/skills/shared/docker/references/base-images-and-stages.md +104 -0
- package/skills/shared/docker/references/compose-recipes.md +109 -0
- package/skills/shared/docker/scripts/verify.sh +149 -0
- package/skills/shared/domains-dns/SKILL.md +131 -0
- package/skills/shared/domains-dns/evals/README.md +16 -0
- package/skills/shared/domains-dns/evals/cases.yaml +47 -0
- package/skills/shared/domains-dns/references/record-cookbook.md +94 -0
- package/skills/shared/domains-dns/references/tls-and-acme.md +90 -0
- package/skills/shared/domains-dns/references/verify-and-debug.md +64 -0
- package/skills/shared/domains-dns/scripts/verify.sh +163 -0
- package/skills/shared/drizzle-orm/SKILL.md +231 -0
- package/skills/shared/drizzle-orm/evals/README.md +12 -0
- package/skills/shared/drizzle-orm/evals/cases.yaml +47 -0
- package/skills/shared/drizzle-orm/references/relations-and-drivers.md +118 -0
- package/skills/shared/drizzle-orm/scripts/verify.sh +155 -0
- package/skills/shared/duckdb/SKILL.md +202 -0
- package/skills/shared/duckdb/evals/README.md +31 -0
- package/skills/shared/duckdb/evals/cases.yaml +41 -0
- package/skills/shared/duckdb/references/python-and-interop.md +105 -0
- package/skills/shared/duckdb/references/remote-and-lakehouse.md +101 -0
- package/skills/shared/duckdb/scripts/verify.sh +71 -0
- package/skills/shared/dynamodb/SKILL.md +204 -0
- package/skills/shared/dynamodb/evals/README.md +8 -0
- package/skills/shared/dynamodb/evals/cases.yaml +46 -0
- package/skills/shared/dynamodb/references/access-patterns.md +127 -0
- package/skills/shared/dynamodb/references/capacity-and-limits.md +78 -0
- package/skills/shared/dynamodb/scripts/verify.sh +108 -0
- package/skills/shared/e2e-testing/SKILL.md +233 -0
- package/skills/shared/e2e-testing/evals/README.md +10 -0
- package/skills/shared/e2e-testing/evals/cases.yaml +64 -0
- package/skills/shared/e2e-testing/references/config-and-ci.md +156 -0
- package/skills/shared/e2e-testing/references/flakiness-playbook.md +124 -0
- package/skills/shared/e2e-testing/scripts/verify.sh +117 -0
- package/skills/shared/electron/SKILL.md +209 -0
- package/skills/shared/electron/evals/README.md +13 -0
- package/skills/shared/electron/evals/cases.yaml +38 -0
- package/skills/shared/electron/references/packaging-and-updates.md +122 -0
- package/skills/shared/electron/references/security-and-ipc.md +158 -0
- package/skills/shared/electron/scripts/verify.sh +143 -0
- package/skills/shared/elixir/SKILL.md +209 -0
- package/skills/shared/elixir/evals/README.md +3 -0
- package/skills/shared/elixir/evals/cases.yaml +41 -0
- package/skills/shared/elixir/references/mix-and-releases.md +91 -0
- package/skills/shared/elixir/references/otp-patterns.md +96 -0
- package/skills/shared/elixir/scripts/verify.sh +76 -0
- package/skills/shared/email-deliverability/SKILL.md +148 -0
- package/skills/shared/email-deliverability/evals/README.md +21 -0
- package/skills/shared/email-deliverability/evals/cases.yaml +45 -0
- package/skills/shared/email-deliverability/scripts/verify.sh +98 -0
- package/skills/shared/embeddings-search/SKILL.md +184 -0
- package/skills/shared/embeddings-search/evals/README.md +10 -0
- package/skills/shared/embeddings-search/evals/cases.yaml +44 -0
- package/skills/shared/embeddings-search/references/evaluation.md +86 -0
- package/skills/shared/embeddings-search/references/models.md +73 -0
- package/skills/shared/embeddings-search/scripts/verify.sh +103 -0
- package/skills/shared/error-handling/SKILL.md +273 -0
- package/skills/shared/error-handling/evals/README.md +12 -0
- package/skills/shared/error-handling/evals/cases.yaml +46 -0
- package/skills/shared/error-handling/references/boundaries-and-messaging.md +120 -0
- package/skills/shared/error-handling/references/retry-and-resilience.md +154 -0
- package/skills/shared/error-handling/scripts/verify.sh +110 -0
- package/skills/shared/expo/SKILL.md +243 -0
- package/skills/shared/expo/evals/README.md +13 -0
- package/skills/shared/expo/evals/cases.yaml +44 -0
- package/skills/shared/expo/references/config-plugins.md +117 -0
- package/skills/shared/expo/references/eas-update.md +118 -0
- package/skills/shared/expo/scripts/verify.sh +132 -0
- package/skills/shared/fal/SKILL.md +196 -0
- package/skills/shared/fal/evals/README.md +3 -0
- package/skills/shared/fal/evals/cases.yaml +42 -0
- package/skills/shared/fal/references/models-and-cost.md +53 -0
- package/skills/shared/fal/references/queue-and-webhooks.md +153 -0
- package/skills/shared/fal/scripts/verify.sh +72 -0
- package/skills/shared/fastapi/SKILL.md +469 -0
- package/skills/shared/fastapi/evals/README.md +50 -0
- package/skills/shared/fastapi/evals/cases.yaml +55 -0
- package/skills/shared/fastapi/references/database.md +347 -0
- package/skills/shared/fastapi/references/production.md +338 -0
- package/skills/shared/fastapi/references/security.md +330 -0
- package/skills/shared/fastapi/references/testing.md +349 -0
- package/skills/shared/fastapi/scripts/verify.sh +157 -0
- package/skills/shared/finetuning/SKILL.md +232 -0
- package/skills/shared/finetuning/evals/README.md +13 -0
- package/skills/shared/finetuning/evals/cases.yaml +50 -0
- package/skills/shared/finetuning/references/hyperparameters-and-eval.md +74 -0
- package/skills/shared/finetuning/references/methods.md +189 -0
- package/skills/shared/firebase/SKILL.md +237 -0
- package/skills/shared/firebase/evals/README.md +12 -0
- package/skills/shared/firebase/evals/cases.yaml +45 -0
- package/skills/shared/firebase/references/cloud-functions.md +102 -0
- package/skills/shared/firebase/references/data-modeling.md +108 -0
- package/skills/shared/firebase/references/security-rules.md +137 -0
- package/skills/shared/firebase/scripts/verify.sh +98 -0
- package/skills/shared/flutter/SKILL.md +400 -0
- package/skills/shared/flutter/evals/README.md +54 -0
- package/skills/shared/flutter/evals/cases.yaml +69 -0
- package/skills/shared/flutter/references/architecture-and-state.md +499 -0
- package/skills/shared/flutter/references/i18n-and-dependencies.md +197 -0
- package/skills/shared/flutter/references/performance.md +299 -0
- package/skills/shared/flutter/references/testing.md +385 -0
- package/skills/shared/flutter/references/ui-and-navigation.md +378 -0
- package/skills/shared/flutter/scripts/verify.sh +104 -0
- package/skills/shared/fly-io/SKILL.md +197 -0
- package/skills/shared/fly-io/evals/README.md +3 -0
- package/skills/shared/fly-io/evals/cases.yaml +42 -0
- package/skills/shared/fly-io/references/fly-toml.md +155 -0
- package/skills/shared/fly-io/references/multi-region.md +66 -0
- package/skills/shared/fly-io/scripts/verify.sh +90 -0
- package/skills/shared/ftd/SKILL.md +111 -0
- package/skills/shared/ftd/evals/cases.yaml +66 -0
- package/skills/shared/ftd/evals/routing.json +24 -0
- package/skills/shared/game-design/SKILL.md +146 -0
- package/skills/shared/game-design/evals/README.md +13 -0
- package/skills/shared/game-design/evals/cases.yaml +47 -0
- package/skills/shared/game-design/references/mechanics-and-loops.md +78 -0
- package/skills/shared/game-design/references/playtesting-and-scope.md +58 -0
- package/skills/shared/game-design/references/progression-and-economy.md +70 -0
- package/skills/shared/game-storytelling/SKILL.md +134 -0
- package/skills/shared/game-storytelling/evals/README.md +28 -0
- package/skills/shared/game-storytelling/evals/cases.yaml +51 -0
- package/skills/shared/game-storytelling/references/branching-and-state.md +134 -0
- package/skills/shared/game-storytelling/references/dialogue-tools.md +117 -0
- package/skills/shared/game-storytelling/references/environmental-storytelling.md +71 -0
- package/skills/shared/gamedev-multiplayer/SKILL.md +237 -0
- package/skills/shared/gamedev-multiplayer/evals/README.md +12 -0
- package/skills/shared/gamedev-multiplayer/evals/cases.yaml +44 -0
- package/skills/shared/gamedev-multiplayer/references/godot-high-level-multiplayer.md +133 -0
- package/skills/shared/gamedev-multiplayer/references/prediction-and-latency.md +104 -0
- package/skills/shared/gamedev-multiplayer/references/unity-and-unreal-netcode.md +166 -0
- package/skills/shared/gamedev-pathing/SKILL.md +233 -0
- package/skills/shared/gamedev-pathing/evals/README.md +14 -0
- package/skills/shared/gamedev-pathing/evals/cases.yaml +49 -0
- package/skills/shared/gamedev-pathing/references/navmesh-workflow.md +110 -0
- package/skills/shared/gamedev-pathing/references/search-algorithms.md +135 -0
- package/skills/shared/gamedev-pathing/references/steering-and-avoidance.md +120 -0
- package/skills/shared/gamedev-physics/SKILL.md +225 -0
- package/skills/shared/gamedev-physics/evals/README.md +12 -0
- package/skills/shared/gamedev-physics/evals/cases.yaml +54 -0
- package/skills/shared/gamedev-physics/references/character-controllers.md +120 -0
- package/skills/shared/gamedev-physics/references/determinism-and-queries.md +124 -0
- package/skills/shared/gamedev-physics/references/layers-and-masks.md +115 -0
- package/skills/shared/gamedev-shaders/SKILL.md +232 -0
- package/skills/shared/gamedev-shaders/evals/README.md +14 -0
- package/skills/shared/gamedev-shaders/evals/cases.yaml +45 -0
- package/skills/shared/gamedev-shaders/references/effect-recipes.md +205 -0
- package/skills/shared/gamedev-shaders/references/godot-shading-language.md +133 -0
- package/skills/shared/gamedev-shaders/references/unity-and-unreal-shaders.md +169 -0
- package/skills/shared/gamedev-shipping/SKILL.md +220 -0
- package/skills/shared/gamedev-shipping/evals/README.md +9 -0
- package/skills/shared/gamedev-shipping/evals/cases.yaml +55 -0
- package/skills/shared/gamedev-shipping/references/mobile-and-desktop.md +127 -0
- package/skills/shared/gamedev-shipping/references/stores-and-ci.md +162 -0
- package/skills/shared/gamedev-shipping/references/web-export-headers.md +140 -0
- package/skills/shared/gcp-essentials/SKILL.md +324 -0
- package/skills/shared/gcp-essentials/evals/README.md +12 -0
- package/skills/shared/gcp-essentials/evals/cases.yaml +38 -0
- package/skills/shared/gcp-essentials/references/deploy-recipes.md +81 -0
- package/skills/shared/gcp-essentials/references/iam-and-auth.md +94 -0
- package/skills/shared/gcp-essentials/references/networking-and-sql.md +74 -0
- package/skills/shared/gcp-essentials/scripts/verify.sh +158 -0
- package/skills/shared/git-workflow/SKILL.md +214 -0
- package/skills/shared/git-workflow/evals/README.md +10 -0
- package/skills/shared/git-workflow/evals/cases.yaml +52 -0
- package/skills/shared/git-workflow/references/gitmoji.md +157 -0
- package/skills/shared/git-workflow/references/interactive-rebase.md +89 -0
- package/skills/shared/github-actions/SKILL.md +244 -0
- package/skills/shared/github-actions/evals/README.md +3 -0
- package/skills/shared/github-actions/evals/cases.yaml +45 -0
- package/skills/shared/github-actions/references/caching-and-matrix.md +92 -0
- package/skills/shared/github-actions/references/oidc-deploys.md +130 -0
- package/skills/shared/github-actions/scripts/verify.sh +105 -0
- package/skills/shared/gitlab-auth/SKILL.md +99 -0
- package/skills/shared/gitlab-workflow/SKILL.md +138 -0
- package/skills/shared/go/SKILL.md +390 -0
- package/skills/shared/go/evals/README.md +56 -0
- package/skills/shared/go/evals/cases.yaml +55 -0
- package/skills/shared/go/references/concurrency.md +557 -0
- package/skills/shared/go/references/http-services.md +529 -0
- package/skills/shared/go/references/testing.md +338 -0
- package/skills/shared/go/scripts/verify.sh +134 -0
- package/skills/shared/godot/SKILL.md +300 -0
- package/skills/shared/godot/evals/README.md +13 -0
- package/skills/shared/godot/evals/cases.yaml +50 -0
- package/skills/shared/godot/references/export-and-testing.md +102 -0
- package/skills/shared/godot/references/gdscript-style.md +84 -0
- package/skills/shared/godot/references/godot3-to-4-traps.md +89 -0
- package/skills/shared/godot/references/nodes-scenes-resources.md +109 -0
- package/skills/shared/harness/SKILL.md +316 -0
- package/skills/shared/harness/assets/_TEMPLATE/.env.example +8 -0
- package/skills/shared/harness/assets/_TEMPLATE/CREDENTIALS.md +25 -0
- package/skills/shared/harness/assets/_TEMPLATE/README.md +25 -0
- package/skills/shared/harness/assets/_TEMPLATE/gitignore +10 -0
- package/skills/shared/harness/assets/_TEMPLATE/test_connection.sh +30 -0
- package/skills/shared/harness/evals/README.md +54 -0
- package/skills/shared/harness/evals/cases.yaml +72 -0
- package/skills/shared/harness/examples/audit-example.md +120 -0
- package/skills/shared/harness/references/agents-md-template.md +41 -0
- package/skills/shared/harness/references/audit-report-template.html +140 -0
- package/skills/shared/harness/references/audit-report-template.md +116 -0
- package/skills/shared/harness/references/claude-md-template.md +85 -0
- package/skills/shared/harness/references/daily-curation-automation.md +68 -0
- package/skills/shared/harness/references/inbox-readme-template.md +51 -0
- package/skills/shared/harness/references/ingest-formats.md +185 -0
- package/skills/shared/harness/references/ingest-ignore-defaults.md +48 -0
- package/skills/shared/harness/references/obsidian-scaffolding.md +103 -0
- package/skills/shared/harness/references/providers.yaml +3546 -0
- package/skills/shared/harness/references/tools-readme-template.md +88 -0
- package/skills/shared/harness/references/wiki-archive-template.html +81 -0
- package/skills/shared/harness/references/wiki-article-template.md +60 -0
- package/skills/shared/harness/references/wiki-dashboard-template.html +136 -0
- package/skills/shared/harness/references/wiki-deep-improve-report-template.html +126 -0
- package/skills/shared/harness/references/wiki-gaps-template.md +22 -0
- package/skills/shared/harness/references/wiki-index-template.md +32 -0
- package/skills/shared/harness/references/wiki-protocol.md +926 -0
- package/skills/shared/harness/references/wiki-raw-template.md +7 -0
- package/skills/shared/harness/references/wiki-worklog-template.md +60 -0
- package/skills/shared/hetzner/SKILL.md +203 -0
- package/skills/shared/hetzner/evals/README.md +35 -0
- package/skills/shared/hetzner/evals/cases.yaml +46 -0
- package/skills/shared/hetzner/references/cloud-init.md +120 -0
- package/skills/shared/hetzner/references/plans-and-locations.md +56 -0
- package/skills/shared/hetzner/scripts/verify.sh +122 -0
- package/skills/shared/htmx/SKILL.md +261 -0
- package/skills/shared/htmx/evals/README.md +3 -0
- package/skills/shared/htmx/evals/cases.yaml +38 -0
- package/skills/shared/htmx/references/patterns.md +113 -0
- package/skills/shared/htmx/references/server-contract.md +91 -0
- package/skills/shared/htmx/scripts/verify.sh +93 -0
- package/skills/shared/huggingface/SKILL.md +191 -0
- package/skills/shared/huggingface/evals/README.md +11 -0
- package/skills/shared/huggingface/evals/cases.yaml +41 -0
- package/skills/shared/huggingface/references/endpoints-and-spaces.md +99 -0
- package/skills/shared/huggingface/references/hub-and-cli.md +85 -0
- package/skills/shared/huggingface/references/inference-providers.md +115 -0
- package/skills/shared/huggingface/scripts/verify.sh +123 -0
- package/skills/shared/idea-refinement/SKILL.md +121 -0
- package/skills/shared/idea-refinement/evals/README.md +3 -0
- package/skills/shared/idea-refinement/evals/cases.yaml +42 -0
- package/skills/shared/implement/SKILL.md +383 -0
- package/skills/shared/implement/evals/README.md +56 -0
- package/skills/shared/implement/evals/cases.yaml +43 -0
- package/skills/shared/implement/references/per-task-review.md +46 -0
- package/skills/shared/implement/scripts/review-package +59 -0
- package/skills/shared/implement/scripts/sdd-workspace +47 -0
- package/skills/shared/implement/scripts/task-brief +77 -0
- package/skills/shared/init/SKILL.md +209 -0
- package/skills/shared/init/evals/README.md +49 -0
- package/skills/shared/init/evals/cases.yaml +74 -0
- package/skills/shared/init/references/accompaniment-and-profile.md +122 -0
- package/skills/shared/init/references/discovery.md +90 -0
- package/skills/shared/init/references/recommend-skills.md +115 -0
- package/skills/shared/init/scripts/verify.sh +118 -0
- package/skills/shared/java/SKILL.md +341 -0
- package/skills/shared/java/evals/README.md +23 -0
- package/skills/shared/java/evals/cases.yaml +43 -0
- package/skills/shared/java/references/builds.md +133 -0
- package/skills/shared/java/references/concurrency.md +108 -0
- package/skills/shared/java/references/streams.md +102 -0
- package/skills/shared/java/scripts/verify.sh +107 -0
- package/skills/shared/knowledge-ops/SKILL.md +122 -0
- package/skills/shared/knowledge-ops/evals/README.md +16 -0
- package/skills/shared/knowledge-ops/evals/cases.yaml +50 -0
- package/skills/shared/knowledge-ops/references/gardening-playbook.md +126 -0
- package/skills/shared/kotlin-android/SKILL.md +245 -0
- package/skills/shared/kotlin-android/evals/README.md +13 -0
- package/skills/shared/kotlin-android/evals/cases.yaml +56 -0
- package/skills/shared/kotlin-android/references/architecture.md +200 -0
- package/skills/shared/kotlin-android/references/gradle-setup.md +125 -0
- package/skills/shared/kotlin-android/scripts/verify.sh +109 -0
- package/skills/shared/laravel/SKILL.md +301 -0
- package/skills/shared/laravel/evals/README.md +10 -0
- package/skills/shared/laravel/evals/cases.yaml +45 -0
- package/skills/shared/laravel/references/eloquent-patterns.md +126 -0
- package/skills/shared/laravel/references/queues-and-scheduling.md +153 -0
- package/skills/shared/laravel/scripts/verify.sh +128 -0
- package/skills/shared/level-design/SKILL.md +143 -0
- package/skills/shared/level-design/evals/README.md +35 -0
- package/skills/shared/level-design/evals/cases.yaml +58 -0
- package/skills/shared/level-design/references/blockout-to-art.md +118 -0
- package/skills/shared/level-design/references/guidance-and-readability.md +152 -0
- package/skills/shared/level-design/references/pacing-and-encounters.md +142 -0
- package/skills/shared/llm-pipeline/SKILL.md +150 -0
- package/skills/shared/llm-pipeline/evals/README.md +3 -0
- package/skills/shared/llm-pipeline/evals/cases.yaml +44 -0
- package/skills/shared/llm-pipeline/references/caching-layers.md +60 -0
- package/skills/shared/llm-pipeline/references/litellm-router.md +101 -0
- package/skills/shared/llm-pipeline/scripts/verify.sh +169 -0
- package/skills/shared/machine-learning/SKILL.md +228 -0
- package/skills/shared/machine-learning/evals/README.md +15 -0
- package/skills/shared/machine-learning/evals/cases.yaml +54 -0
- package/skills/shared/machine-learning/references/gbdt-and-tuning.md +83 -0
- package/skills/shared/machine-learning/references/metrics-and-imbalance.md +82 -0
- package/skills/shared/machine-learning/references/pipelines-and-cv.md +135 -0
- package/skills/shared/modal/SKILL.md +290 -0
- package/skills/shared/modal/evals/README.md +29 -0
- package/skills/shared/modal/evals/cases.yaml +50 -0
- package/skills/shared/modal/references/images-gpu-cookbook.md +160 -0
- package/skills/shared/modal/references/web-and-scaling.md +138 -0
- package/skills/shared/modal/scripts/verify.sh +127 -0
- package/skills/shared/mongodb/SKILL.md +342 -0
- package/skills/shared/mongodb/evals/README.md +29 -0
- package/skills/shared/mongodb/evals/cases.yaml +41 -0
- package/skills/shared/mongodb/references/aggregation.md +115 -0
- package/skills/shared/mongodb/references/data-modeling.md +135 -0
- package/skills/shared/mongodb/references/transactions-and-ops.md +128 -0
- package/skills/shared/mongodb/scripts/verify.sh +151 -0
- package/skills/shared/monitoring/SKILL.md +155 -0
- package/skills/shared/monitoring/evals/README.md +3 -0
- package/skills/shared/monitoring/evals/cases.yaml +47 -0
- package/skills/shared/monitoring/references/burn-rate-and-oncall.md +128 -0
- package/skills/shared/monitoring/references/tool-setup.md +154 -0
- package/skills/shared/monitoring/scripts/verify.sh +145 -0
- package/skills/shared/mysql/SKILL.md +249 -0
- package/skills/shared/mysql/evals/README.md +12 -0
- package/skills/shared/mysql/evals/cases.yaml +49 -0
- package/skills/shared/mysql/references/indexing-and-explain.md +161 -0
- package/skills/shared/mysql/references/mysql-vs-mariadb.md +78 -0
- package/skills/shared/mysql/references/online-ddl-and-migrations.md +120 -0
- package/skills/shared/mysql/references/replication-and-ha.md +115 -0
- package/skills/shared/mysql/scripts/verify.sh +141 -0
- package/skills/shared/neon/SKILL.md +218 -0
- package/skills/shared/neon/evals/README.md +11 -0
- package/skills/shared/neon/evals/cases.yaml +45 -0
- package/skills/shared/neon/references/branching-ci.md +86 -0
- package/skills/shared/neon/scripts/verify.sh +78 -0
- package/skills/shared/nestjs/SKILL.md +217 -0
- package/skills/shared/nestjs/evals/README.md +3 -0
- package/skills/shared/nestjs/evals/cases.yaml +38 -0
- package/skills/shared/nestjs/references/cross-cutting.md +135 -0
- package/skills/shared/nestjs/references/testing-recipes.md +105 -0
- package/skills/shared/nestjs/scripts/verify.sh +98 -0
- package/skills/shared/netlify/SKILL.md +208 -0
- package/skills/shared/netlify/evals/README.md +13 -0
- package/skills/shared/netlify/evals/cases.yaml +43 -0
- package/skills/shared/netlify/references/functions.md +97 -0
- package/skills/shared/netlify/references/netlify-toml.md +115 -0
- package/skills/shared/netlify/scripts/verify.sh +95 -0
- package/skills/shared/nextjs/SKILL.md +400 -0
- package/skills/shared/nextjs/evals/README.md +59 -0
- package/skills/shared/nextjs/evals/cases.yaml +56 -0
- package/skills/shared/nextjs/references/data-and-caching.md +309 -0
- package/skills/shared/nextjs/references/metadata.md +208 -0
- package/skills/shared/nextjs/references/performance.md +325 -0
- package/skills/shared/nextjs/references/react.md +383 -0
- package/skills/shared/nextjs/references/security.md +239 -0
- package/skills/shared/nextjs/references/testing.md +290 -0
- package/skills/shared/nextjs/scripts/verify.sh +141 -0
- package/skills/shared/nlp/SKILL.md +225 -0
- package/skills/shared/nlp/evals/README.md +10 -0
- package/skills/shared/nlp/evals/cases.yaml +45 -0
- package/skills/shared/nlp/references/evaluation.md +107 -0
- package/skills/shared/nlp/references/tokenization.md +95 -0
- package/skills/shared/no-code-app/SKILL.md +145 -0
- package/skills/shared/no-code-app/evals/README.md +3 -0
- package/skills/shared/no-code-app/evals/cases.yaml +43 -0
- package/skills/shared/no-code-app/references/platform-limits.md +100 -0
- package/skills/shared/nodejs/SKILL.md +229 -0
- package/skills/shared/nodejs/evals/README.md +3 -0
- package/skills/shared/nodejs/evals/cases.yaml +39 -0
- package/skills/shared/nodejs/references/express5-migration.md +53 -0
- package/skills/shared/nodejs/references/graceful-shutdown.md +73 -0
- package/skills/shared/nodejs/scripts/verify.sh +122 -0
- package/skills/shared/observability/SKILL.md +235 -0
- package/skills/shared/observability/evals/README.md +3 -0
- package/skills/shared/observability/evals/cases.yaml +51 -0
- package/skills/shared/observability/references/collector-config.md +98 -0
- package/skills/shared/observability/references/instrumentation-recipes.md +115 -0
- package/skills/shared/observability/scripts/verify.sh +156 -0
- package/skills/shared/ollama/SKILL.md +213 -0
- package/skills/shared/ollama/evals/README.md +9 -0
- package/skills/shared/ollama/evals/cases.yaml +43 -0
- package/skills/shared/ollama/references/api.md +148 -0
- package/skills/shared/ollama/references/hardware-sizing.md +87 -0
- package/skills/shared/ollama/scripts/verify.sh +116 -0
- package/skills/shared/open-weights/SKILL.md +239 -0
- package/skills/shared/open-weights/evals/README.md +14 -0
- package/skills/shared/open-weights/evals/cases.yaml +42 -0
- package/skills/shared/open-weights/references/licenses.md +123 -0
- package/skills/shared/open-weights/references/model-families.md +83 -0
- package/skills/shared/open-weights/references/sizing-and-quant.md +89 -0
- package/skills/shared/orient/SKILL.md +92 -0
- package/skills/shared/orient/evals/README.md +18 -0
- package/skills/shared/orient/evals/cases.yaml +67 -0
- package/skills/shared/orient/references/explain-ladder.md +93 -0
- package/skills/shared/orient/references/orientation-contract.md +86 -0
- package/skills/shared/parallel/SKILL.md +168 -0
- package/skills/shared/parallel/evals/README.md +62 -0
- package/skills/shared/parallel/evals/cases.yaml +44 -0
- package/skills/shared/performance/SKILL.md +229 -0
- package/skills/shared/performance/evals/README.md +3 -0
- package/skills/shared/performance/evals/cases.yaml +49 -0
- package/skills/shared/performance/references/profiling-playbook.md +54 -0
- package/skills/shared/performance/scripts/verify.sh +94 -0
- package/skills/shared/phoenix/SKILL.md +169 -0
- package/skills/shared/phoenix/evals/README.md +3 -0
- package/skills/shared/phoenix/evals/cases.yaml +40 -0
- package/skills/shared/phoenix/references/auth-and-scopes.md +82 -0
- package/skills/shared/phoenix/references/ecto-patterns.md +93 -0
- package/skills/shared/phoenix/references/liveview.md +134 -0
- package/skills/shared/phoenix/scripts/verify.sh +73 -0
- package/skills/shared/php/SKILL.md +397 -0
- package/skills/shared/php/evals/README.md +12 -0
- package/skills/shared/php/evals/cases.yaml +45 -0
- package/skills/shared/php/references/tooling.md +170 -0
- package/skills/shared/php/references/type-system.md +220 -0
- package/skills/shared/php/scripts/verify.sh +155 -0
- package/skills/shared/plan/SKILL.md +166 -0
- package/skills/shared/plan/evals/README.md +62 -0
- package/skills/shared/plan/evals/cases.yaml +49 -0
- package/skills/shared/plan/references/plan-template.md +153 -0
- package/skills/shared/planetscale/SKILL.md +198 -0
- package/skills/shared/planetscale/evals/README.md +11 -0
- package/skills/shared/planetscale/evals/cases.yaml +46 -0
- package/skills/shared/planetscale/references/deploy-requests.md +75 -0
- package/skills/shared/planetscale/references/no-foreign-keys.md +88 -0
- package/skills/shared/planetscale/scripts/verify.sh +115 -0
- package/skills/shared/planning-with-files/SKILL.md +278 -0
- package/skills/shared/planning-with-files/examples.md +202 -0
- package/skills/shared/planning-with-files/reference.md +218 -0
- package/skills/shared/planning-with-files/scripts/attest-plan.ps1 +118 -0
- package/skills/shared/planning-with-files/scripts/attest-plan.sh +110 -0
- package/skills/shared/planning-with-files/scripts/check-complete.ps1 +44 -0
- package/skills/shared/planning-with-files/scripts/check-complete.sh +46 -0
- package/skills/shared/planning-with-files/scripts/init-session.ps1 +166 -0
- package/skills/shared/planning-with-files/scripts/init-session.sh +284 -0
- package/skills/shared/planning-with-files/scripts/resolve-plan-dir.ps1 +44 -0
- package/skills/shared/planning-with-files/scripts/resolve-plan-dir.sh +76 -0
- package/skills/shared/planning-with-files/scripts/session-catchup.py +438 -0
- package/skills/shared/planning-with-files/scripts/set-active-plan.ps1 +50 -0
- package/skills/shared/planning-with-files/scripts/set-active-plan.sh +50 -0
- package/skills/shared/planning-with-files/templates/findings.md +95 -0
- package/skills/shared/planning-with-files/templates/progress.md +114 -0
- package/skills/shared/planning-with-files/templates/task_plan.md +132 -0
- package/skills/shared/postgresdb/SKILL.md +354 -0
- package/skills/shared/postgresdb/evals/README.md +55 -0
- package/skills/shared/postgresdb/evals/cases.yaml +57 -0
- package/skills/shared/postgresdb/references/migrations.md +279 -0
- package/skills/shared/postgresdb/references/operations-and-security.md +267 -0
- package/skills/shared/postgresdb/references/query-optimization.md +374 -0
- package/skills/shared/postgresdb/references/schema-and-indexing.md +379 -0
- package/skills/shared/postgresdb/scripts/verify.sh +191 -0
- package/skills/shared/prisma-orm/SKILL.md +313 -0
- package/skills/shared/prisma-orm/evals/README.md +12 -0
- package/skills/shared/prisma-orm/evals/cases.yaml +56 -0
- package/skills/shared/prisma-orm/references/migrations-and-v7-upgrade.md +197 -0
- package/skills/shared/prisma-orm/references/queries-and-performance.md +169 -0
- package/skills/shared/prisma-orm/scripts/verify.sh +137 -0
- package/skills/shared/prompt-engineering/SKILL.md +127 -0
- package/skills/shared/prompt-engineering/evals/README.md +11 -0
- package/skills/shared/prompt-engineering/evals/cases.yaml +46 -0
- package/skills/shared/prompt-engineering/references/eval-templates.md +94 -0
- package/skills/shared/prompt-engineering/references/output-contracts.md +120 -0
- package/skills/shared/prompt-engineering/scripts/verify.sh +84 -0
- package/skills/shared/python/SKILL.md +320 -0
- package/skills/shared/python/evals/README.md +19 -0
- package/skills/shared/python/evals/cases.yaml +46 -0
- package/skills/shared/python/references/async.md +136 -0
- package/skills/shared/python/references/stdlib.md +162 -0
- package/skills/shared/python/references/typing.md +160 -0
- package/skills/shared/python/scripts/verify.sh +125 -0
- package/skills/shared/rag/SKILL.md +209 -0
- package/skills/shared/rag/evals/README.md +13 -0
- package/skills/shared/rag/evals/cases.yaml +45 -0
- package/skills/shared/rag/references/evaluation.md +99 -0
- package/skills/shared/rag/references/pipeline.md +151 -0
- package/skills/shared/rag/scripts/verify.sh +99 -0
- package/skills/shared/rails/SKILL.md +264 -0
- package/skills/shared/rails/evals/README.md +12 -0
- package/skills/shared/rails/evals/cases.yaml +47 -0
- package/skills/shared/rails/references/activerecord.md +148 -0
- package/skills/shared/rails/references/hotwire.md +139 -0
- package/skills/shared/rails/references/testing.md +110 -0
- package/skills/shared/rails/scripts/verify.sh +128 -0
- package/skills/shared/railway/SKILL.md +245 -0
- package/skills/shared/railway/evals/README.md +14 -0
- package/skills/shared/railway/evals/cases.yaml +44 -0
- package/skills/shared/railway/references/cli-cookbook.md +137 -0
- package/skills/shared/railway/references/config-as-code.md +120 -0
- package/skills/shared/railway/scripts/verify.sh +162 -0
- package/skills/shared/react/SKILL.md +182 -0
- package/skills/shared/react/evals/README.md +3 -0
- package/skills/shared/react/evals/cases.yaml +43 -0
- package/skills/shared/react/references/data-and-state.md +152 -0
- package/skills/shared/react/references/performance.md +75 -0
- package/skills/shared/react/references/routing.md +99 -0
- package/skills/shared/react/scripts/verify.sh +123 -0
- package/skills/shared/react-native/SKILL.md +215 -0
- package/skills/shared/react-native/evals/README.md +3 -0
- package/skills/shared/react-native/evals/cases.yaml +42 -0
- package/skills/shared/react-native/references/native-modules.md +123 -0
- package/skills/shared/react-native/references/performance-debugging.md +46 -0
- package/skills/shared/react-native/scripts/verify.sh +120 -0
- package/skills/shared/redis/SKILL.md +298 -0
- package/skills/shared/redis/evals/README.md +10 -0
- package/skills/shared/redis/evals/cases.yaml +43 -0
- package/skills/shared/redis/references/caching.md +116 -0
- package/skills/shared/redis/references/locks-and-rate-limiting.md +140 -0
- package/skills/shared/redis/references/queues.md +102 -0
- package/skills/shared/redis/scripts/verify.sh +164 -0
- package/skills/shared/render/SKILL.md +256 -0
- package/skills/shared/render/evals/README.md +12 -0
- package/skills/shared/render/evals/cases.yaml +45 -0
- package/skills/shared/render/references/blueprint-reference.md +203 -0
- package/skills/shared/render/scripts/verify.sh +167 -0
- package/skills/shared/replicate/SKILL.md +210 -0
- package/skills/shared/replicate/evals/README.md +9 -0
- package/skills/shared/replicate/evals/cases.yaml +45 -0
- package/skills/shared/replicate/references/cog-packaging.md +89 -0
- package/skills/shared/replicate/references/deployments-api.md +87 -0
- package/skills/shared/replicate/references/webhooks-and-async.md +110 -0
- package/skills/shared/replicate/scripts/verify.sh +162 -0
- package/skills/shared/research-ops/SKILL.md +200 -0
- package/skills/shared/research-ops/evals/README.md +13 -0
- package/skills/shared/research-ops/evals/cases.yaml +38 -0
- package/skills/shared/research-ops/references/credibility-rubric.md +78 -0
- package/skills/shared/research-ops/references/memo-template.md +63 -0
- package/skills/shared/research-ops/scripts/verify.sh +181 -0
- package/skills/shared/review/SKILL.md +314 -0
- package/skills/shared/review/evals/README.md +84 -0
- package/skills/shared/review/evals/cases.yaml +55 -0
- package/skills/shared/ruby/SKILL.md +295 -0
- package/skills/shared/ruby/evals/README.md +12 -0
- package/skills/shared/ruby/evals/cases.yaml +41 -0
- package/skills/shared/ruby/references/gems-and-testing.md +208 -0
- package/skills/shared/ruby/references/metaprogramming.md +161 -0
- package/skills/shared/ruby/scripts/verify.sh +83 -0
- package/skills/shared/runpod/SKILL.md +238 -0
- package/skills/shared/runpod/evals/README.md +11 -0
- package/skills/shared/runpod/evals/cases.yaml +47 -0
- package/skills/shared/runpod/references/cost-and-scaling.md +85 -0
- package/skills/shared/runpod/references/serverless-workers.md +101 -0
- package/skills/shared/runpod/scripts/verify.sh +126 -0
- package/skills/shared/rust/SKILL.md +320 -0
- package/skills/shared/rust/evals/README.md +12 -0
- package/skills/shared/rust/evals/cases.yaml +42 -0
- package/skills/shared/rust/references/async-tokio.md +141 -0
- package/skills/shared/rust/references/axum-service.md +132 -0
- package/skills/shared/rust/references/ownership.md +86 -0
- package/skills/shared/rust/references/testing.md +108 -0
- package/skills/shared/rust/scripts/verify.sh +91 -0
- package/skills/shared/scaling/SKILL.md +137 -0
- package/skills/shared/scaling/evals/README.md +3 -0
- package/skills/shared/scaling/evals/cases.yaml +42 -0
- package/skills/shared/scaling/references/load-testing-k6.md +127 -0
- package/skills/shared/scaling/scripts/example.load.js +24 -0
- package/skills/shared/scaling/scripts/verify.sh +70 -0
- package/skills/shared/sdd/SKILL.md +250 -0
- package/skills/shared/sdd/evals/README.md +60 -0
- package/skills/shared/sdd/evals/cases.yaml +90 -0
- package/skills/shared/sdd/references/model-routing.md +194 -0
- package/skills/shared/sdd-init/SKILL.md +189 -0
- package/skills/shared/sdd-init/evals/README.md +3 -0
- package/skills/shared/sdd-init/evals/cases.yaml +43 -0
- package/skills/shared/secure-coding/SKILL.md +336 -0
- package/skills/shared/secure-coding/evals/README.md +68 -0
- package/skills/shared/secure-coding/evals/cases.yaml +55 -0
- package/skills/shared/secure-coding/references/authn-authz.md +249 -0
- package/skills/shared/secure-coding/references/owasp-by-stack.md +574 -0
- package/skills/shared/secure-coding/references/secrets-and-supply-chain.md +205 -0
- package/skills/shared/secure-coding/references/threat-modeling.md +213 -0
- package/skills/shared/secure-coding/scripts/verify.sh +208 -0
- package/skills/shared/security-scan/SKILL.md +219 -0
- package/skills/shared/security-scan/evals/README.md +14 -0
- package/skills/shared/security-scan/evals/cases.yaml +50 -0
- package/skills/shared/security-scan/references/tools.md +97 -0
- package/skills/shared/security-scan/references/triage.md +92 -0
- package/skills/shared/security-scan/scripts/verify.sh +108 -0
- package/skills/shared/ship/SKILL.md +272 -0
- package/skills/shared/ship/evals/README.md +89 -0
- package/skills/shared/ship/evals/cases.yaml +44 -0
- package/skills/shared/shopify/SKILL.md +229 -0
- package/skills/shared/shopify/evals/README.md +14 -0
- package/skills/shared/shopify/evals/cases.yaml +41 -0
- package/skills/shared/shopify/references/apps-graphql.md +103 -0
- package/skills/shared/shopify/references/checkout-extensibility.md +71 -0
- package/skills/shared/shopify/references/liquid-themes.md +89 -0
- package/skills/shared/shopify/scripts/verify.sh +120 -0
- package/skills/shared/simplify-code/SKILL.md +101 -0
- package/skills/shared/simplify-code/evals/README.md +3 -0
- package/skills/shared/simplify-code/evals/cases.yaml +42 -0
- package/skills/shared/skill-scout/SKILL.md +169 -0
- package/skills/shared/skill-scout/evals/README.md +12 -0
- package/skills/shared/skill-scout/evals/cases.yaml +56 -0
- package/skills/shared/skill-scout/references/install-commands.md +76 -0
- package/skills/shared/skill-scout/scripts/verify.sh +154 -0
- package/skills/shared/solid-js/SKILL.md +260 -0
- package/skills/shared/solid-js/evals/README.md +3 -0
- package/skills/shared/solid-js/evals/cases.yaml +38 -0
- package/skills/shared/solid-js/references/reactivity-deep-dive.md +89 -0
- package/skills/shared/solid-js/references/router-and-start.md +93 -0
- package/skills/shared/solid-js/scripts/verify.sh +130 -0
- package/skills/shared/source-grounded-development/SKILL.md +108 -0
- package/skills/shared/source-grounded-development/evals/README.md +3 -0
- package/skills/shared/source-grounded-development/evals/cases.yaml +42 -0
- package/skills/shared/specify/SKILL.md +391 -0
- package/skills/shared/specify/evals/README.md +73 -0
- package/skills/shared/specify/evals/cases.yaml +93 -0
- package/skills/shared/specify/references/eliciting-requirements.md +117 -0
- package/skills/shared/specify/references/spec-template.md +101 -0
- package/skills/shared/speckit-analyze/SKILL.md +35 -0
- package/skills/shared/speckit-assess-decide/SKILL.md +36 -0
- package/skills/shared/speckit-assess-define/SKILL.md +36 -0
- package/skills/shared/speckit-assess-intake/SKILL.md +38 -0
- package/skills/shared/speckit-assess-research/SKILL.md +36 -0
- package/skills/shared/speckit-assess-shape/SKILL.md +36 -0
- package/skills/shared/speckit-bug-assess/SKILL.md +38 -0
- package/skills/shared/speckit-bug-fix/SKILL.md +37 -0
- package/skills/shared/speckit-bug-test/SKILL.md +37 -0
- package/skills/shared/speckit-checklist/SKILL.md +35 -0
- package/skills/shared/speckit-clarify/SKILL.md +32 -0
- package/skills/shared/speckit-constitution/SKILL.md +35 -0
- package/skills/shared/speckit-converge/SKILL.md +36 -0
- package/skills/shared/speckit-implement/SKILL.md +32 -0
- package/skills/shared/speckit-plan/SKILL.md +37 -0
- package/skills/shared/speckit-specify/SKILL.md +36 -0
- package/skills/shared/speckit-tasks/SKILL.md +34 -0
- package/skills/shared/spreadsheet-ops/SKILL.md +180 -0
- package/skills/shared/spreadsheet-ops/evals/README.md +33 -0
- package/skills/shared/spreadsheet-ops/evals/cases.yaml +42 -0
- package/skills/shared/spreadsheet-ops/references/formula-cookbook.md +70 -0
- package/skills/shared/spreadsheet-ops/references/python-excel.md +87 -0
- package/skills/shared/spreadsheet-ops/references/sheets-api-appsscript.md +118 -0
- package/skills/shared/spreadsheet-ops/scripts/verify.sh +152 -0
- package/skills/shared/spring-boot/SKILL.md +350 -0
- package/skills/shared/spring-boot/evals/README.md +11 -0
- package/skills/shared/spring-boot/evals/cases.yaml +49 -0
- package/skills/shared/spring-boot/references/jpa.md +94 -0
- package/skills/shared/spring-boot/references/security.md +92 -0
- package/skills/shared/spring-boot/references/testing.md +95 -0
- package/skills/shared/spring-boot/scripts/verify.sh +115 -0
- package/skills/shared/sql/SKILL.md +286 -0
- package/skills/shared/sql/evals/README.md +9 -0
- package/skills/shared/sql/evals/cases.yaml +49 -0
- package/skills/shared/sql/references/ctes-and-recursion.md +63 -0
- package/skills/shared/sql/references/joins-and-sets.md +71 -0
- package/skills/shared/sql/references/portability.md +38 -0
- package/skills/shared/sql/references/window-functions.md +72 -0
- package/skills/shared/sql/scripts/verify.sh +139 -0
- package/skills/shared/sqlite-turso/SKILL.md +214 -0
- package/skills/shared/sqlite-turso/evals/README.md +24 -0
- package/skills/shared/sqlite-turso/evals/cases.yaml +45 -0
- package/skills/shared/sqlite-turso/references/embedded-replicas.md +96 -0
- package/skills/shared/sqlite-turso/scripts/verify.sh +95 -0
- package/skills/shared/structured-extraction/SKILL.md +230 -0
- package/skills/shared/structured-extraction/evals/README.md +13 -0
- package/skills/shared/structured-extraction/evals/cases.yaml +70 -0
- package/skills/shared/structured-extraction/references/providers.md +152 -0
- package/skills/shared/structured-extraction/scripts/verify.sh +160 -0
- package/skills/shared/suggest/SKILL.md +123 -0
- package/skills/shared/suggest/evals/README.md +17 -0
- package/skills/shared/suggest/evals/cases.yaml +78 -0
- package/skills/shared/supabase/SKILL.md +268 -0
- package/skills/shared/supabase/evals/README.md +12 -0
- package/skills/shared/supabase/evals/cases.yaml +42 -0
- package/skills/shared/supabase/references/auth-ssr.md +173 -0
- package/skills/shared/supabase/references/rls-cookbook.md +122 -0
- package/skills/shared/supabase/scripts/verify.sh +149 -0
- package/skills/shared/svelte/SKILL.md +238 -0
- package/skills/shared/svelte/evals/README.md +3 -0
- package/skills/shared/svelte/evals/cases.yaml +41 -0
- package/skills/shared/svelte/references/runes.md +97 -0
- package/skills/shared/svelte/references/sveltekit-data.md +156 -0
- package/skills/shared/svelte/scripts/verify.sh +128 -0
- package/skills/shared/swift-ios/SKILL.md +224 -0
- package/skills/shared/swift-ios/evals/README.md +3 -0
- package/skills/shared/swift-ios/evals/cases.yaml +46 -0
- package/skills/shared/swift-ios/references/concurrency.md +132 -0
- package/skills/shared/swift-ios/references/testing.md +112 -0
- package/skills/shared/swift-ios/scripts/verify.sh +98 -0
- package/skills/shared/tasks/SKILL.md +265 -0
- package/skills/shared/tasks/evals/README.md +70 -0
- package/skills/shared/tasks/evals/cases.yaml +75 -0
- package/skills/shared/tauri/SKILL.md +219 -0
- package/skills/shared/tauri/evals/README.md +12 -0
- package/skills/shared/tauri/evals/cases.yaml +46 -0
- package/skills/shared/tauri/references/bundling-distribution.md +129 -0
- package/skills/shared/tauri/references/security.md +143 -0
- package/skills/shared/tauri/scripts/verify.sh +178 -0
- package/skills/shared/technical-writing/SKILL.md +230 -0
- package/skills/shared/technical-writing/evals/README.md +12 -0
- package/skills/shared/technical-writing/evals/cases.yaml +53 -0
- package/skills/shared/technical-writing/references/diataxis-modes.md +131 -0
- package/skills/shared/technical-writing/references/vale-starter.md +90 -0
- package/skills/shared/technical-writing/scripts/verify.sh +83 -0
- package/skills/shared/testing-go/SKILL.md +263 -0
- package/skills/shared/testing-go/evals/README.md +3 -0
- package/skills/shared/testing-go/evals/cases.yaml +46 -0
- package/skills/shared/testing-go/references/coverage-and-benchmarks.md +85 -0
- package/skills/shared/testing-go/references/mocks-and-fakes.md +140 -0
- package/skills/shared/testing-go/references/synctest-and-concurrency.md +82 -0
- package/skills/shared/testing-go/scripts/verify.sh +72 -0
- package/skills/shared/testing-py/SKILL.md +197 -0
- package/skills/shared/testing-py/evals/README.md +5 -0
- package/skills/shared/testing-py/evals/cases.yaml +44 -0
- package/skills/shared/testing-py/references/mocking.md +141 -0
- package/skills/shared/testing-py/references/property-testing.md +99 -0
- package/skills/shared/testing-py/scripts/verify.sh +117 -0
- package/skills/shared/testing-web/SKILL.md +244 -0
- package/skills/shared/testing-web/evals/README.md +11 -0
- package/skills/shared/testing-web/evals/cases.yaml +52 -0
- package/skills/shared/testing-web/references/jest-setup.md +88 -0
- package/skills/shared/testing-web/references/recipes.md +116 -0
- package/skills/shared/testing-web/scripts/verify.sh +111 -0
- package/skills/shared/together-fireworks/SKILL.md +176 -0
- package/skills/shared/together-fireworks/evals/README.md +3 -0
- package/skills/shared/together-fireworks/evals/cases.yaml +50 -0
- package/skills/shared/together-fireworks/references/batch-and-tuning.md +59 -0
- package/skills/shared/together-fireworks/references/models-and-pricing.md +79 -0
- package/skills/shared/together-fireworks/scripts/verify.sh +165 -0
- package/skills/shared/training-data/SKILL.md +226 -0
- package/skills/shared/training-data/evals/README.md +13 -0
- package/skills/shared/training-data/evals/cases.yaml +41 -0
- package/skills/shared/training-data/references/formats.md +118 -0
- package/skills/shared/training-data/references/synthesis-dedup-quality.md +134 -0
- package/skills/shared/translation-l10n/SKILL.md +229 -0
- package/skills/shared/translation-l10n/evals/README.md +3 -0
- package/skills/shared/translation-l10n/evals/cases.yaml +39 -0
- package/skills/shared/translation-l10n/references/icu-cookbook.md +82 -0
- package/skills/shared/translation-l10n/references/rtl-and-bidi.md +60 -0
- package/skills/shared/typescript/SKILL.md +225 -0
- package/skills/shared/typescript/evals/README.md +15 -0
- package/skills/shared/typescript/evals/cases.yaml +46 -0
- package/skills/shared/typescript/references/build-and-monorepo.md +141 -0
- package/skills/shared/typescript/references/type-system.md +162 -0
- package/skills/shared/typescript/scripts/verify.sh +52 -0
- package/skills/shared/ui-engineering/SKILL.md +113 -0
- package/skills/shared/ui-engineering/evals/cases.yaml +38 -0
- package/skills/shared/unity/SKILL.md +282 -0
- package/skills/shared/unity/evals/README.md +8 -0
- package/skills/shared/unity/evals/cases.yaml +43 -0
- package/skills/shared/unity/references/build-and-platforms.md +65 -0
- package/skills/shared/unity/references/input-system.md +102 -0
- package/skills/shared/unity/references/lifecycle-deep-dive.md +75 -0
- package/skills/shared/unreal/SKILL.md +270 -0
- package/skills/shared/unreal/evals/README.md +12 -0
- package/skills/shared/unreal/evals/cases.yaml +45 -0
- package/skills/shared/unreal/references/blueprint-cpp-parity.md +109 -0
- package/skills/shared/unreal/references/gameplay-framework.md +95 -0
- package/skills/shared/unreal/references/packaging.md +83 -0
- package/skills/shared/unslop/SKILL.md +143 -0
- package/skills/shared/unslop/evals/README.md +25 -0
- package/skills/shared/unslop/evals/cases.yaml +61 -0
- package/skills/shared/unsloth/SKILL.md +254 -0
- package/skills/shared/unsloth/evals/README.md +10 -0
- package/skills/shared/unsloth/evals/cases.yaml +42 -0
- package/skills/shared/unsloth/references/export.md +75 -0
- package/skills/shared/unsloth/references/grpo.md +91 -0
- package/skills/shared/unsloth/references/masking-and-templates.md +91 -0
- package/skills/shared/variant-explorer/SKILL.md +93 -0
- package/skills/shared/variant-explorer/evals/cases.yaml +38 -0
- package/skills/shared/vector-db/SKILL.md +189 -0
- package/skills/shared/vector-db/evals/README.md +10 -0
- package/skills/shared/vector-db/evals/cases.yaml +45 -0
- package/skills/shared/vector-db/references/engines.md +175 -0
- package/skills/shared/vector-db/references/tuning.md +62 -0
- package/skills/shared/vector-db/scripts/verify.sh +110 -0
- package/skills/shared/vercel/SKILL.md +242 -0
- package/skills/shared/vercel/evals/README.md +23 -0
- package/skills/shared/vercel/evals/cases.yaml +45 -0
- package/skills/shared/vercel/references/cli-cookbook.md +98 -0
- package/skills/shared/vercel/references/vercel-json.md +120 -0
- package/skills/shared/vercel/scripts/verify.sh +168 -0
- package/skills/shared/verify/SKILL.md +230 -0
- package/skills/shared/verify/evals/README.md +78 -0
- package/skills/shared/verify/evals/cases.yaml +104 -0
- package/skills/shared/vllm/SKILL.md +235 -0
- package/skills/shared/vllm/evals/README.md +9 -0
- package/skills/shared/vllm/evals/cases.yaml +47 -0
- package/skills/shared/vllm/references/flags-and-endpoints.md +105 -0
- package/skills/shared/vllm/references/memory-and-throughput.md +78 -0
- package/skills/shared/vue-nuxt/SKILL.md +323 -0
- package/skills/shared/vue-nuxt/evals/README.md +11 -0
- package/skills/shared/vue-nuxt/evals/cases.yaml +49 -0
- package/skills/shared/vue-nuxt/references/data-and-state.md +127 -0
- package/skills/shared/vue-nuxt/references/migration-nuxt4.md +79 -0
- package/skills/shared/vue-nuxt/references/nitro-and-rendering.md +117 -0
- package/skills/shared/vue-nuxt/references/reactivity.md +135 -0
- package/skills/shared/vue-nuxt/scripts/verify.sh +148 -0
- package/skills/shared/webhooks/SKILL.md +229 -0
- package/skills/shared/webhooks/evals/README.md +15 -0
- package/skills/shared/webhooks/evals/cases.yaml +46 -0
- package/skills/shared/webhooks/references/framework-raw-body.md +97 -0
- package/skills/shared/webhooks/references/signature-schemes.md +66 -0
- package/skills/shared/webhooks/scripts/verify.sh +142 -0
- package/skills/shared/wordpress/SKILL.md +224 -0
- package/skills/shared/wordpress/evals/README.md +3 -0
- package/skills/shared/wordpress/evals/cases.yaml +50 -0
- package/skills/shared/wordpress/references/hardening.md +108 -0
- package/skills/shared/wordpress/references/performance.md +80 -0
- package/skills/shared/wordpress/references/woocommerce.md +65 -0
- package/skills/shared/wordpress/scripts/verify.sh +96 -0
- package/skills/shared/worktrees/SKILL.md +204 -0
- package/skills/shared/worktrees/evals/README.md +78 -0
- package/skills/shared/worktrees/evals/cases.yaml +47 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
skill: data-cleaning
|
|
2
|
+
|
|
3
|
+
should_trigger:
|
|
4
|
+
- prompt: "Clean and dedupe this customer CSV and give me something I can re-run every month with the same result."
|
|
5
|
+
why: Core ask — reproducible cleaning pipeline plus dedupe; the headline use case.
|
|
6
|
+
- prompt: "My integer ID column came in as 1001.0 floats and a bunch of rows are duplicated. Fix it."
|
|
7
|
+
why: Non-obvious dtype footgun — only this skill explains read-typing (dtype_backend) before deterministic dedupe.
|
|
8
|
+
- prompt: "Normalize these country values — USA, U.S., United States all mean the same thing."
|
|
9
|
+
why: Category normalization via a mapping table; the unmapped→quarantine pattern is this skill's.
|
|
10
|
+
- prompt: "Add a validation gate so bad rows fail loudly before they ever reach my model."
|
|
11
|
+
why: Schema-contract / pandera framing — declare types, ranges, allowed values; fail loud.
|
|
12
|
+
- prompt: "Quarantine the rows that don't pass instead of silently dropping them."
|
|
13
|
+
why: Non-obvious quarantine pattern unique to this skill; not a generic cleaning ask.
|
|
14
|
+
- prompt: "Limpiar y deduplicar este dataset y dejar un pipeline repetible."
|
|
15
|
+
why: Spanish trigger — same reproducible clean+dedupe intent, no English keyword present.
|
|
16
|
+
- prompt: "Why do my dates parse wrong sometimes and a few rows look duplicated after import?"
|
|
17
|
+
why: Symptom-led, never says 'clean' — ambiguous date format + dedupe both live here.
|
|
18
|
+
|
|
19
|
+
should_not_trigger:
|
|
20
|
+
- prompt: "Export this cleaned DataFrame to Excel with a summary chart and conditional formatting."
|
|
21
|
+
route_to: spreadsheet-ops
|
|
22
|
+
why: Output is a styled sheet/formulas/chart; cleaning already ended at the clean table.
|
|
23
|
+
- prompt: "Scrape all the product prices off this catalog website."
|
|
24
|
+
route_to: data-scraper
|
|
25
|
+
why: Acquisition — the rows aren't held yet; cleaning only starts once you have tabular rows.
|
|
26
|
+
- prompt: "Pull the line items out of these invoice PDFs into a table."
|
|
27
|
+
route_to: structured-extraction
|
|
28
|
+
why: Parsing fields out of unstructured blobs into rows, not cleaning rows you already hold.
|
|
29
|
+
- prompt: "Aggregate this 5GB CSV with SQL fast on my laptop."
|
|
30
|
+
route_to: duckdb
|
|
31
|
+
why: OLAP speed over multi-GB files is the bottleneck, not correctness/normalization.
|
|
32
|
+
- prompt: "Build the KPI dashboard from this already-clean table."
|
|
33
|
+
route_to: business-intelligence
|
|
34
|
+
why: Consumes the clean output; the boundary is the validated table.
|
|
35
|
+
- prompt: "Forecast next quarter's revenue from this monthly clean series."
|
|
36
|
+
route_to: forecasting
|
|
37
|
+
why: Modeling on top of clean data, not producing the clean data.
|
|
38
|
+
|
|
39
|
+
capability:
|
|
40
|
+
- scenario: >
|
|
41
|
+
Given a messy customers CSV — an id column read as floats with .0, "N/A" and 999 sentinels in age,
|
|
42
|
+
duplicate rows per customer, country values USA / U.S. / United States, and malformed dates — produce
|
|
43
|
+
a reproducible clean() pipeline plus a pandera schema that types, normalizes, dedupes deterministically,
|
|
44
|
+
validates, and quarantines failures rather than dropping them.
|
|
45
|
+
must_include:
|
|
46
|
+
- Reads with explicit dtype control (dtype_backend="pyarrow" or numpy_nullable + na_values) so ids stay int, not float
|
|
47
|
+
- Profiles first (nulls %, dup count, per-column dtype, cardinality) to drive the plan
|
|
48
|
+
- Normalizes strings with strip/casefold/NFKC before dedupe
|
|
49
|
+
- Maps categories with a mapping table (dict), unmapped → NA/quarantine, not a regex pile
|
|
50
|
+
- Turns sentinels (-1/999/"N/A") into NA, with an explicit clip-vs-reject range decision
|
|
51
|
+
- Parses dates with an explicit format and errors="coerce", then checks the coerced-NaT count
|
|
52
|
+
- Deduplicates deterministically — explicit subset key + stable sort_values + keep
|
|
53
|
+
- Handles missing per column; no bare fillna(0); impute adds a _was_missing flag
|
|
54
|
+
- Defines a pandera DataFrameModel with coerce, nullable, Field checks (isin/ge/le/unique), and lazy=True
|
|
55
|
+
- Quarantines failing rows to an artifact instead of silently dropping them
|
|
56
|
+
- Writes to a NEW output artifact, leaving the raw source untouched
|
|
57
|
+
- Logs a row-count in/out/coerced/quarantined diff and pins library versions
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Normalization recipes — copy-paste
|
|
2
|
+
|
|
3
|
+
Each recipe is deterministic and re-runnable. Drop them into your `normalize(df)` step. Polars equivalents
|
|
4
|
+
at the end for when pandas runs out of RAM.
|
|
5
|
+
|
|
6
|
+
## Category mapping (unmapped → quarantine, never silent pass)
|
|
7
|
+
|
|
8
|
+
A dict is auditable; a regex tower is not. Anything not in the map becomes NA so the schema gate catches it.
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
COUNTRY = {
|
|
12
|
+
"usa": "US", "u.s.": "US", "u.s.a.": "US", "united states": "US", "us": "US",
|
|
13
|
+
"españa": "ES", "espana": "ES", "spain": "ES", "es": "ES",
|
|
14
|
+
"france": "FR", "fr": "FR",
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def map_category(s, mapping):
|
|
18
|
+
key = s.str.strip().str.casefold().str.normalize("NFKC")
|
|
19
|
+
mapped = key.map(mapping)
|
|
20
|
+
unmapped = key.notna() & mapped.isna()
|
|
21
|
+
if unmapped.any():
|
|
22
|
+
# surface the new values so you extend the map deliberately, not silently
|
|
23
|
+
print("UNMAPPED categories:", sorted(key[unmapped].unique()))
|
|
24
|
+
return mapped # unmapped rows are NA -> the schema's isin/nullable=False check rejects them
|
|
25
|
+
|
|
26
|
+
df["country"] = map_category(df["country"], COUNTRY)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Robust date parsing (explicit format, count the casualties)
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
def parse_dates(s, fmt="%Y-%m-%d", utc=True):
|
|
33
|
+
parsed = pd.to_datetime(s, format=fmt, utc=utc, errors="coerce")
|
|
34
|
+
failed = parsed.isna() & s.notna() # coerced to NaT but original wasn't null = parse failure
|
|
35
|
+
if failed.any():
|
|
36
|
+
raise ValueError(f"{failed.sum()} values did not match {fmt!r}: {s[failed].head().tolist()}")
|
|
37
|
+
return parsed
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If a single source genuinely mixes formats, parse each known format and `combine_first`, then assert no NaT
|
|
41
|
+
remains. Never fall back to dayfirst inference — `03/04/2026` is ambiguous and pandas picks silently.
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
def parse_mixed(s, formats=("%Y-%m-%d", "%d/%m/%Y")):
|
|
45
|
+
out = pd.Series(pd.NaT, index=s.index, dtype="datetime64[ns, UTC]")
|
|
46
|
+
for fmt in formats:
|
|
47
|
+
try_ = pd.to_datetime(s, format=fmt, utc=True, errors="coerce")
|
|
48
|
+
out = out.fillna(try_)
|
|
49
|
+
remaining = out.isna() & s.notna()
|
|
50
|
+
assert not remaining.any(), f"{remaining.sum()} dates matched none of {formats}"
|
|
51
|
+
return out
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Unicode / encoding repair
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
# 1. Read with the RIGHT encoding (don't let pandas/locale guess). If you see mojibake like "RodrÃguez",
|
|
58
|
+
# the file is utf-8 misread as latin-1 — re-read as utf-8.
|
|
59
|
+
df = pd.read_csv("raw.csv", encoding="utf-8")
|
|
60
|
+
|
|
61
|
+
# 2. Normalize text: NFKC folds full-width/compatibility forms; strip control chars and zero-width junk.
|
|
62
|
+
import re
|
|
63
|
+
ZERO_WIDTH = re.compile(r"[]")
|
|
64
|
+
def clean_text(s):
|
|
65
|
+
return (s.str.normalize("NFKC")
|
|
66
|
+
.str.replace(ZERO_WIDTH, "", regex=True)
|
|
67
|
+
.str.strip())
|
|
68
|
+
|
|
69
|
+
# 3. Last-resort repair of already-corrupted text (needs `pip install ftfy`):
|
|
70
|
+
# from ftfy import fix_text; df["name"] = df["name"].map(fix_text)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Sentinel → NA
|
|
74
|
+
|
|
75
|
+
Map the per-column sentinels to real NA *before* any numeric check, so means and ranges aren't poisoned.
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
SENTINELS = {
|
|
79
|
+
"age": [-1, 999],
|
|
80
|
+
"income": [-1, 0, 999999], # 0 is a sentinel here only if 0 income is impossible in this dataset
|
|
81
|
+
"rating": [-1],
|
|
82
|
+
}
|
|
83
|
+
for col, vals in SENTINELS.items():
|
|
84
|
+
df[col] = df[col].mask(df[col].isin(vals)) # -> NA; decide drop/impute/quarantine in handle_missing
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Numeric range — clip vs reject
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
# CLIP: out-of-range is plausibly a recording cap → pull to the bound (keeps the row).
|
|
91
|
+
df["age"] = df["age"].clip(lower=0, upper=120)
|
|
92
|
+
|
|
93
|
+
# REJECT: out-of-range is impossible → set NA so the gate quarantines the row (don't fabricate a value).
|
|
94
|
+
df["age"] = df["age"].mask(~df["age"].between(0, 120))
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Decide per column and write the choice down — clipping a fraud-amount silently hides outliers; rejecting a
|
|
98
|
+
sensor reading silently loses data. The right call depends on the field's meaning.
|
|
99
|
+
|
|
100
|
+
## Polars equivalents (clean-at-scale)
|
|
101
|
+
|
|
102
|
+
Same profile→normalize→dedupe→validate shape, lazy and parallel. Pin Polars and stay deterministic.
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
import polars as pl
|
|
106
|
+
|
|
107
|
+
lf = pl.scan_csv("raw.csv", infer_schema_length=10_000) # lazy: nothing reads until .collect()
|
|
108
|
+
|
|
109
|
+
clean = (
|
|
110
|
+
lf
|
|
111
|
+
# strings: strip + lowercase + (NFKC via map if needed)
|
|
112
|
+
.with_columns(pl.col("country").str.strip_chars().str.to_lowercase().alias("country"))
|
|
113
|
+
# category mapping table
|
|
114
|
+
.with_columns(pl.col("country").replace_strict(COUNTRY, default=None))
|
|
115
|
+
# sentinels -> null
|
|
116
|
+
.with_columns(pl.when(pl.col("age").is_in([-1, 999])).then(None).otherwise(pl.col("age")).alias("age"))
|
|
117
|
+
# dates: explicit format, strict=False coerces failures to null (then check the count)
|
|
118
|
+
.with_columns(pl.col("signup").str.to_datetime("%Y-%m-%d", strict=False, time_zone="UTC"))
|
|
119
|
+
# missing: drop rows missing the required key
|
|
120
|
+
.drop_nulls(subset=["customer_id"])
|
|
121
|
+
# dedupe: deterministic — sort then keep first per key
|
|
122
|
+
.sort(["customer_id", "updated_at"], descending=[False, True])
|
|
123
|
+
.unique(subset=["customer_id"], keep="first")
|
|
124
|
+
.collect() # execute the lazy plan
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# fill_null deliberately (with a flag column), never a blind 0:
|
|
128
|
+
clean = clean.with_columns(
|
|
129
|
+
pl.col("income").is_null().alias("income_was_missing"),
|
|
130
|
+
pl.col("income").fill_null(strategy="mean"),
|
|
131
|
+
)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
pandera validates Polars frames too (`import pandera.polars as pa`), so the gate from
|
|
135
|
+
[validation-patterns.md](validation-patterns.md) carries over. Hand multi-GB analytical SQL to
|
|
136
|
+
[`duckdb`](../../duckdb/SKILL.md) — the engine changes, the discipline does not.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Validation patterns — pandera, GX Core, dbt
|
|
2
|
+
|
|
3
|
+
The gate is what makes cleaned data *trustworthy*: it asserts the contract holds and fails loud when next
|
|
4
|
+
month's file drifts. Pick the lightest tool that covers your blast radius.
|
|
5
|
+
|
|
6
|
+
## Which validator
|
|
7
|
+
|
|
8
|
+
| Situation | Use | Why |
|
|
9
|
+
| --- | --- | --- |
|
|
10
|
+
| One pipeline, validate a DataFrame in Python | **pandera** | Lightweight, in-process, lives next to `clean()`; pin `pandera==0.31.1` (supports pandas ≥ 3) |
|
|
11
|
+
| Many datasets/teams, shared data-quality platform, results store + docs | **GX Core 1.0** | Heavier; Data Context / Suites / Checkpoints are infrastructure, overkill for one script |
|
|
12
|
+
| Cleaning lives in a SQL warehouse, not Python | **dbt** model contracts + tests | Contract enforced at build; tests run post-materialization |
|
|
13
|
+
|
|
14
|
+
Default to pandera. Escalate only when the heavier tool's features are actually needed.
|
|
15
|
+
|
|
16
|
+
## Pandera — the full DataFrameModel
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
import pandera.pandas as pa
|
|
20
|
+
from pandera.typing import Series
|
|
21
|
+
|
|
22
|
+
class CustomerSchema(pa.DataFrameModel):
|
|
23
|
+
customer_id: Series[int] = pa.Field(unique=True, ge=1)
|
|
24
|
+
country: Series[str] = pa.Field(isin=["US", "ES", "FR"])
|
|
25
|
+
age: Series[float] = pa.Field(ge=0, le=120, nullable=True)
|
|
26
|
+
email: Series[str] = pa.Field(str_matches=r"^[^@\s]+@[^@\s]+\.[^@\s]+$", nullable=True)
|
|
27
|
+
signup: Series[pa.DateTime] = pa.Field(nullable=False)
|
|
28
|
+
|
|
29
|
+
class Config:
|
|
30
|
+
strict = True # reject unexpected columns — schema drift fails the build
|
|
31
|
+
coerce = True # coerce to declared dtype; raise if a value can't be coerced
|
|
32
|
+
ordered = False # set True if column order is part of the contract
|
|
33
|
+
|
|
34
|
+
@pa.check("email", name="lowercase_email")
|
|
35
|
+
def email_is_lower(cls, s: Series[str]) -> Series[bool]:
|
|
36
|
+
# custom row-wise check: returns a boolean Series, one per row
|
|
37
|
+
return s.isna() | (s == s.str.lower())
|
|
38
|
+
|
|
39
|
+
@pa.dataframe_check
|
|
40
|
+
def row_budget(cls, df) -> bool:
|
|
41
|
+
# whole-frame invariant: catch a truncated/exploded extract
|
|
42
|
+
return 1 <= len(df) <= 5_000_000
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`coerce` fixes types the contract expects. `nullable` declares which columns may hold NA. Field checks
|
|
46
|
+
(`ge`, `le`, `isin`, `unique`, `str_matches`) are allowed-value rules. `@pa.check` is a custom column
|
|
47
|
+
check; `@pa.dataframe_check` is a whole-frame invariant.
|
|
48
|
+
|
|
49
|
+
## Lazy errors + the quarantine split
|
|
50
|
+
|
|
51
|
+
`lazy=True` collects **every** violation across the frame instead of dying on the first. Use it to split
|
|
52
|
+
valid rows from failing rows — the failures become the quarantine, never a silent drop.
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
def validate_and_split(df, schema):
|
|
56
|
+
"""Return (valid_df, quarantine_df). Quarantine is kept, never discarded."""
|
|
57
|
+
try:
|
|
58
|
+
valid = schema.validate(df, lazy=True)
|
|
59
|
+
return valid, df.iloc[0:0].copy() # empty quarantine — everything passed
|
|
60
|
+
except pa.errors.SchemaErrors as e:
|
|
61
|
+
# failure_cases columns: schema_context, column, check, failure_case, index
|
|
62
|
+
bad_idx = e.failure_cases["index"].dropna().unique()
|
|
63
|
+
quarantine = df.loc[df.index.isin(bad_idx)].copy()
|
|
64
|
+
quarantine["_failed_checks"] = (
|
|
65
|
+
e.failure_cases.dropna(subset=["index"])
|
|
66
|
+
.groupby("index")["check"].agg(lambda c: "; ".join(map(str, c)))
|
|
67
|
+
)
|
|
68
|
+
valid = df.loc[~df.index.isin(bad_idx)]
|
|
69
|
+
return valid, quarantine
|
|
70
|
+
|
|
71
|
+
valid, quarantine = validate_and_split(df, CustomerSchema)
|
|
72
|
+
quarantine.to_parquet("quarantine.parquet") # someone investigates these
|
|
73
|
+
print(f"valid={len(valid)} quarantined={len(quarantine)}") # the audit diff
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Validate **output** always. Validate **input expectations** too when you can state them (e.g. raw must have
|
|
77
|
+
these columns before you start) — it turns a confusing mid-pipeline crash into a clear "the source changed".
|
|
78
|
+
|
|
79
|
+
## GX Core 1.0 — checkpoint sketch
|
|
80
|
+
|
|
81
|
+
GX rebranded its OSS to **GX Core** and shipped 1.0 GA with a simplified API. Reach for it when validation
|
|
82
|
+
is a shared platform across many datasets, not a single script.
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
import great_expectations as gx
|
|
86
|
+
|
|
87
|
+
context = gx.get_context() # Data Context
|
|
88
|
+
ds = context.data_sources.add_pandas("customers_src") # Data Source
|
|
89
|
+
asset = ds.add_dataframe_asset(name="customers")
|
|
90
|
+
batch = asset.add_batch_definition_whole_dataframe("batch")
|
|
91
|
+
|
|
92
|
+
suite = context.suites.add(gx.ExpectationSuite(name="customers_suite"))
|
|
93
|
+
suite.add_expectation(gx.expectations.ExpectColumnValuesToBeBetween(column="age", min_value=0, max_value=120))
|
|
94
|
+
suite.add_expectation(gx.expectations.ExpectColumnValuesToBeInSet(column="country", value_set=["US", "ES", "FR"]))
|
|
95
|
+
|
|
96
|
+
vd = context.validation_definitions.add(
|
|
97
|
+
gx.ValidationDefinition(name="customers_vd", data=batch, suite=suite)
|
|
98
|
+
)
|
|
99
|
+
checkpoint = context.checkpoints.add(gx.Checkpoint(name="customers_cp", validation_definitions=[vd]))
|
|
100
|
+
result = checkpoint.run(batch_parameters={"dataframe": df})
|
|
101
|
+
assert result.success, "GX checkpoint failed — see Data Docs"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The flow is always **Data Context → Data Source → Expectation Suite → Validation Definition → Checkpoint**.
|
|
105
|
+
You get a results store and generated Data Docs — worth the weight only when many people consume them.
|
|
106
|
+
|
|
107
|
+
## dbt — contracts vs tests (cleaning in the warehouse)
|
|
108
|
+
|
|
109
|
+
When cleaning is SQL in a warehouse, the contract lives in the model's YAML. **Contracts** are enforced at
|
|
110
|
+
*build* (the model fails to build if the output is off-contract). **Tests** validate *after*
|
|
111
|
+
materialization.
|
|
112
|
+
|
|
113
|
+
```yaml
|
|
114
|
+
# models/staging/_stg_customers.yml
|
|
115
|
+
models:
|
|
116
|
+
- name: stg_customers
|
|
117
|
+
config:
|
|
118
|
+
contract: { enforced: true } # build fails if columns/types drift — the contract
|
|
119
|
+
columns:
|
|
120
|
+
- name: customer_id
|
|
121
|
+
data_type: bigint
|
|
122
|
+
constraints: [{ type: not_null }, { type: unique }]
|
|
123
|
+
- name: country
|
|
124
|
+
data_type: varchar
|
|
125
|
+
data_tests: # validated post-materialization — the tests
|
|
126
|
+
- accepted_values: { values: ["US", "ES", "FR"] }
|
|
127
|
+
- name: age
|
|
128
|
+
data_type: integer
|
|
129
|
+
data_tests:
|
|
130
|
+
- dbt_utils.accepted_range: { min_value: 0, max_value: 120 }
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Contract = "this shape is guaranteed at build"; tests = "these values held after the run". Use both: the
|
|
134
|
+
contract stops schema drift, the tests catch data drift.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# verify.sh — data-cleaning skill check. Run from anywhere. Read-only by default.
|
|
5
|
+
#
|
|
6
|
+
# Two layers:
|
|
7
|
+
# STATIC (always): SKILL.md exists, frontmatter has the required keys, description is one
|
|
8
|
+
# physical line, and both references/ files exist and are non-empty.
|
|
9
|
+
# RUNTIME (only if pandas + pandera importable): build a tiny fixture with ONE clearly-good
|
|
10
|
+
# row and ONE clearly-bad row (negative age / unmapped country), run a pandera schema with
|
|
11
|
+
# lazy=True, and assert the good row PASSES while the bad row is FLAGGED — proving the gate
|
|
12
|
+
# is not a no-op. If pandas/pandera are absent, print SKIP and still pass the static checks.
|
|
13
|
+
#
|
|
14
|
+
# Writes only inside a private mktemp dir, removed on exit. No network.
|
|
15
|
+
# Exit: 0 on pass or skip; non-zero ONLY on a real failure (missing artifact, malformed
|
|
16
|
+
# frontmatter, or a gate that fails to reject a known-bad row).
|
|
17
|
+
|
|
18
|
+
YELLOW=$'\033[33m'; GREEN=$'\033[32m'; RED=$'\033[31m'; NC=$'\033[0m'
|
|
19
|
+
skip() { printf '%s[skip]%s %s\n' "$YELLOW" "$NC" "$*"; }
|
|
20
|
+
ok() { printf '%s[ok]%s %s\n' "$GREEN" "$NC" "$*"; }
|
|
21
|
+
err() { printf '%s[fail]%s %s\n' "$RED" "$NC" "$*"; }
|
|
22
|
+
|
|
23
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
24
|
+
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
|
|
25
|
+
SKILL="$SKILL_DIR/SKILL.md"
|
|
26
|
+
fail=0
|
|
27
|
+
|
|
28
|
+
# ---- STATIC CHECKS (always run) ----
|
|
29
|
+
if [ ! -f "$SKILL" ]; then
|
|
30
|
+
err "SKILL.md not found at $SKILL"; exit 1
|
|
31
|
+
fi
|
|
32
|
+
ok "SKILL.md present"
|
|
33
|
+
|
|
34
|
+
for key in "name:" "description:" "tags:" "recommends:" "origin:"; do
|
|
35
|
+
if grep -q "^${key}" "$SKILL"; then
|
|
36
|
+
ok "frontmatter has ${key%:}"
|
|
37
|
+
else
|
|
38
|
+
err "frontmatter missing ${key%:}"; fail=1
|
|
39
|
+
fi
|
|
40
|
+
done
|
|
41
|
+
|
|
42
|
+
# description must be exactly one physical line
|
|
43
|
+
desc_lines="$(grep -c '^description:' "$SKILL" || true)"
|
|
44
|
+
if [ "$desc_lines" = "1" ]; then
|
|
45
|
+
ok "description present as a single key line"
|
|
46
|
+
else
|
|
47
|
+
err "expected exactly one 'description:' line, found $desc_lines"; fail=1
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
for ref in "references/validation-patterns.md" "references/normalization-recipes.md"; do
|
|
51
|
+
if [ -s "$SKILL_DIR/$ref" ]; then
|
|
52
|
+
ok "$ref present and non-empty"
|
|
53
|
+
else
|
|
54
|
+
err "$ref missing or empty"; fail=1
|
|
55
|
+
fi
|
|
56
|
+
done
|
|
57
|
+
|
|
58
|
+
if [ "$fail" -ne 0 ]; then
|
|
59
|
+
err "static checks failed"; exit 1
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# ---- RUNTIME GATE CHECK (only if deps present) ----
|
|
63
|
+
if ! command -v python3 >/dev/null 2>&1; then
|
|
64
|
+
skip "python3 not found — ran static checks only"; exit 0
|
|
65
|
+
fi
|
|
66
|
+
if ! python3 -c "import pandas, pandera" >/dev/null 2>&1; then
|
|
67
|
+
skip "pandas/pandera not importable — ran static checks only"; exit 0
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
TMP="$(mktemp -d 2>/dev/null || mktemp -d -t dc_verify)"
|
|
71
|
+
trap 'rm -rf "$TMP"' EXIT
|
|
72
|
+
|
|
73
|
+
python3 - <<'PY'
|
|
74
|
+
import sys
|
|
75
|
+
import pandas as pd
|
|
76
|
+
import pandera.pandas as pa
|
|
77
|
+
from pandera.typing import Series
|
|
78
|
+
|
|
79
|
+
# Fixture: row 1 is clearly GOOD; row 2 is clearly BAD (negative age + unmapped country -> NA).
|
|
80
|
+
COUNTRY = {"usa": "US", "u.s.": "US", "united states": "US", "es": "ES"}
|
|
81
|
+
raw = pd.DataFrame({
|
|
82
|
+
"customer_id": [1, 2],
|
|
83
|
+
"country": ["U.S.", "Atlantis"], # row2 unmapped -> NA -> fails isin
|
|
84
|
+
"age": [42, -5], # row2 out of range -> fails ge(0)
|
|
85
|
+
})
|
|
86
|
+
raw["country"] = raw["country"].str.strip().str.casefold().map(COUNTRY)
|
|
87
|
+
|
|
88
|
+
class Schema(pa.DataFrameModel):
|
|
89
|
+
customer_id: Series[int] = pa.Field(ge=1, unique=True)
|
|
90
|
+
country: Series[str] = pa.Field(isin=["US", "ES", "FR"])
|
|
91
|
+
age: Series[float] = pa.Field(ge=0, le=120)
|
|
92
|
+
class Config:
|
|
93
|
+
coerce = True
|
|
94
|
+
strict = True
|
|
95
|
+
|
|
96
|
+
try:
|
|
97
|
+
Schema.validate(raw, lazy=True)
|
|
98
|
+
print("GATE-NOOP: schema accepted a known-bad row") # gate did nothing -> failure
|
|
99
|
+
sys.exit(1)
|
|
100
|
+
except pa.errors.SchemaErrors as e:
|
|
101
|
+
bad_idx = set(e.failure_cases["index"].dropna().astype(int).unique())
|
|
102
|
+
# The bad row (index 1) must be flagged; the good row (index 0) must NOT be.
|
|
103
|
+
if 1 in bad_idx and 0 not in bad_idx:
|
|
104
|
+
sys.exit(0)
|
|
105
|
+
print(f"GATE-WRONG: flagged indices were {sorted(bad_idx)}; expected {{1}}")
|
|
106
|
+
sys.exit(1)
|
|
107
|
+
PY
|
|
108
|
+
rc=$?
|
|
109
|
+
if [ "$rc" -eq 0 ]; then
|
|
110
|
+
ok "validation gate rejected the bad row and passed the good row (gate is not a no-op)"
|
|
111
|
+
exit 0
|
|
112
|
+
else
|
|
113
|
+
err "validation gate did not behave as documented"
|
|
114
|
+
exit 1
|
|
115
|
+
fi
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: data-scraper
|
|
3
|
+
description: "Use when data lives on a website with no usable API — listings, prices, public records — and the scrape must stay legal and not get blocked: legal gate, extraction path, durable selectors, pacing, resilience. NOT parsing bytes you already hold into fields (that is structured-extraction), NOT a documented API or key (that is api-connector-builder)."
|
|
4
|
+
tags: [web-scraping, crawler, anti-bot, robots-txt, gdpr-compliance, playwright, rate-limiting]
|
|
5
|
+
recommends: [api-connector-builder, structured-extraction, data-cleaning, gdpr-privacy, webhooks]
|
|
6
|
+
origin: ai-hub
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Data scraper
|
|
10
|
+
|
|
11
|
+
You get bytes off websites you do not control — legally, and without getting blocked. You pick the cheapest extraction path that works, build selectors that survive a redesign, pace requests so the host neither bans nor sues you, and you write down the legal basis *before* the first request goes out.
|
|
12
|
+
|
|
13
|
+
One rule above all the others: **scraping is the fallback, not the default.** It is what you reach for only when no API serves the data. If the site has a documented API or you hold a key, stop — that is `../api-connector-builder/SKILL.md`. And once you have the bytes, parsing them into fields is `../structured-extraction/SKILL.md`, normalizing the rows is `../data-cleaning/SKILL.md`. This skill ends the moment you hold the bytes.
|
|
14
|
+
|
|
15
|
+
In 2025-2026 scrapers do not fail on parsing. They fail on a terms-of-service breach, on GDPR exposure, or on being blocked after hammering a host. So the work runs in this order: legal gate → extraction path → tool → selectors → politeness → resilience. Skipping the gate is how you end up in *Meta v. Bright Data*.
|
|
16
|
+
|
|
17
|
+
## The legal gate — run this before any request
|
|
18
|
+
|
|
19
|
+
Walk every item. Each ends in **proceed**, **proceed-narrowed**, or **stop**. One item at stop means the whole scrape stops until you resolve it. Depth and the case law are in `references/legal-compliance.md`.
|
|
20
|
+
|
|
21
|
+
The gates below are the ones with real legal exposure — contract, data-protection law, and anti-circumvention. **robots.txt is not one of them**: it is a voluntary convention with no statutory force, so it informs the decision and never blocks it on its own.
|
|
22
|
+
|
|
23
|
+
- [ ] **Is there an API?** If yes, you are in the wrong skill — never scrape what an API serves. → otherwise proceed.
|
|
24
|
+
- [ ] **Did you read the ToS, and does login/auth apply?** Scraping is most exposed as *breach of contract* when you accepted terms — typically by logging in (*Meta v. Bright Data*, 2024). Logged-out public data weakens that claim. **Prefer logged-out public pages; never bypass auth.** → narrow to public, or stop.
|
|
25
|
+
- [ ] **Is it personal data?** Names, emails, photos, reviews, IP addresses all count. Scraping public personal data for a *new* purpose — aggregation, resale, AI training — is a severe GDPR breach with fines into the tens of millions of EUR. You need a lawful basis (usually legitimate interest) and data minimization. Filter out special categories at the source. → proceed-narrowed (basis + minimization, see `../gdpr-privacy/SKILL.md`), or stop.
|
|
26
|
+
- [ ] **robots.txt and ai.txt?** Read them — they are a *convention*, not law, so this item never stops a scrape on its own. A `Disallow` tells you the host would rather you did not, and `Crawl-delay` tells you its tolerance; both are useful intelligence about where you are likely to get blocked. Weigh it: honoring robots is the low-friction default and the cleanest evidence of good faith, but scraping your own site, one you have permission for, or public pages for research is legitimate whether or not robots allows it. → **advisory: note the decision and move on.**
|
|
27
|
+
- [ ] **Are you about to bypass a control you were shown?** A CAPTCHA, a hard block, an enforced rate limit. *Reddit v. Perplexity AI* (2025) turns precisely on whether anti-bot measures were circumvented — a materially worse position than respectfully pacing public pages. Pacing public data is defensible; defeating a control is the frontier where you lose. → **stop. Do not solve the CAPTCHA. Do not bypass the block.**
|
|
28
|
+
|
|
29
|
+
`hiQ v. LinkedIn` established that scraping *public* data is not automatically a CFAA violation — but that is the floor, not a license. Public + logged-out + no-personal-data is the defensible quadrant, and honoring robots keeps it tidy without being what makes it lawful. Anything outside it, document why and get a human to sign off.
|
|
30
|
+
|
|
31
|
+
## Extraction-path decision table
|
|
32
|
+
|
|
33
|
+
Walk *down* only when the rung above is unavailable. ~94% of modern sites are client-side rendered, yet most still ship machine-readable structured data — parse that before you launch a browser.
|
|
34
|
+
|
|
35
|
+
| Path | Use when | Cost | Detectability |
|
|
36
|
+
|------|----------|------|---------------|
|
|
37
|
+
| **API** (incl. internal XHR/JSON endpoints) | Any documented API, or the page fetches its own JSON you can call directly | Lowest | Lowest — looks like normal traffic |
|
|
38
|
+
| **sitemap.xml + JSON-LD** | `/sitemap.xml` lists the URLs; `<script type="application/ld+json">` carries the records (JSON-LD is Google's preferred structured format, so it is everywhere) | Low — one HTTP GET, parse JSON | Low |
|
|
39
|
+
| **HTML selectors** | Data is in server-rendered HTML, no JSON-LD, no XHR JSON | Medium — selectors drift on redesign | Medium |
|
|
40
|
+
| **Headless browser** | The data only exists after JS executes (SPA, lazy-load, infinite scroll) and there is no callable XHR endpoint | Highest — CPU, RAM, time, easiest to fingerprint | Highest |
|
|
41
|
+
|
|
42
|
+
Before you reach for a browser, open DevTools → Network and look for the XHR/fetch that already returns JSON. Calling that endpoint directly is faster, stabler, and less detectable than rendering the whole page to read what the page itself fetched.
|
|
43
|
+
|
|
44
|
+
## Tool picker
|
|
45
|
+
|
|
46
|
+
| Site profile | Tool | Version (2026) | The one reason |
|
|
47
|
+
|--------------|------|----------------|----------------|
|
|
48
|
+
| Static HTML, no fingerprint wall | `httpx` + `selectolax` (or BeautifulSoup) | current | Fast, no browser; `selectolax` parses far quicker than `lxml` |
|
|
49
|
+
| Static HTML but TLS/JA3 fingerprint blocks you | `curl_cffi` (profile `chrome131`) | current | Impersonates a real browser's TLS/JA3/HTTP2 fingerprint, not just the User-Agent |
|
|
50
|
+
| JS-rendered SPA | Playwright | 1.60.0 (1.59 shipped 2026-04-01) | First-class async, auto-wait, the maintained headless standard |
|
|
51
|
+
| Scalable, resilient, recurring crawler | Crawlee (JS or Python) | actively maintained 2026 | Wraps Playwright + proxy rotation + browserforge fingerprints + a disk-persisted `RequestQueue` that resumes after a crash |
|
|
52
|
+
| Pure-Python static, legacy codebase | Scrapy | current | Battle-tested for static targets — but its Twisted core lags the asyncio ecosystem; pick Crawlee for new work |
|
|
53
|
+
|
|
54
|
+
Default new builds to **Crawlee** when the job is recurring or must not break; reach for plain `httpx`/`curl_cffi` only when the target is static and one-shot.
|
|
55
|
+
|
|
56
|
+
## Robust selectors
|
|
57
|
+
|
|
58
|
+
Selectors break on redesign because they ride on layout, not meaning. Anchor on what is *semantically* stable — `data-*` attributes, ARIA roles, microdata, visible text — never on `nth-child` chains or generated CSS class hashes (`.css-1a2b3c`), which change on every build.
|
|
59
|
+
|
|
60
|
+
```html
|
|
61
|
+
<!-- the page you are scraping -->
|
|
62
|
+
<article data-testid="listing-card">
|
|
63
|
+
<h2 class="css-1a2b3c">Acme Drill 9000</h2>
|
|
64
|
+
<span data-price="129.00">€129,00</span>
|
|
65
|
+
</article>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
# Bad — rides on layout and a build-generated hash; dies on the next deploy
|
|
70
|
+
title = page.query_selector("div:nth-child(3) > article > .css-1a2b3c").inner_text()
|
|
71
|
+
|
|
72
|
+
# Good — anchor on stable semantics, with a fallback chain, and fail loud
|
|
73
|
+
def text_or_raise(card, selectors, field):
|
|
74
|
+
for sel in selectors: # try each selector in priority order
|
|
75
|
+
el = card.query_selector(sel)
|
|
76
|
+
if el and el.inner_text().strip():
|
|
77
|
+
return el.inner_text().strip()
|
|
78
|
+
raise LookupError(f"required field {field!r} not found via {selectors}")
|
|
79
|
+
|
|
80
|
+
card = page.query_selector('[data-testid="listing-card"]')
|
|
81
|
+
title = text_or_raise(card, ["h2", '[itemprop="name"]'], "title")
|
|
82
|
+
price = text_or_raise(card, ["[data-price]", "span:has-text('€')"], "price")
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Two rules baked into that snippet:
|
|
86
|
+
|
|
87
|
+
- **Fallback selector chains.** Give every required field 2-3 ordered selectors. A single redesign rarely breaks all of them at once, so the scraper degrades instead of dying.
|
|
88
|
+
- **Fail loud on a missing required field.** Raise — never silently write `null`. A silent null is a corrupted dataset you discover three months later. A raised error is a fix you make today.
|
|
89
|
+
|
|
90
|
+
## Politeness and anti-block
|
|
91
|
+
|
|
92
|
+
Concrete numbers beat "be respectful." Depth — fingerprint profiles, header sets, proxy taxonomy — is in `references/anti-bot.md`.
|
|
93
|
+
|
|
94
|
+
- **Pace.** Start at **1 request per 1-3 seconds per host**, concurrency capped at **2-5 per host**. Tune *down* if you see 429s, never up to chase speed.
|
|
95
|
+
- **Backoff with jitter.** On a transient error, exponential backoff *plus* random jitter — `delay = base * 2**attempt + random(0, base)`. Without jitter, every worker retries in lockstep and you self-DDoS the host.
|
|
96
|
+
- **Honor 429 and `Retry-After`.** A 429 with `Retry-After: 30` means wait 30 seconds, not retry immediately. Ignoring it is the fastest route to an IP ban.
|
|
97
|
+
- **Conditional GET.** Send `If-Modified-Since` / `If-None-Match` (ETag) on re-crawls. A `304 Not Modified` costs nothing and tells you the page is unchanged — cheaper for you, lighter on the host.
|
|
98
|
+
- **Realistic headers + TLS fingerprint.** A bare `python-requests` User-Agent is an instant tell. Send a full, current browser header set; when JA3/TLS fingerprinting blocks you, switch to `curl_cffi` (`chrome131`) — see the references.
|
|
99
|
+
- **Proxies only when justified.** Residential/mobile proxies are for geo-gating and IP-rate distribution on a target that *permits* the scrape — never to evade a block you were explicitly shown. Budget for them on large recurring jobs; do not reach for them to defeat a hard block (that is the legal line you do not cross).
|
|
100
|
+
|
|
101
|
+
> **Resilience beats speed.** A scraper that runs 50% slower but never breaks is infinitely more valuable than a fast one that dies weekly. Pace for survival, not throughput.
|
|
102
|
+
|
|
103
|
+
## Resilience
|
|
104
|
+
|
|
105
|
+
A recurring crawler must survive crashes, redeploys, and the target's schema drift. Patterns and copy-paste starters are in `references/frameworks.md`.
|
|
106
|
+
|
|
107
|
+
- **Resumable queue.** Use a disk-persisted request queue (Crawlee's `RequestQueue`) so a crash resumes from where it stopped, not from zero. Re-crawling 10k pages because the box rebooted is wasted budget and extra load on the host.
|
|
108
|
+
- **Idempotent writes.** Upsert keyed on a stable id (the source URL or a record id), never blind append — so a re-run repairs rows instead of duplicating them.
|
|
109
|
+
- **Checkpoint every N records.** Flush progress periodically so an interrupt loses minutes, not hours.
|
|
110
|
+
- **Change detection by hash.** Store a content hash per record; only re-process when it changes. This pairs with conditional GET to keep recurring crawls cheap.
|
|
111
|
+
- **Monitor and alert.** Alert on a spike in missing-field errors (schema drift — the site redesigned) and on a spike in 403/429 (you are being blocked). Both are silent-failure modes that rot a dataset until someone checks.
|
|
112
|
+
|
|
113
|
+
## Anti-patterns
|
|
114
|
+
|
|
115
|
+
| Anti-pattern | Why it bites | Do instead |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| Scraping behind a login, then calling it "public data" | Accepting ToS at login is the breach-of-contract hook (*Meta v. Bright Data*) | Stay logged-out on public pages; never bypass auth |
|
|
118
|
+
| Not even reading robots.txt / ai.txt | You lose free intelligence on where you will get blocked, and any good-faith story later | Parse both; honor by default, override deliberately and write down why |
|
|
119
|
+
| No delay, unbounded concurrency | Hammers the host → IP ban, possible CFAA-style exposure | 1 req / 1-3s, cap 2-5 concurrent per host |
|
|
120
|
+
| Selectors on `nth-child` / `.css-1a2b3c` hashes | Break on the next deploy; silent data loss | Anchor on `data-*` / semantic / text, with fallbacks |
|
|
121
|
+
| Silently writing `null` on a missing field | Corrupts the dataset; discovered months later | Raise on a missing *required* field — fail loud |
|
|
122
|
+
| Solving a CAPTCHA / bypassing a hard block | Circumventing a shown control (*Reddit v. Perplexity*) — the worst legal posture | Stop. That control is a "no." |
|
|
123
|
+
| Scraping personal data with no lawful basis | GDPR fines into tens of millions EUR | Establish basis + minimize + filter special categories (`../gdpr-privacy/SKILL.md`) |
|
|
124
|
+
| Storing everything "just in case" | Defeats minimization; expands breach blast radius | Keep only fields the purpose needs; set retention |
|
|
125
|
+
| Launching a browser when JSON-LD was right there | Slowest, most detectable, most expensive path | Check XHR/JSON-LD/sitemap first; browser is last |
|
|
126
|
+
| No resume — a crash restarts from zero | Wastes budget, doubles load on the host | Disk-persisted resumable queue |
|
|
127
|
+
| Hardcoding one User-Agent forever | Stale UA is an easy bot tell | Current full header set; rotate when justified |
|
|
128
|
+
| Retrying with no backoff | Lockstep retries self-DDoS the host | Exponential backoff + jitter; honor `Retry-After` |
|
|
129
|
+
|
|
130
|
+
When in doubt about whether a scrape is defensible, the answer is the gate. Run it, write down the outcome, and only then send a request.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Evals: data-scraper
|
|
2
|
+
|
|
3
|
+
These cases are routing and coverage checks, not an automated pass/fail suite. Read `cases.yaml` against `SKILL.md`. For each `should_trigger` prompt, confirm the description and body would plausibly fire this skill rather than a sibling — note the two non-obvious symptom cases (429/IP-ban and selectors-break-on-redesign, which read as ops problems but are core here) and the Spanish and Catalan triggers. For each `should_not_trigger` prompt, confirm the named `route_to` sibling is the better home and that the boundary in the description would defer to it (structured-extraction once you hold bytes, api-connector-builder when an API exists, data-cleaning for normalization, e2e-testing for UI flow automation, gdpr-privacy for a pure lawful-basis question). For the `capability` case, have a human or a harness LLM produce the response and check it hits every `must_include` item — above all that it runs the legal gate first, walks the extraction path before reaching for a browser, paces per host with backoff and honors 429, uses a resumable queue, fails loud on missing fields, and refuses to bypass a CAPTCHA or hard block. There is no scripted assertion here. The separate `scripts/verify.sh` is the only automated check, and it statically lints an emitted scraper file for a compliance preflight, a rate limit/concurrency cap, retry/backoff, and the absence of CAPTCHA-solver / auth-bypass calls — not these cases.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
skill: data-scraper
|
|
2
|
+
|
|
3
|
+
should_trigger:
|
|
4
|
+
- prompt: "I need to pull all product prices off this competitor's catalog site — they have no API."
|
|
5
|
+
why: Core case — structured data off a site with no API, the canonical scrape.
|
|
6
|
+
- prompt: "Build me a crawler that grabs new public tender listings every morning."
|
|
7
|
+
why: Recurring resilient crawler — routes to the resilience + tool-picker sections.
|
|
8
|
+
- prompt: "My scraper keeps getting 429s and then the IP gets banned after about 200 pages."
|
|
9
|
+
why: Non-obvious — the symptom is a politeness/anti-block failure, not a parsing one.
|
|
10
|
+
- prompt: "The CSS selectors in my scraper break every time the site redesigns."
|
|
11
|
+
why: Non-obvious — points at the robust-selectors section (data-attr / semantic / fallback chains).
|
|
12
|
+
- prompt: "Is it legal for me to scrape this site, and how do I do it without getting sued?"
|
|
13
|
+
why: Legal-gate first — ToS, robots.txt, personal-data, circumvention before any request.
|
|
14
|
+
- prompt: "Vull extreure les dades de contacte d'un directori d'empreses públic."
|
|
15
|
+
why: Catalan trigger — public directory scrape that also nudges the GDPR personal-data gate.
|
|
16
|
+
- prompt: "Necesito scrapear una página de anuncios sin que me bloqueen."
|
|
17
|
+
why: Spanish trigger — extraction plus the anti-block concern.
|
|
18
|
+
|
|
19
|
+
should_not_trigger:
|
|
20
|
+
- prompt: "Parse these 500 saved HTML invoices into a fields table."
|
|
21
|
+
route_to: structured-extraction
|
|
22
|
+
why: Bytes are already in hand; the task is field extraction from documents, not fetching.
|
|
23
|
+
- prompt: "The site publishes a documented REST API with a key — pull the orders into our DB."
|
|
24
|
+
route_to: api-connector-builder
|
|
25
|
+
why: A real API exists; never scrape what an API serves.
|
|
26
|
+
- prompt: "Dedup and normalize this messy scraped CSV — fix the types and nulls."
|
|
27
|
+
route_to: data-cleaning
|
|
28
|
+
why: Downstream of having the rows; normalization, not extraction.
|
|
29
|
+
- prompt: "Automate clicking through our checkout flow to test it end to end."
|
|
30
|
+
route_to: e2e-testing
|
|
31
|
+
why: Browser UI automation for testing a flow, not data extraction.
|
|
32
|
+
- prompt: "What's my GDPR lawful basis for processing this customer list we already hold?"
|
|
33
|
+
route_to: gdpr-privacy
|
|
34
|
+
why: Pure legal-basis question with no scrape — the privacy artifact layer.
|
|
35
|
+
|
|
36
|
+
capability:
|
|
37
|
+
- scenario: "Stand up a resilient daily crawler for a public, JS-rendered listings site that has no API. It contains business names and contact emails. Tell me how to build it so it stays legal and doesn't get blocked."
|
|
38
|
+
must_include:
|
|
39
|
+
- Runs the legal gate before any request — reads ToS, checks robots.txt/ai.txt, and flags the contact emails as personal data needing a lawful basis + minimization (defers basis detail to gdpr-privacy)
|
|
40
|
+
- Walks the extraction path — checks for a callable XHR/JSON endpoint, sitemap.xml, and JSON-LD before committing to a headless browser
|
|
41
|
+
- Picks a tool with a reason — Playwright (1.60) or Crawlee for the JS-rendered SPA, not plain httpx
|
|
42
|
+
- Builds selectors on stable attributes (data-* / semantic / text) with a fallback chain, and fails loud on a missing required field rather than writing null
|
|
43
|
+
- Sets a per-host rate limit (≈1 req / 1-3s, concurrency cap 2-5), exponential backoff with jitter, and honors 429 / Retry-After
|
|
44
|
+
- Uses a resumable disk-persisted queue (Crawlee RequestQueue) and idempotent upserts keyed on a stable id so a crash resumes instead of restarting
|
|
45
|
+
- Refuses to bypass any CAPTCHA or hard block, treating it as a stop and re-running the gate
|
|
46
|
+
- Adds monitoring/alerts on missing-field spikes (schema drift) and 403/429 spikes (blocking)
|