@1aboveio/skills 0.10.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 +3 -0
- package/README.md +90 -0
- package/bin/1aboveio-skills.mjs +18 -0
- package/package.json +28 -0
- package/runtime/skills/distribution/generated/recipes.json +1189 -0
- package/runtime/skills/distribution/scripts/bundles.mjs +280 -0
- package/runtime/skills/engineering/engineering-runtime/scripts/main-module.mjs +80 -0
- package/skills/backend/airflow-dag-develop/LICENSE +3 -0
- package/skills/backend/airflow-dag-develop/SKILL.md +111 -0
- package/skills/backend/app-debug/LICENSE +3 -0
- package/skills/backend/app-debug/SKILL.md +109 -0
- package/skills/backend/app-debug/references/common-errors.md +128 -0
- package/skills/backend/python-backend/LICENSE +3 -0
- package/skills/backend/python-backend/SKILL.md +326 -0
- package/skills/cicd-pipeline/cloud-build/LICENSE +3 -0
- package/skills/cicd-pipeline/cloud-build/SKILL.md +707 -0
- package/skills/cicd-pipeline/cloud-debug/LICENSE +3 -0
- package/skills/cicd-pipeline/cloud-debug/SKILL.md +316 -0
- package/skills/cicd-pipeline/cloud-debug/references/build-failures.md +238 -0
- package/skills/cicd-pipeline/cloud-debug/references/deploy-failures.md +376 -0
- package/skills/cicd-pipeline/cloud-debug/references/pipeline-failures.md +378 -0
- package/skills/cicd-pipeline/cloud-deploy/LICENSE +3 -0
- package/skills/cicd-pipeline/cloud-deploy/SKILL.md +229 -0
- package/skills/cicd-pipeline/cloud-deploy/references/config-templates.md +257 -0
- package/skills/cicd-pipeline/docker/LICENSE +3 -0
- package/skills/cicd-pipeline/docker/SKILL.md +126 -0
- package/skills/cicd-pipeline/google-cloud/LICENSE +3 -0
- package/skills/cicd-pipeline/google-cloud/SKILL.md +118 -0
- package/skills/cicd-pipeline/google-cloud/references/gcs.md +469 -0
- package/skills/cicd-pipeline/google-cloud/references/iam.md +451 -0
- package/skills/cicd-pipeline/google-cloud/references/project.md +349 -0
- package/skills/cicd-pipeline/google-cloud/references/secrets.md +336 -0
- package/skills/cicd-pipeline/google-cloud/references/vpc.md +312 -0
- package/skills/cicd-pipeline/google-cloud/scripts/create-sa.sh +36 -0
- package/skills/cicd-pipeline/google-cloud/scripts/gcp-config.sh +31 -0
- package/skills/cicd-pipeline/google-cloud/scripts/grant-iap.sh +41 -0
- package/skills/cicd-pipeline/google-cloud/scripts/setup-secrets.sh +48 -0
- package/skills/cicd-pipeline/mergify/LICENSE +3 -0
- package/skills/cicd-pipeline/mergify/SKILL.md +138 -0
- package/skills/cicd-pipeline/mergify/assets/templates/mergify.yml +237 -0
- package/skills/cicd-pipeline/mergify/assets/templates/ruleset.json +46 -0
- package/skills/cicd-pipeline/mergify/references/branch-protection.md +277 -0
- package/skills/cicd-pipeline/mergify/references/configuration.md +183 -0
- package/skills/cicd-pipeline/mergify/references/diagnosis.md +73 -0
- package/skills/cicd-pipeline/mergify/references/traps.md +78 -0
- package/skills/cicd-pipeline/mergify/references/watch-contract.md +218 -0
- package/skills/cicd-pipeline/mergify/scripts/audit-core.mjs +131 -0
- package/skills/cicd-pipeline/mergify/scripts/audit.mjs +4 -0
- package/skills/cicd-pipeline/mergify/scripts/watch-pr-delivery-core.mjs +663 -0
- package/skills/cicd-pipeline/mergify/scripts/watch-pr-delivery.mjs +4 -0
- package/skills/cicd-pipeline/podman/LICENSE +3 -0
- package/skills/cicd-pipeline/podman/SKILL.md +70 -0
- package/skills/cicd-pipeline/podman/agents/openai.yaml +4 -0
- package/skills/cicd-pipeline/podman/assets/templates/podman-compose-socket-directory.yml +6 -0
- package/skills/cicd-pipeline/podman/assets/templates/podman-service-override.conf +3 -0
- package/skills/cicd-pipeline/podman/references/compose-compatibility.md +70 -0
- package/skills/cicd-pipeline/podman/references/networking-and-ports.md +74 -0
- package/skills/cicd-pipeline/podman/references/rootless-services-and-sockets.md +156 -0
- package/skills/cicd-pipeline/podman/references/troubleshooting.md +98 -0
- package/skills/engineering/e2e-test/LICENSE +3 -0
- package/skills/engineering/e2e-test/SKILL.md +156 -0
- package/skills/engineering/e2e-test/assets/ci-gates.cloudbuild.yaml +272 -0
- package/skills/engineering/e2e-test/assets/ci-gates.github.yml +451 -0
- package/skills/engineering/e2e-test/assets/e2e-workflow.yml +282 -0
- package/skills/engineering/e2e-test/references/authoring/auth-flows.md +159 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-config.md +71 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-patterns.md +219 -0
- package/skills/engineering/e2e-test/references/authoring/test-skipping.md +44 -0
- package/skills/engineering/e2e-test/references/ci-integration.md +121 -0
- package/skills/engineering/e2e-test/references/ci-playwright-container.md +280 -0
- package/skills/engineering/e2e-test/references/debugging.md +36 -0
- package/skills/engineering/e2e-test/references/presentation-sweep.md +131 -0
- package/skills/engineering/e2e-test/references/reviewing.md +39 -0
- package/skills/engineering/e2e-test/references/route-discovery.md +50 -0
- package/skills/engineering/e2e-test/references/route-manifest.md +44 -0
- package/skills/engineering/e2e-test/scripts/detect-routes-fastapi.py +290 -0
- package/skills/engineering/e2e-test/scripts/detect-routes-nextjs.mjs +200 -0
- package/skills/engineering/e2e-test/scripts/post-visual-evidence.mjs +158 -0
- package/skills/engineering/e2e-test/scripts/presentation-checks.mjs +171 -0
- package/skills/engineering/e2e-test/scripts/presentation-perceivability.mjs +179 -0
- package/skills/engineering/e2e-test/scripts/presentation-reachability.mjs +154 -0
- package/skills/engineering/e2e-test/scripts/presentation-render-health.mjs +141 -0
- package/skills/engineering/e2e-test/scripts/presentation-sweep.mjs +148 -0
- package/skills/engineering/e2e-test/scripts/presentation-temporal.mjs +127 -0
- package/skills/engineering/e2e-test/scripts/presentation-visual.mjs +84 -0
- package/skills/engineering/e2e-test/scripts/project-route-manifest.mjs +75 -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 +10 -0
- package/skills/engineering/engineering-runtime/agents/openai.yaml +6 -0
- package/skills/engineering/engineering-runtime/coherence/workflow.json +553 -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/main-module.mjs +80 -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/workflow-coherence.mjs +576 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +166 -0
- package/skills/engineering/ensure-coverage/LICENSE +3 -0
- package/skills/engineering/ensure-coverage/SKILL.md +136 -0
- package/skills/engineering/ensure-coverage/evals/evals.json +125 -0
- package/skills/engineering/ensure-coverage/references/breadth/coverage-ledger.md +91 -0
- package/skills/engineering/ensure-coverage/references/breadth/inventory-contract.md +83 -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 +25 -0
- package/skills/engineering/ensure-coverage/references/depth/grading.md +35 -0
- package/skills/engineering/ensure-coverage/references/depth/mock-policy.md +87 -0
- package/skills/engineering/ensure-coverage/references/depth/test-smells.md +23 -0
- package/skills/engineering/ensure-coverage/references/enforcement/ci-contract.md +164 -0
- package/skills/engineering/ensure-coverage/references/enforcement/hooks.md +85 -0
- package/skills/engineering/ensure-coverage/references/examples/coverage-ledger.md +109 -0
- package/skills/engineering/ensure-coverage/references/examples/refund-flow.md +33 -0
- package/skills/engineering/ensure-coverage/references/presentation/axis.md +78 -0
- package/skills/engineering/ensure-coverage/references/presentation/runner-contract.md +74 -0
- package/skills/engineering/ensure-coverage/references/process/audit-mode.md +33 -0
- package/skills/engineering/ensure-coverage/references/process/output-template.md +139 -0
- package/skills/engineering/ensure-coverage/references/process/review-contract-template.md +119 -0
- package/skills/engineering/ensure-coverage/references/process/scope-class.md +178 -0
- package/skills/engineering/ensure-coverage/references/process/test-strategy.md +55 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-config.schema.json +45 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-file.schema.json +93 -0
- package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.mjs +178 -0
- package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.mjs +101 -0
- package/skills/engineering/ensure-coverage/scripts/ci-audit.mjs +358 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-checklist.mjs +494 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-ledger.mjs +663 -0
- package/skills/engineering/ensure-coverage/scripts/design-parity.mjs +591 -0
- package/skills/engineering/ensure-coverage/scripts/evidence-block.mjs +367 -0
- package/skills/engineering/ensure-coverage/scripts/lint-tests.mjs +269 -0
- package/skills/engineering/ensure-coverage/scripts/mock-policy-config.mjs +176 -0
- package/skills/engineering/ensure-coverage/scripts/package-lock.json +76 -0
- package/skills/engineering/ensure-coverage/scripts/package.json +19 -0
- package/skills/engineering/ensure-coverage/scripts/scope-class.mjs +554 -0
- package/skills/engineering/harness-runtime/LICENSE +3 -0
- package/skills/engineering/harness-runtime/SKILL.md +18 -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/fixtures/native-question-schemas.json +33 -0
- package/skills/engineering/harness-runtime/fixtures/question-responses.json +54 -0
- package/skills/engineering/harness-runtime/index.mjs +767 -0
- package/skills/engineering/harness-runtime/model-catalog.mjs +787 -0
- package/skills/engineering/harness-runtime/native-question-contracts.md +37 -0
- package/skills/engineering/harness-runtime/references/model-catalog-seed.json +159 -0
- package/skills/engineering/harness-runtime/references/model-catalog.md +57 -0
- package/skills/engineering/implement-and-pr/LICENSE +3 -0
- package/skills/engineering/implement-and-pr/SKILL.md +176 -0
- package/skills/engineering/implement-and-pr/references/ci-iteration.md +10 -0
- package/skills/engineering/implement-and-pr/references/closeout.md +27 -0
- package/skills/engineering/implement-and-pr/references/contract-complete-fix-rounds.md +34 -0
- package/skills/engineering/implement-and-pr/references/evidence-rules.md +39 -0
- package/skills/engineering/implement-and-pr/references/incremental-plan.md +16 -0
- package/skills/engineering/implement-and-pr/references/self-review.md +23 -0
- package/skills/engineering/implement-and-pr/references/tdd-mode.md +18 -0
- package/skills/engineering/resolve-issues/LICENSE +3 -0
- package/skills/engineering/resolve-issues/SKILL.md +167 -0
- package/skills/engineering/resolve-issues/generated/workflow-repair-policy.json +448 -0
- package/skills/engineering/resolve-issues/references/breaker.md +82 -0
- package/skills/engineering/resolve-issues/references/deliverables.md +27 -0
- package/skills/engineering/resolve-issues/references/delivery.md +108 -0
- package/skills/engineering/resolve-issues/references/evidence-lane.md +21 -0
- package/skills/engineering/resolve-issues/references/exact-head-ci.md +287 -0
- package/skills/engineering/resolve-issues/references/fan-out.md +33 -0
- package/skills/engineering/resolve-issues/references/finalization.md +68 -0
- package/skills/engineering/resolve-issues/references/guarantees.md +10 -0
- package/skills/engineering/resolve-issues/references/high-risk.md +29 -0
- package/skills/engineering/resolve-issues/references/incidents/848/README.md +156 -0
- package/skills/engineering/resolve-issues/references/intake.md +86 -0
- package/skills/engineering/resolve-issues/references/integration-gate.md +53 -0
- package/skills/engineering/resolve-issues/references/interference.md +87 -0
- package/skills/engineering/resolve-issues/references/loop.md +134 -0
- package/skills/engineering/resolve-issues/references/model-catalog.md +9 -0
- package/skills/engineering/resolve-issues/references/postmortem.md +27 -0
- package/skills/engineering/resolve-issues/references/pre-flight-model-slots.md +41 -0
- package/skills/engineering/resolve-issues/references/pre-flight-recording-and-checkout.md +48 -0
- package/skills/engineering/resolve-issues/references/pre-flight.md +41 -0
- package/skills/engineering/resolve-issues/references/regression-checklist.md +26 -0
- package/skills/engineering/resolve-issues/references/run-state.md +288 -0
- package/skills/engineering/resolve-issues/references/sandboxed-testing.md +48 -0
- package/skills/engineering/resolve-issues/references/spawn-contract.md +96 -0
- package/skills/engineering/resolve-issues/references/terminal-evidence-journal.md +40 -0
- package/skills/engineering/resolve-issues/references/why.md +653 -0
- package/skills/engineering/resolve-issues/schemas/fix-round.schema.json +49 -0
- package/skills/engineering/resolve-issues/scripts/combine-and-verify.mjs +721 -0
- package/skills/engineering/resolve-issues/scripts/component-candidate.mjs +962 -0
- package/skills/engineering/resolve-issues/scripts/contract-revision.mjs +220 -0
- package/skills/engineering/resolve-issues/scripts/detect-delivery-mode.mjs +420 -0
- package/skills/engineering/resolve-issues/scripts/detect-target-branch.mjs +256 -0
- package/skills/engineering/resolve-issues/scripts/detect-workspace-mode.mjs +168 -0
- package/skills/engineering/resolve-issues/scripts/discover-models.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/doctrine.mjs +62 -0
- package/skills/engineering/resolve-issues/scripts/evidence-lifecycle-contract.mjs +191 -0
- package/skills/engineering/resolve-issues/scripts/exact-head-ci.mjs +413 -0
- package/skills/engineering/resolve-issues/scripts/exact-head-github-provider.mjs +332 -0
- package/skills/engineering/resolve-issues/scripts/finalize.mjs +488 -0
- package/skills/engineering/resolve-issues/scripts/fix-rounds.mjs +3307 -0
- package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-circular-1001.json +16 -0
- package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-valid-sequencing.json +51 -0
- package/skills/engineering/resolve-issues/scripts/fixtures/fmm-express-830-component-candidate.json +17 -0
- package/skills/engineering/resolve-issues/scripts/fixtures/head-check-set-1081.json +166 -0
- package/skills/engineering/resolve-issues/scripts/gate-value-series.mjs +92 -0
- package/skills/engineering/resolve-issues/scripts/guide-index.mjs +73 -0
- package/skills/engineering/resolve-issues/scripts/head-check-set.mjs +159 -0
- package/skills/engineering/resolve-issues/scripts/interference.mjs +427 -0
- package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/next-operations.mjs +419 -0
- package/skills/engineering/resolve-issues/scripts/postmortem.mjs +909 -0
- package/skills/engineering/resolve-issues/scripts/preflight-questions.mjs +322 -0
- package/skills/engineering/resolve-issues/scripts/reconcile-contained-unit-prs.mjs +415 -0
- package/skills/engineering/resolve-issues/scripts/release-state-contract.mjs +697 -0
- package/skills/engineering/resolve-issues/scripts/report.mjs +494 -0
- package/skills/engineering/resolve-issues/scripts/required-check-plan.mjs +172 -0
- package/skills/engineering/resolve-issues/scripts/round-metadata.mjs +79 -0
- package/skills/engineering/resolve-issues/scripts/run-state-review6-cases.mjs +334 -0
- package/skills/engineering/resolve-issues/scripts/run-state.mjs +4784 -0
- package/skills/engineering/resolve-issues/scripts/sandbox-selftest.mjs +395 -0
- package/skills/engineering/resolve-issues/scripts/spawn-contract.mjs +290 -0
- package/skills/engineering/resolve-issues/scripts/terminal-dispositions.mjs +170 -0
- package/skills/engineering/resolve-issues/scripts/terminal-evidence-journal.mjs +293 -0
- package/skills/engineering/resolve-issues/scripts/unit-kind.mjs +197 -0
- package/skills/engineering/resolve-issues/scripts/unit-lifecycle.mjs +127 -0
- package/skills/engineering/resolve-issues/scripts/watch-delivery.mjs +893 -0
- package/skills/engineering/resolve-issues/scripts/workspaces.mjs +829 -0
- package/skills/engineering/resolve-issues/workflows/independent-review.workflow.js +290 -0
- package/skills/engineering/resolve-issues/workflows/prior-art-scan.workflow.js +80 -0
- package/skills/engineering/resolve-issues/workflows/workflow-smoke.mjs +102 -0
- package/skills/engineering/resolve-release/LICENSE +3 -0
- package/skills/engineering/resolve-release/SKILL.md +112 -0
- package/skills/engineering/resolve-release/references/assembly.md +137 -0
- package/skills/engineering/resolve-release/references/auto-when-green.md +56 -0
- package/skills/engineering/resolve-release/references/candidate.md +167 -0
- package/skills/engineering/resolve-release/references/exposure.md +178 -0
- package/skills/engineering/resolve-release/references/handoff.md +24 -0
- package/skills/engineering/resolve-release/references/postmortem.md +230 -0
- package/skills/engineering/resolve-release/references/preflight.md +207 -0
- package/skills/engineering/resolve-release/references/principles.md +94 -0
- package/skills/engineering/resolve-release/references/regression-checklist.md +36 -0
- package/skills/engineering/resolve-release/references/related-skills.md +12 -0
- package/skills/engineering/resolve-release/references/routing.md +149 -0
- package/skills/engineering/resolve-release/references/verified-sha-github-flow.md +285 -0
- package/skills/engineering/resolve-release/references/versioning.md +202 -0
- package/skills/engineering/resolve-release/references/why.md +53 -0
- package/skills/engineering/resolve-release/scripts/adapter-completion-artifact.mjs +389 -0
- package/skills/engineering/resolve-release/scripts/build-changes.mjs +209 -0
- package/skills/engineering/resolve-release/scripts/candidate-hygiene.mjs +407 -0
- package/skills/engineering/resolve-release/scripts/candidate-identity.mjs +904 -0
- package/skills/engineering/resolve-release/scripts/candidate-traffic.mjs +81 -0
- package/skills/engineering/resolve-release/scripts/checked-adapter-loader.mjs +612 -0
- package/skills/engineering/resolve-release/scripts/close-attempt.mjs +135 -0
- package/skills/engineering/resolve-release/scripts/closeout-release.mjs +161 -0
- package/skills/engineering/resolve-release/scripts/doctrine.mjs +106 -0
- package/skills/engineering/resolve-release/scripts/durable-processing.mjs +522 -0
- package/skills/engineering/resolve-release/scripts/ensure-target-green.mjs +659 -0
- package/skills/engineering/resolve-release/scripts/evidence-bundle.mjs +1014 -0
- package/skills/engineering/resolve-release/scripts/finalize-release.mjs +526 -0
- package/skills/engineering/resolve-release/scripts/fixtures/durable-processing-adapter.mjs +169 -0
- package/skills/engineering/resolve-release/scripts/green-gate.mjs +599 -0
- package/skills/engineering/resolve-release/scripts/isolated-adapter-evaluator.mjs +752 -0
- package/skills/engineering/resolve-release/scripts/metadata-pr-status.mjs +56 -0
- package/skills/engineering/resolve-release/scripts/metadata-sync.mjs +1538 -0
- package/skills/engineering/resolve-release/scripts/postmortem.mjs +381 -0
- package/skills/engineering/resolve-release/scripts/preflight-probes.mjs +498 -0
- package/skills/engineering/resolve-release/scripts/production-endpoints.mjs +326 -0
- package/skills/engineering/resolve-release/scripts/rc-circuit-breaker.mjs +272 -0
- package/skills/engineering/resolve-release/scripts/report.mjs +417 -0
- package/skills/engineering/resolve-release/scripts/reprobe-credentials.mjs +114 -0
- package/skills/engineering/resolve-release/scripts/revalidate-candidate.mjs +238 -0
- package/skills/engineering/resolve-release/scripts/review-packet.mjs +503 -0
- package/skills/engineering/resolve-release/scripts/rollback-floor.mjs +263 -0
- package/skills/engineering/resolve-release/scripts/version-assert.mjs +339 -0
- package/skills/engineering/resolve-release/scripts/version-postmortem.mjs +485 -0
- package/skills/engineering/resolve-release/scripts/version.mjs +1199 -0
- package/skills/engineering/resolve-release/scripts/watch-candidate-delivery.mjs +449 -0
- package/skills/engineering/resolve-release/vendor/ACORN-LICENSE +21 -0
- package/skills/engineering/resolve-release/vendor/README.md +60 -0
- package/skills/engineering/resolve-release/vendor/acorn.mjs +6233 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/LICENSE +21 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/README.md +341 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/README.template.md +70 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs +7 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.mts +2033 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.ts +2033 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js +7 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/package.json +49 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/LICENSE +21 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/README.md +5 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.mts +549 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.ts +549 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/package.json +36 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/LICENSE +47 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/README.md +82 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.d.ts +11 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.mjs +22 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cjs +21 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.cjs +21 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.d.ts +11 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.d.ts +11 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.mjs +25 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.wasm +0 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.mts +85 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.ts +85 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.mts +20 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.ts +20 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/package.json +61 -0
- package/skills/engineering/review-pr/LICENSE +3 -0
- package/skills/engineering/review-pr/SKILL.md +123 -0
- package/skills/engineering/review-pr/references/adversarial-reviewer-prompt.md +42 -0
- package/skills/engineering/review-pr/references/code-correctness.md +5 -0
- package/skills/engineering/review-pr/references/contract-freshness.md +9 -0
- package/skills/engineering/review-pr/references/coordination.md +18 -0
- package/skills/engineering/review-pr/references/domain-hazards.md +123 -0
- package/skills/engineering/review-pr/references/finding-themes.md +7 -0
- package/skills/engineering/review-pr/references/github-posting.md +98 -0
- package/skills/engineering/review-pr/references/golden-path-smoke.md +5 -0
- package/skills/engineering/review-pr/references/incremental-output.md +16 -0
- package/skills/engineering/review-pr/references/inputs-and-discovery.md +31 -0
- package/skills/engineering/review-pr/references/output-format.md +99 -0
- package/skills/engineering/review-pr/references/over-mock-screen.md +7 -0
- package/skills/engineering/review-pr/references/promotion-prs.md +16 -0
- package/skills/engineering/review-pr/references/re-review.md +18 -0
- package/skills/engineering/review-pr/references/review-method.md +199 -0
- package/skills/engineering/review-pr/references/review-mode.md +30 -0
- package/skills/engineering/review-pr/references/review-posture.md +53 -0
- package/skills/engineering/review-pr/references/round1-depth.md +62 -0
- package/skills/engineering/review-pr/references/scripts.md +17 -0
- package/skills/engineering/review-pr/references/workflow.md +16 -0
- package/skills/engineering/review-pr/schemas/findings.schema.json +282 -0
- package/skills/engineering/review-pr/scripts/finding-contract.mjs +285 -0
- package/skills/engineering/review-pr/scripts/post-review.mjs +405 -0
- package/skills/engineering/review-pr/scripts/pr-context.mjs +207 -0
- package/skills/engineering/review-pr/scripts/scan-diff.mjs +365 -0
- package/skills/engineering/review-pr/scripts/theme-contract.mjs +57 -0
- package/skills/engineering/smoke/LICENSE +3 -0
- package/skills/engineering/smoke/SKILL.md +131 -0
- package/skills/engineering/smoke/assets/smoke.manifest.example.json +53 -0
- package/skills/engineering/smoke/references/manifest.md +192 -0
- package/skills/engineering/smoke/scripts/smoke.mjs +713 -0
- package/skills/fullstack/better-auth/LICENSE +3 -0
- package/skills/fullstack/better-auth/SKILL.md +601 -0
- package/skills/fullstack/better-auth/references/feishu-api.md +270 -0
- package/skills/fullstack/monorepo/LICENSE +3 -0
- package/skills/fullstack/monorepo/SKILL.md +465 -0
- package/skills/fullstack/nextjs-fullstack/LICENSE +3 -0
- package/skills/fullstack/nextjs-fullstack/SKILL.md +210 -0
- package/skills/fullstack/nextjs-fullstack/conventions.md +318 -0
- package/skills/fullstack/nextjs-fullstack/frontend-conventions.md +61 -0
- package/skills/fullstack/nextjs-fullstack/nextjs16.md +287 -0
- package/skills/fullstack/nextjs-fullstack/server-actions.md +409 -0
- package/skills/fullstack/prisma-setup/LICENSE +3 -0
- package/skills/fullstack/prisma-setup/SKILL.md +180 -0
- package/skills/fullstack/prisma-setup/nextjs.md +258 -0
- package/skills/fullstack/prisma-setup/turborepo.md +301 -0
- package/skills/fullstack/shadcn/LICENSE +3 -0
- package/skills/fullstack/shadcn/SKILL.md +119 -0
- package/skills/fullstack/shadcn/assets/shadcn-small.png +0 -0
- package/skills/fullstack/shadcn/assets/shadcn.png +0 -0
- package/skills/fullstack/shadcn/cli.md +411 -0
- package/skills/fullstack/shadcn/customization.md +224 -0
- package/skills/fullstack/shadcn/evals/evals.json +90 -0
- package/skills/fullstack/shadcn/mcp.md +101 -0
- package/skills/fullstack/shadcn/rules/base-vs-radix.md +323 -0
- package/skills/fullstack/shadcn/rules/component-selection.md +67 -0
- package/skills/fullstack/shadcn/rules/composition.md +195 -0
- package/skills/fullstack/shadcn/rules/data-table.md +201 -0
- package/skills/fullstack/shadcn/rules/forms.md +255 -0
- package/skills/fullstack/shadcn/rules/icons.md +103 -0
- package/skills/fullstack/shadcn/rules/styling.md +167 -0
- package/skills/fullstack/zod-v4/LICENSE +3 -0
- package/skills/fullstack/zod-v4/SKILL.md +287 -0
|
@@ -0,0 +1,659 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ensure-target-green — mechanize the repair lane as a reusable pre-envelope phase (#807).
|
|
3
|
+
//
|
|
4
|
+
// Productizes the prose "repair lane" in SKILL.md + the `target-gate-colour` probe into a
|
|
5
|
+
// named, scripted path:
|
|
6
|
+
//
|
|
7
|
+
// 1. classify failures (required gates only when --gate is set)
|
|
8
|
+
// 2. if all failures ∈ allowlisted classes → open repair unit(s) via resolve-issues brief
|
|
9
|
+
// else → hand structured human brief (supervised) or block
|
|
10
|
+
// 3. land → re-run target-gate-colour on the NEW tip
|
|
11
|
+
// 4. only then propose/confirm envelope (or resume same attempt)
|
|
12
|
+
//
|
|
13
|
+
// SCOPE: tip check-runs only.
|
|
14
|
+
// - Live floor / public-host DEAD while CI green → #800 (floorReadiness / rollback-floor)
|
|
15
|
+
// - Tooling that lies about tip green (stale local main, tag push, blank percent) → #799
|
|
16
|
+
// Do not conflate those with this phase.
|
|
17
|
+
//
|
|
18
|
+
// Modes:
|
|
19
|
+
// supervised (default) — classify + structured brief; never auto-opens repair
|
|
20
|
+
// auto-repair-allowlist — auto-open repair only when every failure is allowlisted
|
|
21
|
+
//
|
|
22
|
+
// Budget: maxRepairRounds (default 2) + wallClockMinutes (default 60) so permanent flakes
|
|
23
|
+
// cannot thrash forever.
|
|
24
|
+
//
|
|
25
|
+
// JSON contract:
|
|
26
|
+
// { state: green|repairing|blocked|unknown, headSha, failing[{name,conclusion,class,allowlisted}],
|
|
27
|
+
// repair?, reprobe?, brief?, override?, attempts[], startedAt, finishedAt, durationMs }
|
|
28
|
+
//
|
|
29
|
+
// Manifest: release.ensureGreen = { startedAt, attempts[], finalHead, outcome, failingClasses[],
|
|
30
|
+
// repairPrs[], durationMs }
|
|
31
|
+
|
|
32
|
+
import { execFileSync } from 'node:child_process'
|
|
33
|
+
import { readFileSync } from 'node:fs'
|
|
34
|
+
import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
|
|
35
|
+
|
|
36
|
+
export const STATES = {
|
|
37
|
+
GREEN: 'green',
|
|
38
|
+
REPAIRING: 'repairing',
|
|
39
|
+
BLOCKED: 'blocked',
|
|
40
|
+
UNKNOWN: 'unknown',
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const MODES = {
|
|
44
|
+
SUPERVISED: 'supervised',
|
|
45
|
+
AUTO_REPAIR_ALLOWLIST: 'auto-repair-allowlist',
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const DEFAULT_MAX_REPAIR_ROUNDS = 2
|
|
49
|
+
export const DEFAULT_WALL_CLOCK_MINUTES = 60
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Repo-declared allowlist / never-auto map. Callers may override via --classify-config.
|
|
53
|
+
* Order matters: first match wins. Critical / hazard patterns must outrank flake heuristics.
|
|
54
|
+
*/
|
|
55
|
+
export const DEFAULT_CLASSIFY_CONFIG = {
|
|
56
|
+
optionalGates: [],
|
|
57
|
+
// Never auto without human — checked first.
|
|
58
|
+
neverAuto: [
|
|
59
|
+
{ class: 'critical', pattern: /auth|authz|session|oauth|token|cookie|password|credential/i },
|
|
60
|
+
{ class: 'critical', pattern: /money|payment|billing|tax|pricing|invoice|ledger|refund/i },
|
|
61
|
+
{ class: 'critical', pattern: /tenant|tenancy|org[-_]?scope|multi[-_]?tenant/i },
|
|
62
|
+
{ class: 'critical', pattern: /migrat|schema\.prisma|prisma migrate|alembic|flyway/i },
|
|
63
|
+
{ class: 'critical', pattern: /post[-_]?deploy|prod[-_]?active|smoke|production/i },
|
|
64
|
+
{ class: 'critical', pattern: /release[-_]?readiness|green[-_]?gate|traffic shift|expose/i },
|
|
65
|
+
],
|
|
66
|
+
allowlist: [
|
|
67
|
+
{ class: 'flake', pattern: /flak|intermittent|order.?dependent|race.?condition|retry/i },
|
|
68
|
+
{ class: 'digest-drift', pattern: /contentDigest|digest drift|workflow.?digest|distribution/i },
|
|
69
|
+
{ class: 'external-fetch', pattern: /ECONNRESET|ETIMEDOUT|ENOTFOUND|registry\.npmjs|fetch failed|network/i },
|
|
70
|
+
{ class: 'missing-optional', pattern: /reported no check-run|absent check/i, onlyOptionalGate: true },
|
|
71
|
+
],
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Terminal conclusions that may count as green. Anything else is not-green. */
|
|
75
|
+
export const ALLOWED_TERMINAL_CONCLUSIONS = new Set(['SUCCESS', 'SKIPPED', 'NEUTRAL'])
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* A check is blocking when it is not completed with an allowed terminal conclusion.
|
|
79
|
+
* GitHub stores in-progress conclusions as null (fetchTip normalizes to ""); those
|
|
80
|
+
* must not silent-green. When `status` is present and not COMPLETED, block even if
|
|
81
|
+
* a conclusion string looks terminal.
|
|
82
|
+
*/
|
|
83
|
+
export function isCheckBlocking(check) {
|
|
84
|
+
if (!check) return true
|
|
85
|
+
const conclusion = String(check.conclusion || '').toUpperCase()
|
|
86
|
+
const status = String(check.status || '').toUpperCase()
|
|
87
|
+
if (status && status !== 'COMPLETED') return true
|
|
88
|
+
if (!ALLOWED_TERMINAL_CONCLUSIONS.has(conclusion)) return true
|
|
89
|
+
return false
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function classifyFailure(check, config = DEFAULT_CLASSIFY_CONFIG) {
|
|
93
|
+
const name = String(check?.name || '')
|
|
94
|
+
const status = String(check?.status || '')
|
|
95
|
+
const rawConclusion = String(check?.conclusion || '')
|
|
96
|
+
// Present but incomplete checks often have conclusion:"" — surface status so briefs are readable.
|
|
97
|
+
const conclusion = rawConclusion
|
|
98
|
+
|| (status && status.toUpperCase() !== 'COMPLETED' ? status : rawConclusion)
|
|
99
|
+
|| 'PENDING'
|
|
100
|
+
const output = String(check?.output || check?.detail || '')
|
|
101
|
+
const text = `${name}\n${output}\n${conclusion}\n${status}`
|
|
102
|
+
const optionalGates = Array.isArray(config.optionalGates) ? config.optionalGates : []
|
|
103
|
+
|
|
104
|
+
for (const rule of config.neverAuto || []) {
|
|
105
|
+
if (rule.pattern.test(text)) {
|
|
106
|
+
return {
|
|
107
|
+
name,
|
|
108
|
+
conclusion,
|
|
109
|
+
status,
|
|
110
|
+
class: rule.class || 'critical',
|
|
111
|
+
allowlisted: false,
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
for (const rule of config.allowlist || []) {
|
|
117
|
+
if (!rule.pattern.test(text)) continue
|
|
118
|
+
if (rule.onlyOptionalGate) {
|
|
119
|
+
if (optionalGates.includes(name)) {
|
|
120
|
+
return { name, conclusion, status, class: rule.class, allowlisted: true }
|
|
121
|
+
}
|
|
122
|
+
// Missing *required* gate is critical, never allowlisted.
|
|
123
|
+
return { name, conclusion, status, class: 'critical', allowlisted: false }
|
|
124
|
+
}
|
|
125
|
+
return { name, conclusion, status, class: rule.class, allowlisted: true }
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return { name, conclusion, status, class: 'unknown', allowlisted: false }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Classify every failing, incomplete, or missing-required check on the tip.
|
|
133
|
+
* A required check that is present but still in progress is blocked/not-green —
|
|
134
|
+
* never silent green on an empty conclusion.
|
|
135
|
+
*/
|
|
136
|
+
export function classifyFailures({ checks, gates = [], config = DEFAULT_CLASSIFY_CONFIG } = {}) {
|
|
137
|
+
if (!Array.isArray(checks)) return []
|
|
138
|
+
const relevant = gates.length > 0 ? checks.filter((c) => gates.includes(c.name)) : checks
|
|
139
|
+
const failing = relevant.filter((c) => isCheckBlocking(c))
|
|
140
|
+
// Missing required gates also count as failures.
|
|
141
|
+
if (gates.length > 0) {
|
|
142
|
+
for (const g of gates) {
|
|
143
|
+
if (!checks.some((c) => c.name === g)) {
|
|
144
|
+
failing.push({
|
|
145
|
+
name: g,
|
|
146
|
+
conclusion: 'MISSING',
|
|
147
|
+
status: '',
|
|
148
|
+
output: 'required gate(s) reported no check-run on the target head',
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return failing.map((c) => classifyFailure(c, config))
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Core ensure path. All I/O is injectable so tests never hit the network.
|
|
158
|
+
*
|
|
159
|
+
* @param {object} opts
|
|
160
|
+
* @param {string|null} opts.headSha
|
|
161
|
+
* @param {Array|null} opts.checks
|
|
162
|
+
* @param {boolean} opts.readable
|
|
163
|
+
* @param {string[]} [opts.gates]
|
|
164
|
+
* @param {object} [opts.config]
|
|
165
|
+
* @param {'supervised'|'auto-repair-allowlist'} [opts.mode]
|
|
166
|
+
* @param {number} [opts.maxRepairRounds]
|
|
167
|
+
* @param {number} [opts.wallClockMinutes]
|
|
168
|
+
* @param {{recorded:boolean,by?:string,reason?:string}|null} [opts.humanOverride]
|
|
169
|
+
* @param {(brief:object)=>Promise<object>} opts.openRepair mockable resolve-issues handoff
|
|
170
|
+
* @param {()=>Promise<{headSha,checks,readable}>} opts.reProbe mandatory re-probe after repair
|
|
171
|
+
* @param {()=>number} [opts.now] ms since epoch (test clock)
|
|
172
|
+
*/
|
|
173
|
+
export async function ensureTargetGreen(opts = {}) {
|
|
174
|
+
const {
|
|
175
|
+
headSha = null,
|
|
176
|
+
checks = null,
|
|
177
|
+
readable = true,
|
|
178
|
+
gates = [],
|
|
179
|
+
config = DEFAULT_CLASSIFY_CONFIG,
|
|
180
|
+
mode = MODES.SUPERVISED,
|
|
181
|
+
maxRepairRounds = DEFAULT_MAX_REPAIR_ROUNDS,
|
|
182
|
+
wallClockMinutes = DEFAULT_WALL_CLOCK_MINUTES,
|
|
183
|
+
humanOverride = null,
|
|
184
|
+
openRepair,
|
|
185
|
+
reProbe,
|
|
186
|
+
now = () => Date.now(),
|
|
187
|
+
} = opts
|
|
188
|
+
|
|
189
|
+
const startedAtMs = now()
|
|
190
|
+
const startedAt = new Date(startedAtMs).toISOString()
|
|
191
|
+
const deadline = startedAtMs + wallClockMinutes * 60_000
|
|
192
|
+
const attempts = []
|
|
193
|
+
|
|
194
|
+
const finish = (partial) => {
|
|
195
|
+
const finishedAtMs = now()
|
|
196
|
+
return {
|
|
197
|
+
...partial,
|
|
198
|
+
startedAt,
|
|
199
|
+
finishedAt: new Date(finishedAtMs).toISOString(),
|
|
200
|
+
durationMs: finishedAtMs - startedAtMs,
|
|
201
|
+
attempts,
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Explicit human override recorded on the envelope may green without tip green.
|
|
206
|
+
if (humanOverride && humanOverride.recorded) {
|
|
207
|
+
attempts.push({ round: 0, state: STATES.GREEN, via: 'human-override' })
|
|
208
|
+
return finish({
|
|
209
|
+
state: STATES.GREEN,
|
|
210
|
+
headSha,
|
|
211
|
+
failing: [],
|
|
212
|
+
override: humanOverride,
|
|
213
|
+
reprobe: { required: false, skipped: 'human-override' },
|
|
214
|
+
})
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (!readable || !Array.isArray(checks)) {
|
|
218
|
+
attempts.push({ round: 0, state: STATES.UNKNOWN })
|
|
219
|
+
return finish({
|
|
220
|
+
state: STATES.UNKNOWN,
|
|
221
|
+
headSha,
|
|
222
|
+
failing: [],
|
|
223
|
+
brief: {
|
|
224
|
+
reason: 'unread-check-runs',
|
|
225
|
+
detail: 'the target branch check-runs could not be read — unknown is not green (#807 / principle 13)',
|
|
226
|
+
},
|
|
227
|
+
})
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// classifyFailures is the source of truth for green — includes present-but-incomplete
|
|
231
|
+
// required gates (empty conclusion / non-COMPLETED status), not only terminal failures.
|
|
232
|
+
let currentHead = headSha
|
|
233
|
+
let currentChecks = checks
|
|
234
|
+
let failing = classifyFailures({ checks: currentChecks, gates, config })
|
|
235
|
+
|
|
236
|
+
if (failing.length === 0) {
|
|
237
|
+
attempts.push({ round: 0, state: STATES.GREEN, headSha: currentHead })
|
|
238
|
+
return finish({
|
|
239
|
+
state: STATES.GREEN,
|
|
240
|
+
headSha: currentHead,
|
|
241
|
+
failing: [],
|
|
242
|
+
})
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Tip red.
|
|
246
|
+
attempts.push({
|
|
247
|
+
round: 0,
|
|
248
|
+
state: STATES.BLOCKED,
|
|
249
|
+
headSha: currentHead,
|
|
250
|
+
failingClasses: failing.map((f) => f.class),
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
const allAllowlisted = failing.every((f) => f.allowlisted)
|
|
254
|
+
|
|
255
|
+
if (mode !== MODES.AUTO_REPAIR_ALLOWLIST) {
|
|
256
|
+
return finish({
|
|
257
|
+
state: STATES.BLOCKED,
|
|
258
|
+
headSha: currentHead,
|
|
259
|
+
failing,
|
|
260
|
+
brief: {
|
|
261
|
+
reason: 'supervised-mode',
|
|
262
|
+
strategy: 'resolve-issues',
|
|
263
|
+
failing,
|
|
264
|
+
detail:
|
|
265
|
+
'tip is red; supervised mode hands a structured brief and holds the lease — do not auto-fix. ' +
|
|
266
|
+
'Re-run ensure-target-green after repair lands, or pass humanOverride on the envelope.',
|
|
267
|
+
},
|
|
268
|
+
})
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (!allAllowlisted) {
|
|
272
|
+
return finish({
|
|
273
|
+
state: STATES.BLOCKED,
|
|
274
|
+
headSha: currentHead,
|
|
275
|
+
failing,
|
|
276
|
+
brief: {
|
|
277
|
+
reason: 'non-allowlisted-failure',
|
|
278
|
+
strategy: 'human',
|
|
279
|
+
failing,
|
|
280
|
+
detail:
|
|
281
|
+
'at least one failure is critical/unknown — never auto-repair without a human ' +
|
|
282
|
+
'(auth/money/tenancy/migration, critical release gate, unknown class)',
|
|
283
|
+
},
|
|
284
|
+
})
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Allowlisted under auto-repair-allowlist: open repair, re-probe, loop under budget.
|
|
288
|
+
if (typeof openRepair !== 'function' || typeof reProbe !== 'function') {
|
|
289
|
+
return finish({
|
|
290
|
+
state: STATES.BLOCKED,
|
|
291
|
+
headSha: currentHead,
|
|
292
|
+
failing,
|
|
293
|
+
brief: {
|
|
294
|
+
reason: 'missing-handoff-seam',
|
|
295
|
+
detail: 'openRepair and reProbe seams are required for the auto-repair path',
|
|
296
|
+
},
|
|
297
|
+
})
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
let lastRepair = null
|
|
301
|
+
let lastReprobe = null
|
|
302
|
+
for (let round = 1; round <= maxRepairRounds; round += 1) {
|
|
303
|
+
if (now() > deadline) {
|
|
304
|
+
return finish({
|
|
305
|
+
state: STATES.BLOCKED,
|
|
306
|
+
headSha: currentHead,
|
|
307
|
+
failing,
|
|
308
|
+
repair: lastRepair,
|
|
309
|
+
reprobe: { required: true, ...(lastReprobe || {}) },
|
|
310
|
+
brief: {
|
|
311
|
+
reason: 'repair-budget-exhausted',
|
|
312
|
+
detail: `wall-clock budget of ${wallClockMinutes}m exhausted after ${round - 1} repair round(s)`,
|
|
313
|
+
},
|
|
314
|
+
})
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const brief = {
|
|
318
|
+
strategy: 'resolve-issues',
|
|
319
|
+
headSha: currentHead,
|
|
320
|
+
failing,
|
|
321
|
+
lease: 'held', // same release attempt lease throughout
|
|
322
|
+
note: 'repair inside the attempt; do not open a second release behind it',
|
|
323
|
+
}
|
|
324
|
+
attempts.push({ round, state: STATES.REPAIRING, headSha: currentHead })
|
|
325
|
+
lastRepair = await openRepair(brief)
|
|
326
|
+
// Re-probe is mandatory after repair lands — never claim green on the old tip.
|
|
327
|
+
lastReprobe = await reProbe()
|
|
328
|
+
currentHead = lastReprobe?.headSha ?? currentHead
|
|
329
|
+
currentChecks = lastReprobe?.checks
|
|
330
|
+
const reReadable = lastReprobe?.readable !== false && Array.isArray(currentChecks)
|
|
331
|
+
|
|
332
|
+
if (!reReadable) {
|
|
333
|
+
attempts.push({ round, state: STATES.UNKNOWN, headSha: currentHead, phase: 'reprobe' })
|
|
334
|
+
return finish({
|
|
335
|
+
state: STATES.UNKNOWN,
|
|
336
|
+
headSha: currentHead,
|
|
337
|
+
failing,
|
|
338
|
+
repair: lastRepair,
|
|
339
|
+
reprobe: { required: true, readable: false },
|
|
340
|
+
brief: {
|
|
341
|
+
reason: 'reprobe-unread',
|
|
342
|
+
detail: 're-probe could not read check-runs on the new tip — unknown is not green',
|
|
343
|
+
},
|
|
344
|
+
})
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
failing = classifyFailures({ checks: currentChecks, gates, config })
|
|
348
|
+
if (failing.length === 0) {
|
|
349
|
+
attempts.push({ round, state: STATES.GREEN, headSha: currentHead, phase: 'reprobe' })
|
|
350
|
+
return finish({
|
|
351
|
+
state: STATES.GREEN,
|
|
352
|
+
headSha: currentHead,
|
|
353
|
+
failing: [],
|
|
354
|
+
repair: lastRepair,
|
|
355
|
+
reprobe: { required: true, headSha: currentHead, state: STATES.GREEN },
|
|
356
|
+
})
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
attempts.push({
|
|
360
|
+
round,
|
|
361
|
+
state: STATES.BLOCKED,
|
|
362
|
+
headSha: currentHead,
|
|
363
|
+
phase: 'reprobe',
|
|
364
|
+
failingClasses: failing.map((f) => f.class),
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
// Still red — only continue if still fully allowlisted.
|
|
368
|
+
if (!failing.every((f) => f.allowlisted)) {
|
|
369
|
+
return finish({
|
|
370
|
+
state: STATES.BLOCKED,
|
|
371
|
+
headSha: currentHead,
|
|
372
|
+
failing,
|
|
373
|
+
repair: lastRepair,
|
|
374
|
+
reprobe: { required: true, headSha: currentHead, state: STATES.BLOCKED },
|
|
375
|
+
brief: {
|
|
376
|
+
reason: 'non-allowlisted-failure',
|
|
377
|
+
failing,
|
|
378
|
+
detail: 're-probe still red with a non-allowlisted class — hand to human',
|
|
379
|
+
},
|
|
380
|
+
})
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
return finish({
|
|
385
|
+
state: STATES.BLOCKED,
|
|
386
|
+
headSha: currentHead,
|
|
387
|
+
failing,
|
|
388
|
+
repair: lastRepair,
|
|
389
|
+
reprobe: { required: true, ...(lastReprobe ? { headSha: lastReprobe.headSha } : {}) },
|
|
390
|
+
brief: {
|
|
391
|
+
reason: 'repair-budget-exhausted',
|
|
392
|
+
detail: `maxRepairRounds=${maxRepairRounds} exhausted; tip still red — permanent flake cannot thrash forever`,
|
|
393
|
+
},
|
|
394
|
+
})
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/** Write release.ensureGreen onto a manifest (pure). */
|
|
398
|
+
export function recordEnsureGreen(manifest, result) {
|
|
399
|
+
const m = structuredClone(manifest || {})
|
|
400
|
+
if (!m.release || typeof m.release !== 'object') m.release = {}
|
|
401
|
+
m.release.ensureGreen = {
|
|
402
|
+
startedAt: result.startedAt,
|
|
403
|
+
finishedAt: result.finishedAt,
|
|
404
|
+
durationMs: result.durationMs,
|
|
405
|
+
attempts: result.attempts || [],
|
|
406
|
+
finalHead: result.headSha || null,
|
|
407
|
+
outcome: result.state,
|
|
408
|
+
failingClasses: (result.failing || []).map((f) => f.class),
|
|
409
|
+
repairPrs: result.repair?.prs || [],
|
|
410
|
+
repairIssues: result.repair?.issues || [],
|
|
411
|
+
override: result.override || null,
|
|
412
|
+
}
|
|
413
|
+
return m
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export function parseArgs(argv) {
|
|
417
|
+
const args = {
|
|
418
|
+
gates: [],
|
|
419
|
+
mode: MODES.SUPERVISED,
|
|
420
|
+
maxRepairRounds: DEFAULT_MAX_REPAIR_ROUNDS,
|
|
421
|
+
wallClockMinutes: DEFAULT_WALL_CLOCK_MINUTES,
|
|
422
|
+
}
|
|
423
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
424
|
+
const a = argv[i]
|
|
425
|
+
if (a === '--repo') args.repo = argv[++i]
|
|
426
|
+
else if (a === '--target-branch') args.targetBranch = argv[++i]
|
|
427
|
+
else if (a === '--gate') args.gates.push(argv[++i])
|
|
428
|
+
else if (a === '--classify-config') args.classifyConfig = argv[++i]
|
|
429
|
+
else if (a === '--mode') args.mode = argv[++i]
|
|
430
|
+
else if (a === '--max-repair-rounds') args.maxRepairRounds = Number(argv[++i])
|
|
431
|
+
else if (a === '--wall-clock-minutes') args.wallClockMinutes = Number(argv[++i])
|
|
432
|
+
else if (a === '--json') args.json = true
|
|
433
|
+
else if (a === '--help' || a === '-h') args.help = true
|
|
434
|
+
else if (a === '--dry-classify') args.dryClassify = true
|
|
435
|
+
else if (a.startsWith('-')) {
|
|
436
|
+
// Keep the first unknown flag token (not a following value) so --gat x reports --gat.
|
|
437
|
+
if (!args.unknown) args.unknown = a
|
|
438
|
+
} else if (!args.unknown) {
|
|
439
|
+
// No positionals on this CLI — bare junk is also a usage error (exit 2).
|
|
440
|
+
args.unknown = a
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return args
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function help() {
|
|
447
|
+
return `ensure-target-green — tip check-runs repair phase (#807)
|
|
448
|
+
|
|
449
|
+
Standalone surface (Option 4). Classifies target-branch tip failures, optionally
|
|
450
|
+
opens allowlisted repair work via a resolve-issues brief, re-probes the NEW tip,
|
|
451
|
+
and only then reports green so the release envelope can proceed.
|
|
452
|
+
|
|
453
|
+
Usage:
|
|
454
|
+
node …/ensure-target-green.mjs \\
|
|
455
|
+
--repo <owner/name> --target-branch <prod> \\
|
|
456
|
+
[--gate <check-name>…] \\
|
|
457
|
+
[--classify-config <path>] \\
|
|
458
|
+
[--mode supervised|auto-repair-allowlist] \\
|
|
459
|
+
[--max-repair-rounds <n>] \\
|
|
460
|
+
[--wall-clock-minutes <n>] \\
|
|
461
|
+
[--json] [--dry-classify]
|
|
462
|
+
|
|
463
|
+
Modes:
|
|
464
|
+
supervised (default) classify + structured brief; never auto-opens repair
|
|
465
|
+
auto-repair-allowlist open repair only when every failure is allowlisted
|
|
466
|
+
|
|
467
|
+
Exit codes:
|
|
468
|
+
0 state=green
|
|
469
|
+
1 state=blocked|repairing|unknown (not green — do not confirm envelope)
|
|
470
|
+
2 usage error
|
|
471
|
+
|
|
472
|
+
Non-overlap:
|
|
473
|
+
· tip check-runs only — live floor / public-host DEAD is #800 (floorReadiness)
|
|
474
|
+
· true remote tip / tag-push / blank-percent honesty is #799
|
|
475
|
+
· never skip/weaken required gates; never claim green on a different SHA
|
|
476
|
+
· never stuff tip repairs into the promotion PR
|
|
477
|
+
|
|
478
|
+
JSON: { state, headSha, failing[{name,conclusion,class,allowlisted}], repair?, reprobe?, brief? }`
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const safeJson = (t) => { try { return JSON.parse(t) } catch { return null } }
|
|
482
|
+
|
|
483
|
+
/** owner/name only — rejects shell metacharacters before any process spawn. */
|
|
484
|
+
export const REPO_NAME_RE = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/
|
|
485
|
+
|
|
486
|
+
export function isValidRepo(repo) {
|
|
487
|
+
return REPO_NAME_RE.test(String(repo || ''))
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Invoke `gh api` via argv (never /bin/sh -c). Path segments are validated/
|
|
492
|
+
* encoded so operator- or orchestrator-supplied --repo cannot inject shell.
|
|
493
|
+
*/
|
|
494
|
+
function ghApi({ path, jq, timeout = 60_000 } = {}) {
|
|
495
|
+
try {
|
|
496
|
+
const args = ['api', path]
|
|
497
|
+
if (jq != null) args.push('--jq', jq)
|
|
498
|
+
const stdout = execFileSync('gh', args, {
|
|
499
|
+
encoding: 'utf8',
|
|
500
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
501
|
+
timeout,
|
|
502
|
+
})
|
|
503
|
+
return { ok: true, stdout, stderr: '' }
|
|
504
|
+
} catch (error) {
|
|
505
|
+
return {
|
|
506
|
+
ok: false,
|
|
507
|
+
stdout: error.stdout?.toString?.() || '',
|
|
508
|
+
stderr: error.stderr?.toString?.() || error.message || '',
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
function loadConfig(path) {
|
|
514
|
+
if (!path) return DEFAULT_CLASSIFY_CONFIG
|
|
515
|
+
const raw = JSON.parse(readFileSync(path, 'utf8'))
|
|
516
|
+
// Patterns arrive as strings in JSON; compile them.
|
|
517
|
+
const compile = (rules = []) => rules.map((r) => ({
|
|
518
|
+
...r,
|
|
519
|
+
pattern: r.pattern instanceof RegExp ? r.pattern : new RegExp(r.pattern, r.flags || 'i'),
|
|
520
|
+
}))
|
|
521
|
+
return {
|
|
522
|
+
optionalGates: raw.optionalGates || [],
|
|
523
|
+
neverAuto: compile(raw.neverAuto || DEFAULT_CLASSIFY_CONFIG.neverAuto.map((r) => ({
|
|
524
|
+
class: r.class,
|
|
525
|
+
pattern: r.pattern.source,
|
|
526
|
+
flags: r.pattern.flags,
|
|
527
|
+
}))),
|
|
528
|
+
allowlist: compile(raw.allowlist || DEFAULT_CLASSIFY_CONFIG.allowlist.map((r) => ({
|
|
529
|
+
class: r.class,
|
|
530
|
+
pattern: r.pattern.source,
|
|
531
|
+
flags: r.pattern.flags,
|
|
532
|
+
onlyOptionalGate: r.onlyOptionalGate,
|
|
533
|
+
}))),
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Fetch tip SHA + check-runs without a shell. Repo must be owner/name;
|
|
539
|
+
* branch is a single path segment (URI-encoded), never interpolated into sh -c.
|
|
540
|
+
* Exported for regression tests that assert argv form / validation.
|
|
541
|
+
*/
|
|
542
|
+
export function fetchTip({ repo, targetBranch, api = ghApi } = {}) {
|
|
543
|
+
if (!isValidRepo(repo)) {
|
|
544
|
+
return {
|
|
545
|
+
headSha: null,
|
|
546
|
+
checks: null,
|
|
547
|
+
readable: false,
|
|
548
|
+
error: `invalid --repo ${repo}; expected owner/name`,
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
const branch = encodeURIComponent(String(targetBranch || ''))
|
|
552
|
+
const sha = api({ path: `repos/${repo}/commits/${branch}`, jq: '.sha' })
|
|
553
|
+
const checks = api({
|
|
554
|
+
path: `repos/${repo}/commits/${branch}/check-runs`,
|
|
555
|
+
jq: '[.check_runs[] | {name: .name, status: (.status // ""), conclusion: (.conclusion // ""), output: ((.output.summary // "") + " " + (.output.title // ""))}]',
|
|
556
|
+
})
|
|
557
|
+
return {
|
|
558
|
+
headSha: sha.ok ? String(sha.stdout || '').trim() : null,
|
|
559
|
+
checks: checks.ok ? safeJson(checks.stdout) : null,
|
|
560
|
+
readable: sha.ok && checks.ok,
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Default openRepair: emit a structured resolve-issues brief to stdout/stderr and return
|
|
566
|
+
* a handoff record. Real spawn is the caller's job (agent / resolve-release phase); this
|
|
567
|
+
* seam is deliberately mockable and does not nest an orchestrator in v1.
|
|
568
|
+
*/
|
|
569
|
+
export async function defaultOpenRepair(brief) {
|
|
570
|
+
// Structured brief the agent (or resolve-issues) consumes. We do not auto-merge anything.
|
|
571
|
+
return {
|
|
572
|
+
opened: true,
|
|
573
|
+
strategy: 'resolve-issues',
|
|
574
|
+
brief,
|
|
575
|
+
issues: [],
|
|
576
|
+
prs: [],
|
|
577
|
+
note: 'structured brief ready — open/land repair via resolve-issues while the release lease is held; re-probe before resume',
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
export async function runCli(argv) {
|
|
582
|
+
const args = parseArgs(argv)
|
|
583
|
+
if (args.help) {
|
|
584
|
+
console.log(help())
|
|
585
|
+
return 0
|
|
586
|
+
}
|
|
587
|
+
// Fail closed on any unknown flag BEFORE fetchTip/classification — a mistyped
|
|
588
|
+
// --gate / --classify-config must never silently skip the required-gate check
|
|
589
|
+
// or fall back to the default allowlist (exit 2 usage contract).
|
|
590
|
+
if (args.unknown) {
|
|
591
|
+
console.error(`ensure-target-green: unknown flag ${args.unknown} (see --help)`)
|
|
592
|
+
return 2
|
|
593
|
+
}
|
|
594
|
+
if (!args.repo || !args.targetBranch) {
|
|
595
|
+
console.error(help())
|
|
596
|
+
return 2
|
|
597
|
+
}
|
|
598
|
+
if (!isValidRepo(args.repo)) {
|
|
599
|
+
console.error(`ensure-target-green: invalid --repo ${args.repo}; expected owner/name`)
|
|
600
|
+
return 2
|
|
601
|
+
}
|
|
602
|
+
if (args.mode && !Object.values(MODES).includes(args.mode)) {
|
|
603
|
+
console.error(`unknown --mode ${args.mode}; expected ${Object.values(MODES).join('|')}`)
|
|
604
|
+
return 2
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const config = loadConfig(args.classifyConfig)
|
|
608
|
+
const tip = fetchTip({ repo: args.repo, targetBranch: args.targetBranch })
|
|
609
|
+
|
|
610
|
+
if (args.dryClassify) {
|
|
611
|
+
const failing = tip.readable
|
|
612
|
+
? classifyFailures({ checks: tip.checks, gates: args.gates, config })
|
|
613
|
+
: []
|
|
614
|
+
const out = {
|
|
615
|
+
state: !tip.readable ? STATES.UNKNOWN : failing.length === 0 ? STATES.GREEN : STATES.BLOCKED,
|
|
616
|
+
headSha: tip.headSha,
|
|
617
|
+
failing,
|
|
618
|
+
}
|
|
619
|
+
console.log(JSON.stringify(out, null, 2))
|
|
620
|
+
return out.state === STATES.GREEN ? 0 : 1
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// Live CLI: supervised by default — classify + brief. Auto-repair opens a structured
|
|
624
|
+
// handoff but does not itself wait for land (the release agent holds the lease and
|
|
625
|
+
// re-invokes after repair lands, or supplies injectable seams when embedding).
|
|
626
|
+
const result = await ensureTargetGreen({
|
|
627
|
+
headSha: tip.headSha,
|
|
628
|
+
checks: tip.checks,
|
|
629
|
+
readable: tip.readable,
|
|
630
|
+
gates: args.gates,
|
|
631
|
+
config,
|
|
632
|
+
mode: args.mode,
|
|
633
|
+
maxRepairRounds: args.maxRepairRounds,
|
|
634
|
+
wallClockMinutes: args.wallClockMinutes,
|
|
635
|
+
openRepair: defaultOpenRepair,
|
|
636
|
+
reProbe: async () => fetchTip({ repo: args.repo, targetBranch: args.targetBranch }),
|
|
637
|
+
})
|
|
638
|
+
|
|
639
|
+
if (args.json) console.log(JSON.stringify(result, null, 2))
|
|
640
|
+
else {
|
|
641
|
+
console.log(`state=${result.state} head=${result.headSha || '(unknown)'}`)
|
|
642
|
+
if (result.failing?.length) {
|
|
643
|
+
for (const f of result.failing) {
|
|
644
|
+
console.log(` failing: ${f.name}=${f.conclusion} class=${f.class} allowlisted=${f.allowlisted}`)
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
if (result.brief) console.log(` brief: ${result.brief.reason} — ${result.brief.detail || ''}`)
|
|
648
|
+
if (result.repair) console.log(` repair: strategy=${result.repair.strategy || 'resolve-issues'}`)
|
|
649
|
+
if (result.reprobe) console.log(` reprobe: required=${result.reprobe.required !== false}`)
|
|
650
|
+
console.log(` durationMs=${result.durationMs}`)
|
|
651
|
+
}
|
|
652
|
+
return result.state === STATES.GREEN ? 0 : 1
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
if (isMainModule(import.meta.url)) {
|
|
656
|
+
runCli(process.argv.slice(2)).then((code) => {
|
|
657
|
+
process.exitCode = code
|
|
658
|
+
})
|
|
659
|
+
}
|