@1aboveio/skills 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -2
- package/bin/cli.mjs +14 -0
- package/bin/select-core.mjs +172 -0
- package/package.json +146 -4
- package/skills/app-dev/airflow/LICENSE +3 -0
- package/skills/app-dev/airflow/SKILL.md +199 -0
- package/skills/app-dev/airflow/release-check.mjs +93 -0
- package/skills/app-dev/android-foundation/LICENSE +3 -0
- package/skills/app-dev/android-foundation/SKILL.md +192 -0
- package/skills/app-dev/android-foundation/assets/android-ci-job.yml +217 -0
- package/skills/app-dev/android-foundation/references/ci.md +87 -0
- package/skills/app-dev/android-foundation/references/gotchas.md +221 -0
- package/skills/app-dev/android-foundation/references/setup.md +164 -0
- package/skills/app-dev/android-foundation/release-check.mjs +93 -0
- package/skills/app-dev/android-foundation/scripts/device-run.sh +176 -0
- package/skills/app-dev/android-foundation/scripts/device-run.test.mjs +172 -0
- package/skills/app-dev/app-debug/LICENSE +3 -0
- package/skills/app-dev/app-debug/SKILL.md +110 -0
- package/skills/app-dev/app-debug/references/common-errors.md +128 -0
- package/skills/app-dev/app-debug/release-check.mjs +93 -0
- package/skills/app-dev/better-auth/LICENSE +3 -0
- package/skills/app-dev/better-auth/SKILL.md +598 -0
- package/skills/app-dev/better-auth/references/feishu-api.md +270 -0
- package/skills/app-dev/better-auth/release-check.mjs +93 -0
- package/skills/app-dev/data-catalog/LICENSE +3 -0
- package/skills/app-dev/data-catalog/SKILL.md +204 -0
- package/skills/app-dev/data-catalog/agents/openai.yaml +3 -0
- package/skills/app-dev/data-catalog/references/data-catalog-conventions.md +75 -0
- package/skills/app-dev/data-catalog/references/field-definitions.md +116 -0
- package/skills/app-dev/data-catalog/references/format.md +121 -0
- package/skills/app-dev/data-catalog/release-check.mjs +93 -0
- package/skills/app-dev/data-catalog/scripts/data-catalog.test.mjs +36 -0
- package/skills/app-dev/data-catalog/scripts/data_catalog.py +1392 -0
- package/skills/app-dev/data-catalog/scripts/persist-conventions-core.mjs +117 -0
- package/skills/app-dev/data-catalog/scripts/persist-conventions.mjs +17 -0
- package/skills/app-dev/data-catalog/scripts/test_data_catalog.py +571 -0
- package/skills/app-dev/ios-foundation/LICENSE +3 -0
- package/skills/app-dev/ios-foundation/SKILL.md +184 -0
- package/skills/app-dev/ios-foundation/references/setup.md +243 -0
- package/skills/app-dev/ios-foundation/release-check.mjs +93 -0
- package/skills/app-dev/monorepo/LICENSE +3 -0
- package/skills/app-dev/monorepo/SKILL.md +462 -0
- package/skills/app-dev/monorepo/release-check.mjs +93 -0
- package/skills/app-dev/nextjs-fullstack/LICENSE +3 -0
- package/skills/app-dev/nextjs-fullstack/SKILL.md +211 -0
- package/skills/app-dev/nextjs-fullstack/conventions.md +318 -0
- package/skills/app-dev/nextjs-fullstack/frontend-conventions.md +61 -0
- package/skills/app-dev/nextjs-fullstack/nextjs16.md +287 -0
- package/skills/app-dev/nextjs-fullstack/release-check.mjs +93 -0
- package/skills/app-dev/nextjs-fullstack/server-actions.md +409 -0
- package/skills/app-dev/prisma-setup/LICENSE +3 -0
- package/skills/app-dev/prisma-setup/SKILL.md +181 -0
- package/skills/app-dev/prisma-setup/nextjs.md +258 -0
- package/skills/app-dev/prisma-setup/release-check.mjs +93 -0
- package/skills/app-dev/prisma-setup/turborepo.md +301 -0
- package/skills/app-dev/pyspark/LICENSE +3 -0
- package/skills/app-dev/pyspark/SKILL.md +127 -0
- package/skills/app-dev/pyspark/assets/templates/etl.py +748 -0
- package/skills/app-dev/pyspark/assets/templates/utils/__init__.py +1 -0
- package/skills/app-dev/pyspark/assets/templates/utils/hudi_metadata.py +14 -0
- package/skills/app-dev/pyspark/references/diagnosis-and-profiling.md +169 -0
- package/skills/app-dev/pyspark/references/etl-contract.md +129 -0
- package/skills/app-dev/pyspark/references/production-validation.md +131 -0
- package/skills/app-dev/pyspark/references/reconciliation.md +38 -0
- package/skills/app-dev/pyspark/references/transformation-design.md +190 -0
- package/skills/app-dev/pyspark/references/velocity-feature-calculation.md +193 -0
- package/skills/app-dev/pyspark/release-check.mjs +93 -0
- package/skills/app-dev/pyspark/scripts/spark_eventlog_summary.py +223 -0
- package/skills/app-dev/python-backend/LICENSE +3 -0
- package/skills/app-dev/python-backend/SKILL.md +325 -0
- package/skills/app-dev/python-backend/assets/uv-install.sh +48 -0
- package/skills/app-dev/python-backend/references/uv-installs.md +83 -0
- package/skills/app-dev/python-backend/release-check.mjs +93 -0
- package/skills/app-dev/shadcn/LICENSE +3 -0
- package/skills/app-dev/shadcn/SKILL.md +120 -0
- package/skills/app-dev/shadcn/assets/shadcn-small.png +0 -0
- package/skills/app-dev/shadcn/assets/shadcn.png +0 -0
- package/skills/app-dev/shadcn/cli.md +411 -0
- package/skills/app-dev/shadcn/customization.md +224 -0
- package/skills/app-dev/shadcn/mcp.md +101 -0
- package/skills/app-dev/shadcn/release-check.mjs +93 -0
- package/skills/app-dev/shadcn/rules/base-vs-radix.md +323 -0
- package/skills/app-dev/shadcn/rules/component-selection.md +67 -0
- package/skills/app-dev/shadcn/rules/composition.md +195 -0
- package/skills/app-dev/shadcn/rules/data-table.md +201 -0
- package/skills/app-dev/shadcn/rules/forms.md +255 -0
- package/skills/app-dev/shadcn/rules/icons.md +103 -0
- package/skills/app-dev/shadcn/rules/styling.md +167 -0
- package/skills/app-dev/zod-v4/LICENSE +3 -0
- package/skills/app-dev/zod-v4/SKILL.md +286 -0
- package/skills/app-dev/zod-v4/release-check.mjs +93 -0
- package/skills/cicd/cloud-build/LICENSE +3 -0
- package/skills/cicd/cloud-build/SKILL.md +707 -0
- package/skills/cicd/cloud-build/release-check.mjs +93 -0
- package/skills/cicd/cloud-debug/LICENSE +3 -0
- package/skills/cicd/cloud-debug/SKILL.md +315 -0
- package/skills/cicd/cloud-debug/references/build-failures.md +238 -0
- package/skills/cicd/cloud-debug/references/deploy-failures.md +376 -0
- package/skills/cicd/cloud-debug/references/pipeline-failures.md +378 -0
- package/skills/cicd/cloud-debug/release-check.mjs +93 -0
- package/skills/cicd/cloud-deploy/LICENSE +3 -0
- package/skills/cicd/cloud-deploy/SKILL.md +230 -0
- package/skills/cicd/cloud-deploy/references/config-templates.md +257 -0
- package/skills/cicd/cloud-deploy/release-check.mjs +93 -0
- package/skills/cicd/docker/LICENSE +3 -0
- package/skills/cicd/docker/SKILL.md +151 -0
- package/skills/cicd/docker/release-check.mjs +93 -0
- package/skills/cicd/github-actions/LICENSE +3 -0
- package/skills/cicd/github-actions/SKILL.md +111 -0
- package/skills/cicd/github-actions/references/audit-profile-optimize.md +150 -0
- package/skills/cicd/github-actions/references/ci-case-studies.md +141 -0
- package/skills/cicd/github-actions/references/conditional-ci.md +214 -0
- package/skills/cicd/github-actions/references/debugging.md +13 -0
- package/skills/cicd/github-actions/references/pipeline.md +87 -0
- package/skills/cicd/github-actions/references/post-deploy-and-publishing.md +33 -0
- package/skills/cicd/github-actions/references/runners.md +253 -0
- package/skills/cicd/github-actions/references/security.md +29 -0
- package/skills/cicd/github-actions/references/speed-and-audit.md +115 -0
- package/skills/cicd/github-actions/references/two-pass-reading.md +92 -0
- package/skills/cicd/github-actions/release-check.mjs +93 -0
- package/skills/cicd/github-actions/scripts/ci-run-audit-core.mjs +612 -0
- package/skills/cicd/github-actions/scripts/ci-run-audit.mjs +4 -0
- package/skills/cicd/github-actions/scripts/ci-run-audit.test.mjs +637 -0
- package/skills/cicd/github-flow/LICENSE +3 -0
- package/skills/cicd/github-flow/SKILL.md +123 -0
- package/skills/cicd/github-flow/references/ci-conventions.md +14 -0
- package/skills/cicd/github-flow/release-check.mjs +93 -0
- package/skills/cicd/github-flow/scripts/flow-core.mjs +105 -0
- package/skills/cicd/github-flow/scripts/flow.mjs +81 -0
- package/skills/cicd/github-flow/scripts/flow.test.mjs +114 -0
- package/skills/cicd/github-flow/scripts/persist-conventions-core.mjs +117 -0
- package/skills/cicd/github-flow/scripts/persist-conventions.mjs +49 -0
- package/skills/cicd/github-flow/scripts/persist-conventions.test.mjs +108 -0
- package/skills/cicd/google-cloud/LICENSE +3 -0
- package/skills/cicd/google-cloud/SKILL.md +119 -0
- package/skills/cicd/google-cloud/references/gcs.md +469 -0
- package/skills/cicd/google-cloud/references/iam.md +451 -0
- package/skills/cicd/google-cloud/references/project.md +349 -0
- package/skills/cicd/google-cloud/references/secrets.md +336 -0
- package/skills/cicd/google-cloud/references/vpc.md +312 -0
- package/skills/cicd/google-cloud/release-check.mjs +93 -0
- package/skills/cicd/google-cloud/scripts/create-sa.sh +36 -0
- package/skills/cicd/google-cloud/scripts/gcp-config.sh +31 -0
- package/skills/cicd/google-cloud/scripts/grant-iap.sh +41 -0
- package/skills/cicd/google-cloud/scripts/setup-secrets.sh +48 -0
- package/skills/cicd/mergify/LICENSE +3 -0
- package/skills/cicd/mergify/SKILL.md +102 -0
- package/skills/cicd/mergify/assets/templates/mergify.yml +215 -0
- package/skills/cicd/mergify/assets/templates/ruleset.json +46 -0
- package/skills/cicd/mergify/references/branch-protection.md +282 -0
- package/skills/cicd/mergify/references/configuration.md +274 -0
- package/skills/cicd/mergify/references/diagnosis.md +109 -0
- package/skills/cicd/mergify/references/stacks.md +84 -0
- package/skills/cicd/mergify/references/traps.md +119 -0
- package/skills/cicd/mergify/references/watch-contract.md +274 -0
- package/skills/cicd/mergify/release-check.mjs +93 -0
- package/skills/cicd/mergify/scripts/audit-core.mjs +208 -0
- package/skills/cicd/mergify/scripts/audit.mjs +4 -0
- package/skills/cicd/mergify/scripts/audit.test.mjs +201 -0
- package/skills/cicd/mergify/scripts/entrypoints.test.mjs +106 -0
- package/skills/cicd/mergify/scripts/pr-620-mergify-comments.fixture.json +30 -0
- package/skills/cicd/mergify/scripts/stack-push-core.mjs +258 -0
- package/skills/cicd/mergify/scripts/stack-push.mjs +4 -0
- package/skills/cicd/mergify/scripts/stack-push.test.mjs +233 -0
- package/skills/cicd/mergify/scripts/watch-pr-delivery-core.mjs +1065 -0
- package/skills/cicd/mergify/scripts/watch-pr-delivery.mjs +4 -0
- package/skills/cicd/mergify/scripts/watch-pr-delivery.test.mjs +1826 -0
- package/skills/cicd/podman/LICENSE +3 -0
- package/skills/cicd/podman/SKILL.md +71 -0
- package/skills/cicd/podman/agents/openai.yaml +4 -0
- package/skills/cicd/podman/assets/templates/podman-compose-socket-directory.yml +6 -0
- package/skills/cicd/podman/assets/templates/podman-service-override.conf +3 -0
- package/skills/cicd/podman/references/compose-compatibility.md +70 -0
- package/skills/cicd/podman/references/networking-and-ports.md +74 -0
- package/skills/cicd/podman/references/rootless-services-and-sockets.md +156 -0
- package/skills/cicd/podman/references/troubleshooting.md +98 -0
- package/skills/cicd/podman/release-check.mjs +93 -0
- package/skills/content/article-review/LICENSE +3 -0
- package/skills/content/article-review/SKILL.md +66 -0
- package/skills/content/article-review/references/report-format.md +68 -0
- package/skills/content/article-review/references/template-guide.md +79 -0
- package/skills/content/article-review/references/template-wechat-payments.md +125 -0
- package/skills/content/article-review/release-check.mjs +93 -0
- package/skills/content/article-to-image/LICENSE +3 -0
- package/skills/content/article-to-image/SKILL.md +91 -0
- package/skills/content/article-to-image/references/formats.md +53 -0
- package/skills/content/article-to-image/release-check.mjs +93 -0
- package/skills/content/flowchart-svg/LICENSE +3 -0
- package/skills/content/flowchart-svg/SKILL.md +43 -0
- package/skills/content/flowchart-svg/release-check.mjs +93 -0
- package/skills/content/flowchart-svg/scripts/export_png.sh +8 -0
- package/skills/content/image-gen/LICENSE +3 -0
- package/skills/content/image-gen/SKILL.md +192 -0
- package/skills/content/image-gen/release-check.mjs +93 -0
- package/skills/content/image-gen/scripts/credentials.mjs +217 -0
- package/skills/content/image-gen/scripts/credentials.test.mjs +212 -0
- package/skills/content/image-gen/scripts/generate.mjs +240 -0
- package/skills/content/image-gen/scripts/options.mjs +293 -0
- package/skills/content/image-gen/scripts/options.test.mjs +245 -0
- package/skills/content/mermaid/LICENSE +3 -0
- package/skills/content/mermaid/SKILL.md +635 -0
- package/skills/content/mermaid/release-check.mjs +93 -0
- package/skills/content/wechat-article-writer/LICENSE +3 -0
- package/skills/content/wechat-article-writer/SKILL.md +92 -0
- package/skills/content/wechat-article-writer/references/style-selector.md +133 -0
- package/skills/content/wechat-article-writer/references/writing-rules.md +152 -0
- package/skills/content/wechat-article-writer/release-check.mjs +93 -0
- package/skills/content/wechat-article-writer/templates/wechat-comparison.md +52 -0
- package/skills/content/wechat-article-writer/templates/wechat-howto.md +51 -0
- package/skills/content/wechat-article-writer/templates/wechat-insight.md +50 -0
- package/skills/content/wechat-article-writer/templates/wechat-pitfall.md +52 -0
- package/skills/content/wechat-publisher/LICENSE +3 -0
- package/skills/content/wechat-publisher/SKILL.md +171 -0
- package/skills/content/wechat-publisher/references/api.md +105 -0
- package/skills/content/wechat-publisher/references/layout-rules.md +57 -0
- package/skills/content/wechat-publisher/references/wechat-safe-template.html +86 -0
- package/skills/content/wechat-publisher/release-check.mjs +93 -0
- package/skills/content/wechat-publisher/scripts/md_to_wechat_html.py +194 -0
- package/skills/content/wechat-publisher/scripts/publish.py +239 -0
- package/skills/content/wechat-search/LICENSE +3 -0
- package/skills/content/wechat-search/SKILL.md +211 -0
- package/skills/content/wechat-search/release-check.mjs +93 -0
- package/skills/content/wechat-search/scripts/start-chrome.sh +83 -0
- package/skills/content/xai-search/LICENSE +3 -0
- package/skills/content/xai-search/SKILL.md +79 -0
- package/skills/content/xai-search/release-check.mjs +93 -0
- package/skills/content/xai-search/scripts/xai_search.sh +187 -0
- package/skills/content/xai-search/tests/smoke_test.sh +36 -0
- package/skills/core/distill-writing/LICENSE +3 -0
- package/skills/core/distill-writing/SKILL.md +74 -0
- package/skills/core/distill-writing/references/extraction.md +95 -0
- package/skills/core/distill-writing/references/updating.md +46 -0
- package/skills/core/distill-writing/release-check.mjs +93 -0
- package/skills/core/doc-to-md/LICENSE +3 -0
- package/skills/core/doc-to-md/SKILL.md +78 -0
- package/skills/core/doc-to-md/release-check.mjs +93 -0
- package/skills/core/doc-to-md/scripts/convert.py +157 -0
- package/skills/core/editorial-review/LICENSE +3 -0
- package/skills/core/editorial-review/SKILL.md +79 -0
- package/skills/core/editorial-review/references/checklist.md +94 -0
- package/skills/core/editorial-review/release-check.mjs +93 -0
- package/skills/core/house-style/LICENSE +3 -0
- package/skills/core/house-style/SKILL.md +33 -0
- package/skills/core/house-style/references/defaults.md +66 -0
- package/skills/core/house-style/references/rules.md +267 -0
- package/skills/core/house-style/references/sources.md +27 -0
- package/skills/core/house-style/references/style-en.md +131 -0
- package/skills/core/house-style/references/style-zh.md +141 -0
- package/skills/core/house-style/references/terminology-zh.md +223 -0
- package/skills/core/house-style/release-check.mjs +93 -0
- package/skills/core/house-style/templates/brd.md +103 -0
- package/skills/core/house-style/templates/commercial-proposal.md +93 -0
- package/skills/core/house-style/templates/compliance-policy.md +109 -0
- package/skills/core/house-style/templates/gap-analysis.md +105 -0
- package/skills/core/house-style/templates/general.md +63 -0
- package/skills/core/house-style/templates/integration-guide.md +98 -0
- package/skills/core/house-style/templates/prd.md +81 -0
- package/skills/core/house-style/templates/risk-operations-procedure.md +94 -0
- package/skills/core/house-style/templates/technical-spec.md +96 -0
- package/skills/core/polish-cn/LICENSE +3 -0
- package/skills/core/polish-cn/SKILL.md +102 -0
- package/skills/core/polish-cn/references/brief.md +93 -0
- package/skills/core/polish-cn/references/models.md +76 -0
- package/skills/core/polish-cn/release-check.mjs +93 -0
- package/skills/core/polish-cn/scripts/polish-cn.test.mjs +244 -0
- package/skills/core/polish-cn/scripts/polish_blocks.py +489 -0
- package/skills/core/reg-parser/LICENSE +3 -0
- package/skills/core/reg-parser/SKILL.md +212 -0
- package/skills/core/reg-parser/references/checklist-schema.md +223 -0
- package/skills/core/reg-parser/references/checklists/hk-amlo-checklist.json +1306 -0
- package/skills/core/reg-parser/references/checklists/hk-amlo-checklist.md +469 -0
- package/skills/core/reg-parser/references/checklists/hk-fi-corporate-onboarding-cdd-checklist.json +634 -0
- package/skills/core/reg-parser/references/checklists/hk-fi-corporate-onboarding-cdd-checklist.md +233 -0
- package/skills/core/reg-parser/references/checklists/hk-mso-guideline-checklist.json +2194 -0
- package/skills/core/reg-parser/references/checklists/hk-mso-guideline-checklist.md +771 -0
- package/skills/core/reg-parser/references/checklists/kyc-aml-checklist.md +258 -0
- package/skills/core/reg-parser/references/checklists/visa-vars-checklist.md +1058 -0
- package/skills/core/reg-parser/references/mandates/hk-amlo-cap615.md +389 -0
- package/skills/core/reg-parser/references/mandates/visa-vars.md +205 -0
- package/skills/core/reg-parser/release-check.mjs +93 -0
- package/skills/core/reg-parser/scripts/compare_checklist.py +230 -0
- package/skills/core/reg-parser/scripts/dump_checklist.py +361 -0
- package/skills/core/reg-parser/scripts/preprocess-mandate.sh +187 -0
- package/skills/core/reg-parser/scripts/reg-parser.test.mjs +165 -0
- package/skills/core/reg-parser/scripts/test_quarantine.sh +105 -0
- package/skills/core/reg-parser/scripts/validate_checklist.py +563 -0
- package/skills/core/reg-parser/scripts/validate_mandate.py +273 -0
- package/skills/core/terminology/LICENSE +3 -0
- package/skills/core/terminology/SKILL.md +62 -0
- package/skills/core/terminology/references/format.md +50 -0
- package/skills/core/terminology/references/init.md +32 -0
- package/skills/core/terminology/release-check.mjs +93 -0
- package/skills/core/write-doc/LICENSE +3 -0
- package/skills/core/write-doc/SKILL.md +141 -0
- package/skills/core/write-doc/references/bilingual.md +60 -0
- package/skills/core/write-doc/release-check.mjs +93 -0
- package/skills/engineering/better-review/LICENSE +3 -0
- package/skills/engineering/better-review/SKILL.md +249 -0
- package/skills/engineering/better-review/agents/openai.yaml +9 -0
- package/skills/engineering/better-review/references/domain-hazards.md +53 -0
- package/skills/engineering/better-review/references/passes.md +147 -0
- package/skills/engineering/better-review/references/result.md +151 -0
- package/skills/engineering/better-review/release-check.mjs +93 -0
- package/skills/engineering/better-review/scripts/pr-context.mjs +212 -0
- package/skills/engineering/better-review/scripts/pr-context.test.mjs +168 -0
- package/skills/engineering/better-review/scripts/rereview-scope.mjs +503 -0
- package/skills/engineering/better-review/scripts/rereview-scope.test.mjs +587 -0
- package/skills/engineering/better-review/scripts/scan-diff.mjs +365 -0
- package/skills/engineering/better-review/scripts/scan-diff.test.mjs +414 -0
- package/skills/engineering/better-review/scripts/vendor-sync.test.mjs +96 -0
- package/skills/engineering/e2e-test/LICENSE +3 -0
- package/skills/engineering/e2e-test/SKILL.md +98 -0
- package/skills/engineering/e2e-test/assets/ci-gates.cloudbuild.yaml +24 -0
- package/skills/engineering/e2e-test/references/authoring/auth-flows.md +159 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-config.md +73 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-patterns.md +144 -0
- package/skills/engineering/e2e-test/references/ci-integration.md +25 -0
- package/skills/engineering/e2e-test/references/ci-playwright-container.md +290 -0
- package/skills/engineering/e2e-test/references/presentation-sweep.md +104 -0
- package/skills/engineering/e2e-test/references/reviewing.md +41 -0
- package/skills/engineering/e2e-test/references/route-manifest.md +51 -0
- package/skills/engineering/e2e-test/release-check.mjs +93 -0
- package/skills/engineering/e2e-test/scripts/detect-routes-nextjs.mjs +200 -0
- package/skills/engineering/e2e-test/scripts/presentation-checks.mjs +171 -0
- package/skills/engineering/e2e-test/scripts/presentation-checks.test.mjs +106 -0
- package/skills/engineering/e2e-test/scripts/presentation-perceivability.mjs +179 -0
- package/skills/engineering/e2e-test/scripts/presentation-perceivability.test.mjs +117 -0
- package/skills/engineering/e2e-test/scripts/presentation-reachability.mjs +154 -0
- package/skills/engineering/e2e-test/scripts/presentation-reachability.test.mjs +69 -0
- package/skills/engineering/e2e-test/scripts/presentation-render-health.mjs +141 -0
- package/skills/engineering/e2e-test/scripts/presentation-render-health.test.mjs +98 -0
- package/skills/engineering/e2e-test/scripts/presentation-sweep.mjs +147 -0
- package/skills/engineering/e2e-test/scripts/presentation-sweep.test.mjs +71 -0
- package/skills/engineering/e2e-test/scripts/presentation-temporal.mjs +127 -0
- package/skills/engineering/e2e-test/scripts/presentation-temporal.test.mjs +59 -0
- package/skills/engineering/e2e-test/scripts/project-route-manifest.mjs +82 -0
- package/skills/engineering/e2e-test/scripts/project-route-manifest.test.mjs +76 -0
- package/skills/engineering/e2e-test/scripts/validate-manifest.mjs +106 -0
- package/skills/engineering/engineering-runtime/LICENSE +3 -0
- package/skills/engineering/engineering-runtime/SKILL.md +11 -0
- package/skills/engineering/engineering-runtime/agents/openai.yaml +6 -0
- package/skills/engineering/engineering-runtime/coherence/workflow.json +597 -0
- package/skills/engineering/engineering-runtime/engineering-runtime.test.mjs +68 -0
- package/skills/engineering/engineering-runtime/release-check.mjs +93 -0
- package/skills/engineering/engineering-runtime/scripts/exact-head-artifact.mjs +131 -0
- package/skills/engineering/engineering-runtime/scripts/head-check-set.mjs +398 -0
- package/skills/engineering/engineering-runtime/scripts/invocation-policy.mjs +187 -0
- package/skills/engineering/engineering-runtime/scripts/invocation-policy.test.mjs +95 -0
- package/skills/engineering/engineering-runtime/scripts/main-module.mjs +79 -0
- package/skills/engineering/engineering-runtime/scripts/main-module.test.mjs +288 -0
- package/skills/engineering/engineering-runtime/scripts/mergify-yaml.mjs +11 -0
- package/skills/engineering/engineering-runtime/scripts/package-lock.json +43 -0
- package/skills/engineering/engineering-runtime/scripts/package.json +10 -0
- package/skills/engineering/engineering-runtime/scripts/required-check-plan.mjs +223 -0
- package/skills/engineering/engineering-runtime/scripts/required-check-plan.test.mjs +96 -0
- package/skills/engineering/engineering-runtime/scripts/review-completion.mjs +56 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +595 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +189 -0
- package/skills/engineering/engineering-runtime/scripts/yaml-mapping.mjs +18 -0
- package/skills/engineering/ensure-coverage/LICENSE +3 -0
- package/skills/engineering/ensure-coverage/SKILL.md +129 -0
- package/skills/engineering/ensure-coverage/references/breadth/coverage-ledger.md +92 -0
- package/skills/engineering/ensure-coverage/references/breadth/inventory-contract.md +85 -0
- package/skills/engineering/ensure-coverage/references/breadth/surface-baseline.md +44 -0
- package/skills/engineering/ensure-coverage/references/breadth/surface-discovery.md +16 -0
- package/skills/engineering/ensure-coverage/references/depth/characterization.md +68 -0
- package/skills/engineering/ensure-coverage/references/depth/coverage.config.example.json +19 -0
- package/skills/engineering/ensure-coverage/references/depth/grading.md +35 -0
- package/skills/engineering/ensure-coverage/references/depth/mock-policy.md +57 -0
- package/skills/engineering/ensure-coverage/references/depth/test-smells.md +39 -0
- package/skills/engineering/ensure-coverage/references/enforcement/ci-contract.md +44 -0
- package/skills/engineering/ensure-coverage/references/examples/coverage-ledger.md +110 -0
- package/skills/engineering/ensure-coverage/references/examples/refund-flow.md +35 -0
- package/skills/engineering/ensure-coverage/references/presentation/axis.md +64 -0
- package/skills/engineering/ensure-coverage/references/process/audit-mode.md +27 -0
- package/skills/engineering/ensure-coverage/references/process/output-template.md +139 -0
- package/skills/engineering/ensure-coverage/references/process/test-strategy.md +56 -0
- package/skills/engineering/ensure-coverage/release-check.mjs +93 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-config.schema.json +67 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-file.schema.json +140 -0
- package/skills/engineering/ensure-coverage/scripts/README.md +99 -0
- package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.mjs +182 -0
- package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.test.mjs +96 -0
- package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.mjs +105 -0
- package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.test.mjs +47 -0
- package/skills/engineering/ensure-coverage/scripts/ci-audit.mjs +137 -0
- package/skills/engineering/ensure-coverage/scripts/ci-audit.test.mjs +86 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-ledger.mjs +674 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-ledger.test.mjs +447 -0
- package/skills/engineering/ensure-coverage/scripts/design-parity.mjs +591 -0
- package/skills/engineering/ensure-coverage/scripts/design-parity.test.mjs +552 -0
- package/skills/engineering/ensure-coverage/scripts/lint-tests.mjs +282 -0
- package/skills/engineering/ensure-coverage/scripts/lint-tests.test.mjs +289 -0
- package/skills/engineering/ensure-coverage/scripts/mock-policy-config.mjs +176 -0
- package/skills/engineering/ensure-coverage/scripts/mock-policy-config.test.mjs +119 -0
- package/skills/engineering/ensure-coverage/scripts/package.json +19 -0
- package/skills/engineering/golden-path/LICENSE +3 -0
- package/skills/engineering/golden-path/SKILL.md +230 -0
- package/skills/engineering/golden-path/agents/openai.yaml +3 -0
- package/skills/engineering/golden-path/assets/golden-paths.example.json +57 -0
- package/skills/engineering/golden-path/references/contract.md +239 -0
- package/skills/engineering/golden-path/references/migration.md +111 -0
- package/skills/engineering/golden-path/release-check.mjs +93 -0
- package/skills/engineering/golden-path/scripts/golden-path-core.mjs +1779 -0
- package/skills/engineering/golden-path/scripts/golden-path.mjs +6 -0
- package/skills/engineering/golden-path/scripts/golden-path.test.mjs +1457 -0
- package/skills/engineering/harness-runtime/LICENSE +3 -0
- package/skills/engineering/harness-runtime/SKILL.md +19 -0
- package/skills/engineering/harness-runtime/agents/openai.yaml +6 -0
- package/skills/engineering/harness-runtime/bin/discover-models.mjs +4 -0
- package/skills/engineering/harness-runtime/bin/model-catalog.mjs +4 -0
- package/skills/engineering/harness-runtime/contracts.md +15 -0
- package/skills/engineering/harness-runtime/discover-models.mjs +392 -0
- package/skills/engineering/harness-runtime/discover-models.test.mjs +363 -0
- package/skills/engineering/harness-runtime/fixtures/native-question-schemas.json +33 -0
- package/skills/engineering/harness-runtime/fixtures/question-responses.json +54 -0
- package/skills/engineering/harness-runtime/harness-runtime.test.mjs +967 -0
- package/skills/engineering/harness-runtime/index.mjs +767 -0
- package/skills/engineering/harness-runtime/model-catalog-seed.test.mjs +829 -0
- package/skills/engineering/harness-runtime/model-catalog.mjs +787 -0
- package/skills/engineering/harness-runtime/model-catalog.test.mjs +366 -0
- package/skills/engineering/harness-runtime/native-question-contracts.md +37 -0
- package/skills/engineering/harness-runtime/references/model-catalog-seed.json +408 -0
- package/skills/engineering/harness-runtime/references/model-catalog.md +57 -0
- package/skills/engineering/harness-runtime/release-check.mjs +93 -0
- package/skills/engineering/resolve-issues/LICENSE +3 -0
- package/skills/engineering/resolve-issues/SKILL.md +250 -0
- package/skills/engineering/resolve-issues/agents/openai.yaml +9 -0
- package/skills/engineering/resolve-issues/plugin-hooks.json +17 -0
- package/skills/engineering/resolve-issues/references/canary.md +28 -0
- package/skills/engineering/resolve-issues/references/ci.md +105 -0
- package/skills/engineering/resolve-issues/references/done.md +25 -0
- package/skills/engineering/resolve-issues/references/dropbox.md +90 -0
- package/skills/engineering/resolve-issues/references/expire.md +318 -0
- package/skills/engineering/resolve-issues/references/exploration.md +202 -0
- package/skills/engineering/resolve-issues/references/implementation.md +303 -0
- package/skills/engineering/resolve-issues/references/preflight.md +445 -0
- package/skills/engineering/resolve-issues/references/review.md +228 -0
- package/skills/engineering/resolve-issues/references/shared-modules.md +44 -0
- package/skills/engineering/resolve-issues/references/task-plan.md +264 -0
- package/skills/engineering/resolve-issues/release-check.mjs +93 -0
- package/skills/engineering/resolve-issues/scripts/cleanup-runs.mjs +364 -0
- package/skills/engineering/resolve-issues/scripts/cleanup-runs.test.mjs +280 -0
- package/skills/engineering/resolve-issues/scripts/discover-models.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/dropbox.mjs +473 -0
- package/skills/engineering/resolve-issues/scripts/dropbox.test.mjs +346 -0
- package/skills/engineering/resolve-issues/scripts/findings-reuse.mjs +98 -0
- package/skills/engineering/resolve-issues/scripts/findings-reuse.test.mjs +88 -0
- package/skills/engineering/resolve-issues/scripts/github-reviews.mjs +384 -0
- package/skills/engineering/resolve-issues/scripts/github-reviews.test.mjs +264 -0
- package/skills/engineering/resolve-issues/scripts/install-hooks.mjs +135 -0
- package/skills/engineering/resolve-issues/scripts/install-hooks.test.mjs +79 -0
- package/skills/engineering/resolve-issues/scripts/issue-tree.mjs +162 -0
- package/skills/engineering/resolve-issues/scripts/issue-tree.test.mjs +107 -0
- package/skills/engineering/resolve-issues/scripts/manual-invocation.test.mjs +14 -0
- package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/next-actions-capacity.test.mjs +149 -0
- package/skills/engineering/resolve-issues/scripts/next-actions.mjs +856 -0
- package/skills/engineering/resolve-issues/scripts/next-actions.test.mjs +915 -0
- package/skills/engineering/resolve-issues/scripts/plan-sync.mjs +269 -0
- package/skills/engineering/resolve-issues/scripts/plan-sync.test.mjs +156 -0
- package/skills/engineering/resolve-issues/scripts/preflight-models.mjs +736 -0
- package/skills/engineering/resolve-issues/scripts/preflight-models.test.mjs +448 -0
- package/skills/engineering/resolve-issues/scripts/ready-check.mjs +185 -0
- package/skills/engineering/resolve-issues/scripts/ready-check.test.mjs +217 -0
- package/skills/engineering/resolve-issues/scripts/rehydrate.mjs +98 -0
- package/skills/engineering/resolve-issues/scripts/rehydrate.test.mjs +91 -0
- package/skills/engineering/resolve-issues/scripts/review-verdict.mjs +509 -0
- package/skills/engineering/resolve-issues/scripts/review-verdict.test.mjs +1060 -0
- package/skills/engineering/resolve-issues/scripts/size-check.mjs +492 -0
- package/skills/engineering/resolve-issues/scripts/size-check.test.mjs +458 -0
- package/skills/engineering/resolve-release/LICENSE +3 -0
- package/skills/engineering/resolve-release/SKILL.md +215 -0
- package/skills/engineering/resolve-release/agents/openai.yaml +8 -0
- package/skills/engineering/resolve-release/flows/cloud-run-canary.md +13 -0
- package/skills/engineering/resolve-release/flows/cloud-run.md +7 -0
- package/skills/engineering/resolve-release/flows/root-tag-npm.md +13 -0
- package/skills/engineering/resolve-release/flows/workspace-npm.md +22 -0
- package/skills/engineering/resolve-release/references/canary.md +51 -0
- package/skills/engineering/resolve-release/references/candidate.md +41 -0
- package/skills/engineering/resolve-release/references/cut.md +131 -0
- package/skills/engineering/resolve-release/references/dark-launch.md +66 -0
- package/skills/engineering/resolve-release/references/flows.md +150 -0
- package/skills/engineering/resolve-release/references/preflight.md +154 -0
- package/skills/engineering/resolve-release/references/prepared-metadata.md +260 -0
- package/skills/engineering/resolve-release/references/promotion.md +82 -0
- package/skills/engineering/resolve-release/references/publish.md +232 -0
- package/skills/engineering/resolve-release/references/workspace-npm.md +103 -0
- package/skills/engineering/resolve-release/release-check.mjs +93 -0
- package/skills/engineering/resolve-release/scripts/apply.mjs +212 -0
- package/skills/engineering/resolve-release/scripts/apply.test.mjs +99 -0
- package/skills/engineering/resolve-release/scripts/dark-flags.mjs +134 -0
- package/skills/engineering/resolve-release/scripts/dark-flags.test.mjs +100 -0
- package/skills/engineering/resolve-release/scripts/flow.mjs +500 -0
- package/skills/engineering/resolve-release/scripts/flow.test.mjs +340 -0
- package/skills/engineering/resolve-release/scripts/green-head.mjs +231 -0
- package/skills/engineering/resolve-release/scripts/green-head.test.mjs +101 -0
- package/skills/engineering/resolve-release/scripts/npm-version-absence.mjs +138 -0
- package/skills/engineering/resolve-release/scripts/npm-version-absence.test.mjs +426 -0
- package/skills/engineering/resolve-release/scripts/plan-npm.test.mjs +659 -0
- package/skills/engineering/resolve-release/scripts/plan-toml-boundary.test.mjs +317 -0
- package/skills/engineering/resolve-release/scripts/plan-uv.test.mjs +291 -0
- package/skills/engineering/resolve-release/scripts/plan.mjs +806 -0
- package/skills/engineering/resolve-release/scripts/plan.test.mjs +428 -0
- package/skills/engineering/rush-issues/LICENSE +3 -0
- package/skills/engineering/rush-issues/SKILL.md +58 -0
- package/skills/engineering/rush-issues/agents/openai.yaml +8 -0
- package/skills/engineering/rush-issues/rehydrate.mjs +10 -0
- package/skills/engineering/rush-issues/release-check.mjs +93 -0
- package/skills/engineering/rush-release/LICENSE +3 -0
- package/skills/engineering/rush-release/SKILL.md +35 -0
- package/skills/engineering/rush-release/agents/openai.yaml +8 -0
- package/skills/engineering/rush-release/release-check.mjs +93 -0
- package/skills/engineering/test-quality/LICENSE +3 -0
- package/skills/engineering/test-quality/SKILL.md +79 -0
- package/skills/engineering/test-quality/references/audit.md +80 -0
- package/skills/engineering/test-quality/references/lint.md +24 -0
- package/skills/engineering/test-quality/references/principles.md +143 -0
- package/skills/engineering/test-quality/references/testing-conventions.md +9 -0
- package/skills/engineering/test-quality/release-check.mjs +93 -0
- package/skills/engineering/test-quality/scripts/lint-tests.mjs +574 -0
- package/skills/engineering/test-quality/scripts/lint-tests.test.mjs +591 -0
- package/skills/engineering/test-quality/scripts/mock-policy-config.mjs +176 -0
- package/skills/engineering/test-quality/scripts/mock-policy-config.test.mjs +119 -0
- package/skills/engineering/test-quality/scripts/persist-conventions-core.mjs +117 -0
- package/skills/engineering/test-quality/scripts/persist-conventions.mjs +17 -0
- package/skills/engineering/test-quality/scripts/persist-conventions.test.mjs +104 -0
- package/skills/risk-compliance/compliance-audit/LICENSE +3 -0
- package/skills/risk-compliance/compliance-audit/SKILL.md +439 -0
- package/skills/risk-compliance/compliance-audit/references/findings-schema.md +293 -0
- package/skills/risk-compliance/compliance-audit/references/normalization-rules.md +45 -0
- package/skills/risk-compliance/compliance-audit/references/vars-checklist.md +1068 -0
- package/skills/risk-compliance/compliance-audit/references/vars-findings-schema.md +398 -0
- package/skills/risk-compliance/compliance-audit/release-check.mjs +93 -0
- package/skills/risk-compliance/compliance-audit/scripts/compliance-audit.test.mjs +14 -0
- package/skills/risk-compliance/compliance-audit/scripts/export_tracker_xlsx.py +221 -0
- package/skills/risk-compliance/compliance-audit/scripts/reconcile_tracker.py +458 -0
- package/skills/risk-compliance/compliance-audit/scripts/test_export_tracker_xlsx.py +97 -0
- package/skills/risk-compliance/compliance-audit/scripts/test_validate_tracker.py +157 -0
- package/skills/risk-compliance/compliance-audit/scripts/validate_tracker.py +829 -0
- package/skills/risk-compliance/contract-compare/LICENSE +3 -0
- package/skills/risk-compliance/contract-compare/SKILL.md +199 -0
- package/skills/risk-compliance/contract-compare/references/comparison-dimensions.md +209 -0
- package/skills/risk-compliance/contract-compare/release-check.mjs +93 -0
- package/skills/risk-compliance/contract-review/LICENSE +3 -0
- package/skills/risk-compliance/contract-review/SKILL.md +240 -0
- package/skills/risk-compliance/contract-review/references/review-criteria.md +223 -0
- package/skills/risk-compliance/contract-review/release-check.mjs +93 -0
- package/skills/risk-compliance/doc-authenticity/LICENSE +3 -0
- package/skills/risk-compliance/doc-authenticity/SKILL.md +160 -0
- package/skills/risk-compliance/doc-authenticity/agents/openai.yaml +8 -0
- package/skills/risk-compliance/doc-authenticity/manual-invocation.test.mjs +12 -0
- package/skills/risk-compliance/doc-authenticity/references/agreement.md +66 -0
- package/skills/risk-compliance/doc-authenticity/references/bank-statement.md +150 -0
- package/skills/risk-compliance/doc-authenticity/references/forensic-signals.md +157 -0
- package/skills/risk-compliance/doc-authenticity/references/image-signals.md +114 -0
- package/skills/risk-compliance/doc-authenticity/references/invoice.md +66 -0
- package/skills/risk-compliance/doc-authenticity/references/issuer-profiles.md +86 -0
- package/skills/risk-compliance/doc-authenticity/references/verdict-and-report.md +95 -0
- package/skills/risk-compliance/doc-authenticity/references/verdict.schema.json +81 -0
- package/skills/risk-compliance/doc-authenticity/release-check.mjs +93 -0
- package/skills/risk-compliance/doc-authenticity/scripts/image_forensics.py +294 -0
- package/skills/risk-compliance/doc-authenticity/scripts/pdf_forensics.py +401 -0
- package/skills/risk-compliance/doc-authenticity/scripts/validate_codes.py +224 -0
- package/skills/risk-compliance/doc-authenticity/scripts/validate_verdict.py +308 -0
- package/skills/risk-compliance/doc-authenticity/scripts/validate_verdict.test.mjs +212 -0
- package/skills/risk-compliance/fraud-analysis/LICENSE +3 -0
- package/skills/risk-compliance/fraud-analysis/SKILL.md +114 -0
- package/skills/risk-compliance/fraud-analysis/references/archetypes/authorized-payment-scam.md +41 -0
- package/skills/risk-compliance/fraud-analysis/references/archetypes/first-party-fraud.md +44 -0
- package/skills/risk-compliance/fraud-analysis/references/archetypes/third-party-fraud.md +27 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/bank-transfer.md +24 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/card-payment.md +30 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/payment-collection.md +20 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/payout.md +20 -0
- package/skills/risk-compliance/fraud-analysis/references/feature-engineering.md +158 -0
- package/skills/risk-compliance/fraud-analysis/references/mechanisms/account-takeover.md +36 -0
- package/skills/risk-compliance/fraud-analysis/references/report-rationale.md +45 -0
- package/skills/risk-compliance/fraud-analysis/references/report-template.md +190 -0
- package/skills/risk-compliance/fraud-analysis/references/review-checklist.md +175 -0
- package/skills/risk-compliance/fraud-analysis/references/taxonomy.md +79 -0
- package/skills/risk-compliance/fraud-analysis/references/terminology.md +108 -0
- package/skills/risk-compliance/fraud-analysis/references/workflow.md +175 -0
- package/skills/risk-compliance/fraud-analysis/release-check.mjs +93 -0
- package/skills/risk-compliance/payment-analysis/LICENSE +3 -0
- package/skills/risk-compliance/payment-analysis/SKILL.md +180 -0
- package/skills/risk-compliance/payment-analysis/references/auth-rate-actions.md +30 -0
- package/skills/risk-compliance/payment-analysis/references/chargebacks.md +208 -0
- package/skills/risk-compliance/payment-analysis/references/chinese-polish.md +51 -0
- package/skills/risk-compliance/payment-analysis/references/event-layers.md +127 -0
- package/skills/risk-compliance/payment-analysis/references/fx.md +59 -0
- package/skills/risk-compliance/payment-analysis/references/journey.md +79 -0
- package/skills/risk-compliance/payment-analysis/references/metrics.md +67 -0
- package/skills/risk-compliance/payment-analysis/references/report-template.md +119 -0
- package/skills/risk-compliance/payment-analysis/references/terminology.md +95 -0
- package/skills/risk-compliance/payment-analysis/references/visualization.md +56 -0
- package/skills/risk-compliance/payment-analysis/release-check.mjs +93 -0
- package/skills/risk-compliance/report-writing/LICENSE +3 -0
- package/skills/risk-compliance/report-writing/SKILL.md +220 -0
- package/skills/risk-compliance/report-writing/references/audit-report-template.md +121 -0
- package/skills/risk-compliance/report-writing/references/external-assessment-template.md +167 -0
- package/skills/risk-compliance/report-writing/references/management-report-template.md +145 -0
- package/skills/risk-compliance/report-writing/references/vars-report-template.md +224 -0
- package/skills/risk-compliance/report-writing/release-check.mjs +93 -0
- package/skills/risk-compliance/similar-domain/LICENSE +3 -0
- package/skills/risk-compliance/similar-domain/SKILL.md +203 -0
- package/skills/risk-compliance/similar-domain/references/entities.md +67 -0
- package/skills/risk-compliance/similar-domain/references/fingerprints.md +134 -0
- package/skills/risk-compliance/similar-domain/references/pivots.md +82 -0
- package/skills/risk-compliance/similar-domain/references/report-template.md +93 -0
- package/skills/risk-compliance/similar-domain/references/scoring.md +130 -0
- package/skills/risk-compliance/similar-domain/references/terminology.md +41 -0
- package/skills/risk-compliance/similar-domain/references/workflow.md +85 -0
- package/skills/risk-compliance/similar-domain/release-check.mjs +93 -0
- package/skills/risk-compliance/tld-detection/LICENSE +3 -0
- package/skills/risk-compliance/tld-detection/SKILL.md +245 -0
- package/skills/risk-compliance/tld-detection/agents/openai.yaml +9 -0
- package/skills/risk-compliance/tld-detection/references/chinese-polish.md +55 -0
- package/skills/risk-compliance/tld-detection/references/clean.md +51 -0
- package/skills/risk-compliance/tld-detection/references/clustering.md +235 -0
- package/skills/risk-compliance/tld-detection/references/decision.md +189 -0
- package/skills/risk-compliance/tld-detection/references/fx-conversion.md +232 -0
- package/skills/risk-compliance/tld-detection/references/report-template.md +272 -0
- package/skills/risk-compliance/tld-detection/references/streams.md +141 -0
- package/skills/risk-compliance/tld-detection/references/terminology.md +95 -0
- package/skills/risk-compliance/tld-detection/references/workflow.md +95 -0
- package/skills/risk-compliance/tld-detection/release-check.mjs +93 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_ladders.py +390 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_ladders.test.mjs +14 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_streams.py +650 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_streams.test.mjs +14 -0
- package/skills/risk-compliance/tld-detection/tests/test_detect_ladders.py +134 -0
- package/skills/risk-compliance/tld-detection/tests/test_detect_streams.py +520 -0
|
@@ -0,0 +1,736 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// resolve-issues fast path for model selection.
|
|
3
|
+
//
|
|
4
|
+
// One command: discover → tier (shared harness-runtime catalog) → recommend
|
|
5
|
+
// implementer + fill explorer + fill diagnoser + fill reviewer ≠ implementer. Prints a ready
|
|
6
|
+
// ask payload the orchestrator hands straight to the harness's native question
|
|
7
|
+
// tool (see references/shared-modules.md) without reading longer workflow
|
|
8
|
+
// doctrine before model selection.
|
|
9
|
+
//
|
|
10
|
+
// Maintenance (sync / bank) is deferred until AFTER the human answers — never
|
|
11
|
+
// block the picker on catalog writes.
|
|
12
|
+
//
|
|
13
|
+
// Usage:
|
|
14
|
+
// node preflight-models.mjs --harness <pi|codex|claude-code> [--risk routine|high]
|
|
15
|
+
// [--available id,id,...] [--human-named id,id,...] [--implementer id[@effort]] [--ask-only]
|
|
16
|
+
//
|
|
17
|
+
// --implementer pins the implementer: it is the only option, and the run never
|
|
18
|
+
// falls back to a recommended model when the pinned one is not available.
|
|
19
|
+
//
|
|
20
|
+
// Exit: 0 whenever it ran (a result with `ok: false` and a `code` of `no-slot-eligible` or
|
|
21
|
+
// `pinned-implementer-unavailable` is the answer, not a failure) · 2 usage or crash
|
|
22
|
+
import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
|
|
23
|
+
import {
|
|
24
|
+
detectHarness,
|
|
25
|
+
discover,
|
|
26
|
+
} from '../../harness-runtime/discover-models.mjs'
|
|
27
|
+
import {
|
|
28
|
+
tierProposals,
|
|
29
|
+
pointsFromTiers,
|
|
30
|
+
isSlotEligible,
|
|
31
|
+
DEFAULT_EFFORT,
|
|
32
|
+
readCatalog,
|
|
33
|
+
pathForHarness,
|
|
34
|
+
readSeed,
|
|
35
|
+
defaultSeedPath,
|
|
36
|
+
findSeedEntry,
|
|
37
|
+
} from '../../harness-runtime/model-catalog.mjs'
|
|
38
|
+
|
|
39
|
+
export const RISK = Object.freeze(['routine', 'high'])
|
|
40
|
+
|
|
41
|
+
// Preferred fills when discovery actually yielded the id (resolve-issues defaults).
|
|
42
|
+
// Reviewer: the frontier band's home role is review (model-catalog.md). Since
|
|
43
|
+
// 2026-09-23 the primary is gpt-6-astra@medium and the fallback (when the
|
|
44
|
+
// implementer IS Astra — a human pick; resolve-issues never recommends frontier for
|
|
45
|
+
// implementation) is gpt-5.6-sol@medium. Both are synthesized below-catalog
|
|
46
|
+
// policy points (the catalog banks `high` per rule 6); the model ids are the
|
|
47
|
+
// two frontier points by the official DeepSWE v1.1 board at high (73.2%±3.4,
|
|
48
|
+
// 69.4%±1.4) and the *effort* comes from the local blinded review benchmark
|
|
49
|
+
// (docs/research/2026-09-23-reviewer-benchmark-astra-vs-sol.md): Astra-medium
|
|
50
|
+
// matched Sol-medium's useful-finding yield in under half the wall-clock time
|
|
51
|
+
// and beat Astra-high on yield; Sol-high found three more at 3.5x the time.
|
|
52
|
+
// Independence is by model id, never by effort.
|
|
53
|
+
export const TEAM_REVIEWER_POLICY = Object.freeze({
|
|
54
|
+
pi: {
|
|
55
|
+
primary: { id: 'openai/gpt-6-astra', family: 'openai', effort: 'medium', tier: 'frontier' },
|
|
56
|
+
fallback: { id: 'openai/gpt-5.6-sol', family: 'openai', effort: 'medium', tier: 'frontier' },
|
|
57
|
+
},
|
|
58
|
+
codex: {
|
|
59
|
+
primary: { id: 'gpt-6-astra', family: 'openai', effort: 'medium', tier: 'frontier' },
|
|
60
|
+
fallback: { id: 'gpt-5.6-sol', family: 'openai', effort: 'medium', tier: 'frontier' },
|
|
61
|
+
},
|
|
62
|
+
'claude-code': {
|
|
63
|
+
primary: { id: 'gpt-6-astra', family: 'openai', effort: 'medium', tier: 'frontier' },
|
|
64
|
+
fallback: { id: 'gpt-5.6-sol', family: 'openai', effort: 'medium', tier: 'frontier' },
|
|
65
|
+
},
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
// Implementer ladders: ordered per risk and harness, first discovered point
|
|
69
|
+
// wins. Order set by the team on 2026-09-23 over the DeepSWE v1.1 evidence in
|
|
70
|
+
// the catalog notes (official board where a model has a run, vendor launch
|
|
71
|
+
// figure otherwise). A frontier point reaches the recommendation only through
|
|
72
|
+
// these ladders; the reviewer slot then switches to a distinct model id (an
|
|
73
|
+
// Astra implementation is reviewed by gpt-5.6-sol@medium; every other rung by
|
|
74
|
+
// gpt-6-astra@medium, a different family for the Grok/MiMo rungs).
|
|
75
|
+
//
|
|
76
|
+
// High risk (reordered 2026-09-30 by the team: gpt-6.1-sol@high first, 75.2
|
|
77
|
+
// vendor at about a fifth of Astra's cost per task, then the rest unchanged):
|
|
78
|
+
// gpt-6.1-sol@high → gpt-6-astra@high (73.2%±3.4 official, top of the board) →
|
|
79
|
+
// gpt-5.6-sol@high (69.4%±1.4 official; slowest point in the local review
|
|
80
|
+
// benchmark) → grok-4.7@high (71.0 vendor, $2/$6, not on the official board;
|
|
81
|
+
// kept behind the two official frontier points until Datacurve runs it), over
|
|
82
|
+
// gpt-5.5@high (64.4%±3.1, retiring from Codex 2026-10-14).
|
|
83
|
+
//
|
|
84
|
+
// Routine (reordered 2026-09-28 by the team: gpt-6-sol@high first, then
|
|
85
|
+
// luna, grok-4.6, mimo; the evidence notes below are unchanged): gpt-6-luna@high (balanced-coder by human classification — OpenAI
|
|
86
|
+
// published no high point, 66.6 vendor is at max; $0.10/$0.50. Pi smoke on one
|
|
87
|
+
// small tool task: high 30s vs max 62s vs Terra@high 29s at ~1/20 the cost, so
|
|
88
|
+
// high keeps Terra's latency at near-zero spend; max was too slow) →
|
|
89
|
+
// grok-4.6@high (deep-reasoner; 65.2%±1.5 official, $2/$6) → mimo-v2.6-pro@high
|
|
90
|
+
// (frontier; 71.9 vendor, $0.44/$0.87; MiMo's API has thinking on/off only, so
|
|
91
|
+
// `high` labels that single point — behind grok-4.6 until an official run and
|
|
92
|
+
// local trajectory evidence exist) → gpt-6-sol@high (deep-reasoner; 65.3 vendor;
|
|
93
|
+
// replaced gpt-5.6-terra@high on 2026-09-27, ADR 0009). On 2026-09-30 every
|
|
94
|
+
// gpt-6-sol rung became gpt-6.1-sol (75.2 vendor at high, frontier; Codex now
|
|
95
|
+
// lists gpt-6-sol as previous generation), in the same positions. Only the OpenAI rungs
|
|
96
|
+
// exist on Codex (it lists no Grok or MiMo ids). A rung discovery does not
|
|
97
|
+
// yield is skipped; past the ladder the tier order applies.
|
|
98
|
+
//
|
|
99
|
+
// Escalation fix workers (test-first, last-try) always take the high-risk ladder
|
|
100
|
+
// (gpt-6.1-sol@high first since 2026-09-30), whatever the run's risk (team
|
|
101
|
+
// decision 2026-09-28).
|
|
102
|
+
export const TEAM_IMPLEMENTER_PREFERENCE = Object.freeze({
|
|
103
|
+
routine: {
|
|
104
|
+
pi: [
|
|
105
|
+
{ id: 'openai/gpt-6.1-sol', family: 'openai', effort: 'high', tier: 'frontier' },
|
|
106
|
+
{ id: 'openai/gpt-6-luna', family: 'openai', effort: 'high', tier: 'balanced-coder' },
|
|
107
|
+
{ id: 'xai/grok-4.6', family: 'xai', effort: 'high', tier: 'deep-reasoner' },
|
|
108
|
+
{ id: 'xiaomi/mimo-v2.6-pro', family: 'xiaomi', effort: 'high', tier: 'frontier' },
|
|
109
|
+
],
|
|
110
|
+
codex: [
|
|
111
|
+
{ id: 'gpt-6.1-sol', family: 'openai', effort: 'high', tier: 'frontier' },
|
|
112
|
+
{ id: 'gpt-6-luna', family: 'openai', effort: 'high', tier: 'balanced-coder' },
|
|
113
|
+
],
|
|
114
|
+
'claude-code': [
|
|
115
|
+
{ id: 'gpt-6.1-sol', family: 'openai', effort: 'high', tier: 'frontier' },
|
|
116
|
+
{ id: 'gpt-6-luna', family: 'openai', effort: 'high', tier: 'balanced-coder' },
|
|
117
|
+
{ id: 'grok-4.6', family: 'xai', effort: 'high', tier: 'deep-reasoner' },
|
|
118
|
+
{ id: 'mimo-v2.6-pro', family: 'xiaomi', effort: 'high', tier: 'frontier' },
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
high: {
|
|
122
|
+
pi: [
|
|
123
|
+
{ id: 'openai/gpt-6.1-sol', family: 'openai', effort: 'high', tier: 'frontier' },
|
|
124
|
+
{ id: 'openai/gpt-6-astra', family: 'openai', effort: 'high', tier: 'frontier' },
|
|
125
|
+
{ id: 'openai/gpt-5.6-sol', family: 'openai', effort: 'high', tier: 'frontier' },
|
|
126
|
+
{ id: 'xai/grok-4.7', family: 'xai', effort: 'high', tier: 'frontier' },
|
|
127
|
+
],
|
|
128
|
+
codex: [
|
|
129
|
+
{ id: 'gpt-6.1-sol', family: 'openai', effort: 'high', tier: 'frontier' },
|
|
130
|
+
{ id: 'gpt-6-astra', family: 'openai', effort: 'high', tier: 'frontier' },
|
|
131
|
+
{ id: 'gpt-5.6-sol', family: 'openai', effort: 'high', tier: 'frontier' },
|
|
132
|
+
],
|
|
133
|
+
'claude-code': [
|
|
134
|
+
{ id: 'gpt-6.1-sol', family: 'openai', effort: 'high', tier: 'frontier' },
|
|
135
|
+
{ id: 'gpt-6-astra', family: 'openai', effort: 'high', tier: 'frontier' },
|
|
136
|
+
{ id: 'gpt-5.6-sol', family: 'openai', effort: 'high', tier: 'frontier' },
|
|
137
|
+
{ id: 'grok-4.7', family: 'xai', effort: 'high', tier: 'frontier' },
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
// Explorer: gpt-6.1-sol@medium first (ADR 0009 named gpt-6-sol; replaced
|
|
143
|
+
// 2026-09-30; 73 vendor at medium), then the routine implementer ladder without
|
|
144
|
+
// its gpt-6.1-sol@high rung. The medium point is below the catalog's banked `high`, so it is a
|
|
145
|
+
// policy point synthesized from a discovered id, like the reviewer's; when
|
|
146
|
+
// discovery does not yield gpt-6.1-sol, the fill falls through to the routine
|
|
147
|
+
// ladder.
|
|
148
|
+
export const TEAM_EXPLORER_POLICY = Object.freeze({
|
|
149
|
+
pi: { id: 'openai/gpt-6.1-sol', family: 'openai', effort: 'medium', tier: 'frontier' },
|
|
150
|
+
codex: { id: 'gpt-6.1-sol', family: 'openai', effort: 'medium', tier: 'frontier' },
|
|
151
|
+
'claude-code': { id: 'gpt-6.1-sol', family: 'openai', effort: 'medium', tier: 'frontier' },
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
export const TEAM_EXPLORER_DEFAULT = Object.freeze(
|
|
155
|
+
Object.fromEntries(
|
|
156
|
+
Object.entries(TEAM_IMPLEMENTER_PREFERENCE.routine).map(([harness, ladder]) => [
|
|
157
|
+
harness,
|
|
158
|
+
[TEAM_EXPLORER_POLICY[harness], ...ladder.filter((rung) => rung.id !== TEAM_EXPLORER_POLICY[harness].id)],
|
|
159
|
+
]),
|
|
160
|
+
),
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
const TIER_RANK = Object.freeze({
|
|
164
|
+
frontier: 0,
|
|
165
|
+
'deep-reasoner': 1,
|
|
166
|
+
'balanced-coder': 2,
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
function usage() {
|
|
170
|
+
return `preflight-models — discover + recommend implementer, fill explorer + reviewer (resolve-issues fast path)
|
|
171
|
+
|
|
172
|
+
Usage:
|
|
173
|
+
node preflight-models.mjs --harness <pi|codex|claude-code> [--risk routine|high]
|
|
174
|
+
[--available <id,id,...>] [--human-named <id,id,...>] [--implementer <id[@effort]>] [--ask-only]
|
|
175
|
+
|
|
176
|
+
Output JSON:
|
|
177
|
+
{ harness, risk, discovery, models, implementer, explorer, diagnoser, reviewer, ask, deferred }
|
|
178
|
+
|
|
179
|
+
--ask-only prints only the ask block (for piping into a question UI).
|
|
180
|
+
--implementer pins the implementer (the only option); exit 4 when it is not an
|
|
181
|
+
available slot-eligible point. Never substitute another model.
|
|
182
|
+
Deferred: run catalog sync/bank AFTER the human answers — never before the ask.`
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function parseList(value) {
|
|
186
|
+
return String(value || '')
|
|
187
|
+
.split(',')
|
|
188
|
+
.map((s) => s.trim())
|
|
189
|
+
.filter(Boolean)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function parseArgs(argv) {
|
|
193
|
+
const out = {
|
|
194
|
+
harness: null,
|
|
195
|
+
risk: 'routine',
|
|
196
|
+
available: [],
|
|
197
|
+
humanNamed: [],
|
|
198
|
+
implementer: null,
|
|
199
|
+
askOnly: false,
|
|
200
|
+
help: false,
|
|
201
|
+
}
|
|
202
|
+
for (let i = 0; i < argv.length; i++) {
|
|
203
|
+
const a = argv[i]
|
|
204
|
+
if (a === '--help' || a === '-h' || a === 'help') out.help = true
|
|
205
|
+
else if (a === '--ask-only') out.askOnly = true
|
|
206
|
+
else if (a === '--harness') out.harness = argv[++i]
|
|
207
|
+
else if (a === '--risk') out.risk = argv[++i]
|
|
208
|
+
else if (a === '--available') out.available = parseList(argv[++i])
|
|
209
|
+
else if (a === '--human-named') out.humanNamed = parseList(argv[++i])
|
|
210
|
+
else if (a === '--implementer') out.implementer = argv[++i]
|
|
211
|
+
else if (a.startsWith('--harness=')) out.harness = a.slice('--harness='.length)
|
|
212
|
+
else if (a.startsWith('--risk=')) out.risk = a.slice('--risk='.length)
|
|
213
|
+
else if (a.startsWith('--available=')) out.available = parseList(a.slice('--available='.length))
|
|
214
|
+
else if (a.startsWith('--human-named=')) out.humanNamed = parseList(a.slice('--human-named='.length))
|
|
215
|
+
else if (a.startsWith('--implementer=')) out.implementer = a.slice('--implementer='.length)
|
|
216
|
+
else throw new Error(`unknown argument: ${a}`)
|
|
217
|
+
}
|
|
218
|
+
if (out.implementer !== null && (typeof out.implementer !== 'string' || !out.implementer.trim())) throw new Error('--implementer needs a model id')
|
|
219
|
+
return out
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* The point a pin names: `id@effort` matches that operating point exactly; a
|
|
224
|
+
* bare `id` takes the floor effort when banked, else the id's first point.
|
|
225
|
+
*/
|
|
226
|
+
export function findPinnedPoint(points, pin) {
|
|
227
|
+
const text = String(pin || '').trim()
|
|
228
|
+
if (!text) return null
|
|
229
|
+
const at = text.lastIndexOf('@')
|
|
230
|
+
const id = at > 0 ? text.slice(0, at) : text
|
|
231
|
+
const effort = at > 0 ? text.slice(at + 1) : null
|
|
232
|
+
const same = points.filter((p) => p.id === id)
|
|
233
|
+
if (effort) return same.find((p) => p.effort === effort) || null
|
|
234
|
+
return same.find((p) => p.effort === DEFAULT_EFFORT) || same[0] || null
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function familyOf(id, hinted) {
|
|
238
|
+
if (hinted) return hinted
|
|
239
|
+
if (id.includes('/')) return id.slice(0, id.indexOf('/'))
|
|
240
|
+
return 'unknown'
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/** Prefer banked catalog family, then seed, then id prefix. */
|
|
244
|
+
export function resolveFamily(harness, id, { catalog = null, seed = null } = {}) {
|
|
245
|
+
const banked = (catalog?.models || []).find((m) => m && m.id === id)
|
|
246
|
+
if (banked?.family) return banked.family
|
|
247
|
+
const seeded = seed ? findSeedEntry(seed, harness, id) : null
|
|
248
|
+
if (seeded?.family) return seeded.family
|
|
249
|
+
return familyOf(id)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function pointKey(id, effort) {
|
|
253
|
+
return `${id}@${effort || DEFAULT_EFFORT}`
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** Expand tierProposals().models into slot-eligible operating points. */
|
|
257
|
+
export function slotPoints(tieredModels, { harness, catalog = null, seed = null } = {}) {
|
|
258
|
+
const points = []
|
|
259
|
+
for (const model of tieredModels) {
|
|
260
|
+
const entries = Object.keys(model.tiers || {}).length
|
|
261
|
+
? pointsFromTiers(model.tiers)
|
|
262
|
+
: []
|
|
263
|
+
const family = resolveFamily(harness, model.id, { catalog, seed })
|
|
264
|
+
for (const p of entries) {
|
|
265
|
+
if (!isSlotEligible(p.tier)) continue
|
|
266
|
+
points.push({
|
|
267
|
+
id: model.id,
|
|
268
|
+
effort: p.effort || DEFAULT_EFFORT,
|
|
269
|
+
tier: p.tier,
|
|
270
|
+
family,
|
|
271
|
+
source: model.source,
|
|
272
|
+
citation: model.citation || null,
|
|
273
|
+
key: pointKey(model.id, p.effort || DEFAULT_EFFORT),
|
|
274
|
+
})
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return points
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function preferRisk(tier, risk) {
|
|
281
|
+
if (risk === 'high') {
|
|
282
|
+
if (tier === 'deep-reasoner') return 0
|
|
283
|
+
if (tier === 'balanced-coder') return 1
|
|
284
|
+
return 2 // frontier is never recommended by tier alone (only via the team ladder)
|
|
285
|
+
}
|
|
286
|
+
// routine
|
|
287
|
+
if (tier === 'balanced-coder') return 0
|
|
288
|
+
if (tier === 'deep-reasoner') return 1
|
|
289
|
+
return 2
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Recommend implementer. The team ladder for the risk/harness is consulted
|
|
294
|
+
* first (high risk: gpt-6.1-sol, gpt-6-astra, gpt-5.6-sol, then grok-4.7, all
|
|
295
|
+
* @high — the ladder is the only way a frontier point becomes the
|
|
296
|
+
* recommendation; routine: gpt-6.1-sol@high, gpt-6-luna@high, grok-4.6@high,
|
|
297
|
+
* then mimo-v2.6-pro@high). Without a ladder hit
|
|
298
|
+
* the tier order applies: routine → balanced-coder; high → deep-reasoner;
|
|
299
|
+
* frontier is listed but never recommended by tier alone.
|
|
300
|
+
*/
|
|
301
|
+
export function recommendImplementer(points, risk = 'routine', harness = null) {
|
|
302
|
+
if (!points.length) return null
|
|
303
|
+
const ladder = harness ? TEAM_IMPLEMENTER_PREFERENCE[risk]?.[harness] || [] : []
|
|
304
|
+
for (const preferred of ladder) {
|
|
305
|
+
const preferredPoint = findPreferredPoint(points, preferred)
|
|
306
|
+
if (preferredPoint && preferredPoint.tier === preferred.tier) return preferredPoint
|
|
307
|
+
}
|
|
308
|
+
const sorted = [...points].sort((a, b) => {
|
|
309
|
+
const ra = preferRisk(a.tier, risk)
|
|
310
|
+
const rb = preferRisk(b.tier, risk)
|
|
311
|
+
if (ra !== rb) return ra - rb
|
|
312
|
+
// Prefer the floor effort when tied; then stable id.
|
|
313
|
+
if (a.effort !== b.effort) {
|
|
314
|
+
if (a.effort === DEFAULT_EFFORT) return -1
|
|
315
|
+
if (b.effort === DEFAULT_EFFORT) return 1
|
|
316
|
+
return a.effort < b.effort ? -1 : 1
|
|
317
|
+
}
|
|
318
|
+
return a.id.localeCompare(b.id)
|
|
319
|
+
})
|
|
320
|
+
// First non-frontier if any; else first point (single-model / only-frontier harness)
|
|
321
|
+
return sorted.find((p) => p.tier !== 'frontier') || sorted[0]
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Escalation fix-worker fill (test-first, last-try): the high-risk implementer ladder
|
|
326
|
+
* (gpt-6.1-sol, gpt-6-astra, gpt-5.6-sol, then grok-4.7, all @high), whatever
|
|
327
|
+
* the run's risk.
|
|
328
|
+
*/
|
|
329
|
+
export function fillDiagnoser(points, harness) {
|
|
330
|
+
const fill = recommendImplementer(points, 'high', harness)
|
|
331
|
+
return { fill: fill || null, reason: fill ? 'high-risk-ladder' : 'none' }
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function findPreferredPoint(points, preferred) {
|
|
335
|
+
if (!preferred) return null
|
|
336
|
+
return points.find(
|
|
337
|
+
(p) => p.id === preferred.id && (p.effort || DEFAULT_EFFORT) === (preferred.effort || DEFAULT_EFFORT),
|
|
338
|
+
) || null
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Reviewer and explorer policy may deliberately use a below-catalog effort. The
|
|
342
|
+
// catalog continues to describe pushed capability points (high/xhigh/max);
|
|
343
|
+
// discovery of the model id is still required before this role-specific point
|
|
344
|
+
// exists.
|
|
345
|
+
function findPolicyPoint(points, preferred, { source, citation }) {
|
|
346
|
+
if (!preferred) return null
|
|
347
|
+
const discovered = points.find((p) => p.id === preferred.id)
|
|
348
|
+
if (!discovered) return null
|
|
349
|
+
if ((preferred.effort || DEFAULT_EFFORT) === DEFAULT_EFFORT) {
|
|
350
|
+
return findPreferredPoint(points, preferred)
|
|
351
|
+
}
|
|
352
|
+
return {
|
|
353
|
+
...discovered,
|
|
354
|
+
effort: preferred.effort,
|
|
355
|
+
tier: preferred.tier,
|
|
356
|
+
source,
|
|
357
|
+
citation,
|
|
358
|
+
key: pointKey(preferred.id, preferred.effort),
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const REVIEW_POLICY_SOURCE = Object.freeze({
|
|
363
|
+
source: 'team-review-policy',
|
|
364
|
+
citation: 'docs/research/2026-09-23-reviewer-benchmark-astra-vs-sol.md',
|
|
365
|
+
})
|
|
366
|
+
const EXPLORER_POLICY_SOURCE = Object.freeze({
|
|
367
|
+
source: 'team-explorer-policy',
|
|
368
|
+
citation: 'docs/adr/0009-orchestrator-coordinates-only.md',
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
function findReviewerPolicyPoint(points, preferred) {
|
|
372
|
+
return findPolicyPoint(points, preferred, REVIEW_POLICY_SOURCE)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Explorer fill: gpt-6.1-sol@medium when gpt-6.1-sol is discovered, then the
|
|
377
|
+
* routine implementer ladder without its gpt-6.1-sol@high rung (gpt-6-luna@high,
|
|
378
|
+
* grok-4.6@high, then mimo-v2.6-pro@high), first discovered rung wins;
|
|
379
|
+
* without a rung, the balanced-coder tier.
|
|
380
|
+
*/
|
|
381
|
+
export function fillExplorer(points, harness) {
|
|
382
|
+
const ladder = TEAM_EXPLORER_DEFAULT[harness] || []
|
|
383
|
+
const policy = TEAM_EXPLORER_POLICY[harness]
|
|
384
|
+
let preferredPoint = null
|
|
385
|
+
for (const preferred of ladder) {
|
|
386
|
+
const candidate = preferred === policy
|
|
387
|
+
? findPolicyPoint(points, preferred, EXPLORER_POLICY_SOURCE)
|
|
388
|
+
: findPreferredPoint(points, preferred)
|
|
389
|
+
if (candidate) {
|
|
390
|
+
preferredPoint = candidate
|
|
391
|
+
if (candidate.tier === preferred.tier) return { fill: candidate, reason: 'team-default' }
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
const balanced = points
|
|
395
|
+
.filter((p) => p.tier === 'balanced-coder')
|
|
396
|
+
.sort((a, b) => {
|
|
397
|
+
if (a.effort === DEFAULT_EFFORT && b.effort !== DEFAULT_EFFORT) return -1
|
|
398
|
+
if (b.effort === DEFAULT_EFFORT && a.effort !== DEFAULT_EFFORT) return 1
|
|
399
|
+
return a.id.localeCompare(b.id)
|
|
400
|
+
})
|
|
401
|
+
const fill = balanced[0] || null
|
|
402
|
+
return {
|
|
403
|
+
fill,
|
|
404
|
+
reason: fill ? (preferredPoint ? 'ladder' : 'balanced-coder') : 'none',
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Reviewer fill is implementer-aware and must differ by model id:
|
|
410
|
+
* Astra implementer -> gpt-5.6-sol@medium; otherwise -> gpt-6-astra@medium. If that
|
|
411
|
+
* policy point is unavailable, the existing diversity-first ladder applies.
|
|
412
|
+
*/
|
|
413
|
+
export function rankReviewers(points, implementer, harness) {
|
|
414
|
+
const policy = TEAM_REVIEWER_POLICY[harness] || null
|
|
415
|
+
const deepPool = points.filter((p) => p.tier === 'deep-reasoner' || p.tier === 'frontier')
|
|
416
|
+
const pool = deepPool.length ? deepPool : points
|
|
417
|
+
const scored = pool.map((p) => {
|
|
418
|
+
const sameId = p.id === implementer.id
|
|
419
|
+
const sameFamily = p.family && implementer.family && p.family === implementer.family
|
|
420
|
+
let diversity
|
|
421
|
+
if (sameId) diversity = 5
|
|
422
|
+
else if (!sameFamily && p.tier === 'deep-reasoner') diversity = 0
|
|
423
|
+
else if (!sameFamily && p.tier === 'frontier') diversity = 1
|
|
424
|
+
else if (sameFamily && p.tier === 'deep-reasoner') diversity = 2
|
|
425
|
+
else if (!sameFamily) diversity = 3
|
|
426
|
+
else diversity = 4
|
|
427
|
+
return { ...p, diversity, tierRank: TIER_RANK[p.tier] ?? 9 }
|
|
428
|
+
})
|
|
429
|
+
scored.sort((a, b) => {
|
|
430
|
+
if (a.diversity !== b.diversity) return a.diversity - b.diversity
|
|
431
|
+
if (a.tierRank !== b.tierRank) return a.tierRank - b.tierRank
|
|
432
|
+
return a.id.localeCompare(b.id)
|
|
433
|
+
})
|
|
434
|
+
|
|
435
|
+
const primaryPoint = findReviewerPolicyPoint(points, policy?.primary)
|
|
436
|
+
const fallbackPoint = findReviewerPolicyPoint(points, policy?.fallback)
|
|
437
|
+
|
|
438
|
+
const ranking = []
|
|
439
|
+
const rankedIds = new Set()
|
|
440
|
+
for (const candidate of [primaryPoint, fallbackPoint, ...scored]) {
|
|
441
|
+
if (!candidate || rankedIds.has(candidate.id)) continue
|
|
442
|
+
rankedIds.add(candidate.id)
|
|
443
|
+
ranking.push(candidate)
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const implementerIsPrimary = implementer.id === policy?.primary?.id
|
|
447
|
+
const policyFill = implementerIsPrimary ? fallbackPoint : primaryPoint
|
|
448
|
+
const fill = policyFill && policyFill.id !== implementer.id
|
|
449
|
+
? policyFill
|
|
450
|
+
: scored.find((p) => p.id !== implementer.id) || scored[0]
|
|
451
|
+
let reason
|
|
452
|
+
if (fill?.id === primaryPoint?.id) reason = 'team-default'
|
|
453
|
+
else if (fill?.id === fallbackPoint?.id && implementerIsPrimary) reason = 'implementer-aware-default'
|
|
454
|
+
else reason = fill?.id === implementer.id ? 'no-distinct-candidate' : 'ladder'
|
|
455
|
+
|
|
456
|
+
return {
|
|
457
|
+
fill,
|
|
458
|
+
reason,
|
|
459
|
+
ranking,
|
|
460
|
+
teamDefaultApplied: reason === 'team-default' || reason === 'implementer-aware-default',
|
|
461
|
+
reducedDiversity: !!(fill && implementer && fill.family && fill.family === implementer.family && fill.id !== implementer.id),
|
|
462
|
+
notIndependent: !!(fill && implementer && fill.id === implementer.id),
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
function optionFromPoint(p, { recommended = false, role, ladderRung = 0 }) {
|
|
467
|
+
const why =
|
|
468
|
+
role === 'implementer'
|
|
469
|
+
? ladderRung
|
|
470
|
+
? `team ladder rung ${ladderRung}${recommended ? '' : ' — next discovered rung'}`
|
|
471
|
+
: p.tier === 'balanced-coder'
|
|
472
|
+
? 'routine implementer band'
|
|
473
|
+
: p.tier === 'deep-reasoner'
|
|
474
|
+
? 'deep-reasoner for risk-heavy work'
|
|
475
|
+
: p.tier === 'frontier'
|
|
476
|
+
? recommended
|
|
477
|
+
? 'frontier — team implementer ladder preference'
|
|
478
|
+
: 'frontier (alternate only — not the recommendation)'
|
|
479
|
+
: p.tier
|
|
480
|
+
: p.tier
|
|
481
|
+
return {
|
|
482
|
+
id: p.key, // operating point id for the picker; parse back to model+effort
|
|
483
|
+
modelId: p.id,
|
|
484
|
+
label: `${p.id} @ ${p.effort}`,
|
|
485
|
+
description: `${p.tier}${recommended ? ' · recommended' : ''} · ${why}`,
|
|
486
|
+
family: p.family,
|
|
487
|
+
effort: p.effort,
|
|
488
|
+
tier: p.tier,
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/** Native question UIs typically allow 2–4 options. Keep the rest as `alternates`. */
|
|
493
|
+
export const ASK_OPTION_LIMIT = 4
|
|
494
|
+
|
|
495
|
+
function slotFillPayload(slot) {
|
|
496
|
+
if (!slot?.fill) return null
|
|
497
|
+
return {
|
|
498
|
+
id: slot.fill.key,
|
|
499
|
+
modelId: slot.fill.id,
|
|
500
|
+
effort: slot.fill.effort,
|
|
501
|
+
family: slot.fill.family,
|
|
502
|
+
tier: slot.fill.tier,
|
|
503
|
+
reason: slot.reason,
|
|
504
|
+
reducedDiversity: slot.reducedDiversity || false,
|
|
505
|
+
notIndependent: slot.notIndependent || false,
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* The ask's options are the team ladder for this risk/harness, in ladder order,
|
|
511
|
+
* limited to the rungs discovery actually yielded, then the remaining points by
|
|
512
|
+
* risk-matched band and id. The ladder is the policy; before 2026-09-23 the
|
|
513
|
+
* options were band-then-id, which pushed the ladder rungs (gpt-5.6-sol,
|
|
514
|
+
* grok-4.7, gpt-6-sol) into `alternates` behind whichever deep-reasoners sorted
|
|
515
|
+
* first by id, and native pickers never show alternates. One frontier point is
|
|
516
|
+
* kept visible only when none of the primary options is frontier already.
|
|
517
|
+
*/
|
|
518
|
+
export function buildAsk(implementer, points, reviewer, { risk = 'routine', explorer = null, diagnoser = null, harness = null, pinned = false } = {}) {
|
|
519
|
+
if (pinned) {
|
|
520
|
+
return {
|
|
521
|
+
header: 'Implementer',
|
|
522
|
+
question: 'The implementer is pinned for this run; it is the only option. (Explorer + reviewer are filled automatically; reviewer ≠ implementer.)',
|
|
523
|
+
recommended: implementer.key,
|
|
524
|
+
pinned: true,
|
|
525
|
+
options: [{ ...optionFromPoint(implementer, { recommended: true, role: 'implementer' }), description: `${implementer.tier} · pinned` }],
|
|
526
|
+
alternates: [],
|
|
527
|
+
explorerFill: slotFillPayload(explorer),
|
|
528
|
+
diagnoserFill: slotFillPayload(diagnoser),
|
|
529
|
+
reviewerFill: slotFillPayload(reviewer),
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
const seen = new Set()
|
|
533
|
+
const ordered = []
|
|
534
|
+
const ladderRungByKey = new Map()
|
|
535
|
+
const push = (p) => {
|
|
536
|
+
if (!p || seen.has(p.key)) return
|
|
537
|
+
seen.add(p.key)
|
|
538
|
+
ordered.push(p)
|
|
539
|
+
}
|
|
540
|
+
push(implementer)
|
|
541
|
+
const ladder = harness ? TEAM_IMPLEMENTER_PREFERENCE[risk]?.[harness] || [] : []
|
|
542
|
+
ladder.forEach((preferred, index) => {
|
|
543
|
+
const point = findPreferredPoint(points, preferred)
|
|
544
|
+
if (point && point.tier === preferred.tier) {
|
|
545
|
+
ladderRungByKey.set(point.key, index + 1)
|
|
546
|
+
push(point)
|
|
547
|
+
}
|
|
548
|
+
})
|
|
549
|
+
// Then the remaining points by risk-matched band, then id.
|
|
550
|
+
const rest = [...points].sort((a, b) => preferRisk(a.tier, risk) - preferRisk(b.tier, risk) || a.id.localeCompare(b.id))
|
|
551
|
+
for (const p of rest) push(p)
|
|
552
|
+
let primary = ordered.slice(0, ASK_OPTION_LIMIT)
|
|
553
|
+
const frontier = ordered.find((p) => p.tier === 'frontier' && p.key !== implementer?.key)
|
|
554
|
+
if (frontier && !primary.some((p) => p.tier === 'frontier') && primary.length === ASK_OPTION_LIMIT) {
|
|
555
|
+
primary = [...primary.slice(0, ASK_OPTION_LIMIT - 1), frontier]
|
|
556
|
+
}
|
|
557
|
+
const primaryKeys = new Set(primary.map((p) => p.key))
|
|
558
|
+
const optionFor = (p, recommended) =>
|
|
559
|
+
optionFromPoint(p, { recommended, role: 'implementer', ladderRung: ladderRungByKey.get(p.key) || 0 })
|
|
560
|
+
const options = primary.map((p) => optionFor(p, p.key === implementer?.key))
|
|
561
|
+
const alternates = ordered.filter((p) => !primaryKeys.has(p.key)).map((p) => optionFor(p, false))
|
|
562
|
+
|
|
563
|
+
return {
|
|
564
|
+
header: 'Implementer',
|
|
565
|
+
question: 'Which model should implement every issue in this run? (Explorer + reviewer are filled automatically; reviewer ≠ implementer.)',
|
|
566
|
+
recommended: implementer?.key || null,
|
|
567
|
+
options,
|
|
568
|
+
alternates,
|
|
569
|
+
explorerFill: slotFillPayload(explorer),
|
|
570
|
+
diagnoserFill: slotFillPayload(diagnoser),
|
|
571
|
+
reviewerFill: slotFillPayload(reviewer),
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
export function buildPreflightModels({
|
|
576
|
+
harness,
|
|
577
|
+
risk = 'routine',
|
|
578
|
+
available = [],
|
|
579
|
+
humanNamed = [],
|
|
580
|
+
implementer: pin = null,
|
|
581
|
+
env = process.env,
|
|
582
|
+
discoverFn = discover,
|
|
583
|
+
tierFn = tierProposals,
|
|
584
|
+
} = {}) {
|
|
585
|
+
if (!harness) throw new Error('harness is required')
|
|
586
|
+
if (!RISK.includes(risk)) throw new Error(`risk must be one of ${RISK.join('|')}`)
|
|
587
|
+
|
|
588
|
+
const discovery = discoverFn(harness, env, {
|
|
589
|
+
spawnModelIds: available,
|
|
590
|
+
humanNamedModelIds: humanNamed,
|
|
591
|
+
})
|
|
592
|
+
const seenIds = discovery.discovered.map((d) => d.id)
|
|
593
|
+
const tiered = tierFn(harness, seenIds)
|
|
594
|
+
const catalog = readCatalog(pathForHarness(harness, env))
|
|
595
|
+
const seed = readSeed(defaultSeedPath())
|
|
596
|
+
const points = slotPoints(tiered.models, { harness, catalog, seed })
|
|
597
|
+
const implementer = pin ? findPinnedPoint(points, pin) : recommendImplementer(points, risk, harness)
|
|
598
|
+
if (pin && !implementer) {
|
|
599
|
+
return {
|
|
600
|
+
ok: false,
|
|
601
|
+
code: 'pinned-implementer-unavailable',
|
|
602
|
+
pinned: pin,
|
|
603
|
+
harness,
|
|
604
|
+
risk,
|
|
605
|
+
discovery,
|
|
606
|
+
models: tiered,
|
|
607
|
+
points: points.map((p) => p.key),
|
|
608
|
+
implementer: null,
|
|
609
|
+
explorer: null,
|
|
610
|
+
diagnoser: null,
|
|
611
|
+
reviewer: null,
|
|
612
|
+
ask: null,
|
|
613
|
+
reason: `${pin} is not an available slot-eligible model here; block the run, never substitute another implementer`,
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
if (!implementer) {
|
|
617
|
+
return {
|
|
618
|
+
ok: false,
|
|
619
|
+
code: 'no-slot-eligible',
|
|
620
|
+
harness,
|
|
621
|
+
risk,
|
|
622
|
+
discovery,
|
|
623
|
+
models: tiered,
|
|
624
|
+
points: [],
|
|
625
|
+
implementer: null,
|
|
626
|
+
explorer: null,
|
|
627
|
+
diagnoser: null,
|
|
628
|
+
reviewer: null,
|
|
629
|
+
ask: null,
|
|
630
|
+
deferred: {
|
|
631
|
+
afterConfirm: [
|
|
632
|
+
'model-catalog.mjs sync --harness <h> --seen <ids>',
|
|
633
|
+
'model-catalog.mjs bank / bank-from-seed for any human confirmation',
|
|
634
|
+
],
|
|
635
|
+
},
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
const explorer = fillExplorer(points, harness)
|
|
639
|
+
const diagnoser = fillDiagnoser(points, harness)
|
|
640
|
+
const reviewer = rankReviewers(points, implementer, harness)
|
|
641
|
+
const ask = buildAsk(implementer, points, reviewer, { risk, explorer, diagnoser, harness, pinned: !!pin })
|
|
642
|
+
return {
|
|
643
|
+
ok: true,
|
|
644
|
+
...(pin ? { pinned: pin } : {}),
|
|
645
|
+
harness,
|
|
646
|
+
risk,
|
|
647
|
+
discovery: {
|
|
648
|
+
completeness: discovery.completeness,
|
|
649
|
+
discovered: discovery.discovered,
|
|
650
|
+
notes: discovery.notes,
|
|
651
|
+
},
|
|
652
|
+
models: tiered,
|
|
653
|
+
points,
|
|
654
|
+
implementer,
|
|
655
|
+
explorer: {
|
|
656
|
+
fill: explorer.fill,
|
|
657
|
+
reason: explorer.reason,
|
|
658
|
+
},
|
|
659
|
+
diagnoser: {
|
|
660
|
+
fill: diagnoser.fill,
|
|
661
|
+
reason: diagnoser.reason,
|
|
662
|
+
},
|
|
663
|
+
reviewer: {
|
|
664
|
+
fill: reviewer.fill,
|
|
665
|
+
reason: reviewer.reason,
|
|
666
|
+
ranking: reviewer.ranking.map((p) => p.key),
|
|
667
|
+
teamDefaultApplied: reviewer.teamDefaultApplied,
|
|
668
|
+
reducedDiversity: reviewer.reducedDiversity,
|
|
669
|
+
notIndependent: reviewer.notIndependent,
|
|
670
|
+
},
|
|
671
|
+
ask,
|
|
672
|
+
deferred: {
|
|
673
|
+
afterConfirm: [
|
|
674
|
+
`model-catalog.mjs sync --harness ${harness} --seen ${seenIds.join(',')}`,
|
|
675
|
+
'bank confirmations only after the human answers — never before the ask',
|
|
676
|
+
],
|
|
677
|
+
doNotReadBeforeAsk: [
|
|
678
|
+
'harness-runtime/references/model-catalog.md',
|
|
679
|
+
],
|
|
680
|
+
},
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
export function runCli(argv, env = process.env) {
|
|
685
|
+
let args
|
|
686
|
+
try {
|
|
687
|
+
args = parseArgs(argv)
|
|
688
|
+
} catch (e) {
|
|
689
|
+
console.error(`preflight-models: ${e.message}`)
|
|
690
|
+
console.error(usage())
|
|
691
|
+
return 2
|
|
692
|
+
}
|
|
693
|
+
if (args.help) {
|
|
694
|
+
console.log(usage())
|
|
695
|
+
return 0
|
|
696
|
+
}
|
|
697
|
+
const harness = args.harness || detectHarness(env)
|
|
698
|
+
if (!harness) {
|
|
699
|
+
console.error('preflight-models: pass --harness <pi|codex|claude-code>')
|
|
700
|
+
return 2
|
|
701
|
+
}
|
|
702
|
+
if (!RISK.includes(args.risk)) {
|
|
703
|
+
console.error(`preflight-models: --risk must be ${RISK.join('|')}`)
|
|
704
|
+
return 2
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
let result
|
|
708
|
+
try {
|
|
709
|
+
result = buildPreflightModels({
|
|
710
|
+
harness,
|
|
711
|
+
risk: args.risk,
|
|
712
|
+
available: args.available,
|
|
713
|
+
humanNamed: args.humanNamed,
|
|
714
|
+
implementer: args.implementer,
|
|
715
|
+
env,
|
|
716
|
+
})
|
|
717
|
+
} catch (e) {
|
|
718
|
+
console.error(`preflight-models: ${e.message}`)
|
|
719
|
+
return 2
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
if (!result.ok) {
|
|
723
|
+
console.log(JSON.stringify(result, null, 2))
|
|
724
|
+
return 0
|
|
725
|
+
}
|
|
726
|
+
if (args.askOnly) {
|
|
727
|
+
console.log(JSON.stringify(result.ask, null, 2))
|
|
728
|
+
return 0
|
|
729
|
+
}
|
|
730
|
+
console.log(JSON.stringify(result, null, 2))
|
|
731
|
+
return 0
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
if (isMainModule(import.meta.url)) {
|
|
735
|
+
process.exit(runCli(process.argv.slice(2)))
|
|
736
|
+
}
|