@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,415 @@
|
|
|
1
|
+
import { execFileSync, spawnSync } from 'node:child_process'
|
|
2
|
+
|
|
3
|
+
const SHA_RE = /^[0-9a-f]{7,64}$/i
|
|
4
|
+
const isObject = (value) => value != null && typeof value === 'object' && !Array.isArray(value)
|
|
5
|
+
const nonEmpty = (value) => typeof value === 'string' && value.trim().length > 0
|
|
6
|
+
const clone = (value) => structuredClone(value)
|
|
7
|
+
const same = (left, right) => JSON.stringify(left) === JSON.stringify(right)
|
|
8
|
+
const refNumber = (value) => {
|
|
9
|
+
if (Number.isInteger(value) && value > 0) return value
|
|
10
|
+
const match = String(value ?? '').match(/(?:^|#)(\d+)$/)
|
|
11
|
+
return match ? Number(match[1]) : null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const COMPONENT_OUTCOMES = new Set([
|
|
15
|
+
'component-merged',
|
|
16
|
+
'component-unreadable',
|
|
17
|
+
'component-not-merged',
|
|
18
|
+
'component-merge-sha-mismatch',
|
|
19
|
+
])
|
|
20
|
+
const UNIT_OUTCOMES = new Set([
|
|
21
|
+
'closed-superseded',
|
|
22
|
+
'already-closed',
|
|
23
|
+
'already-merged',
|
|
24
|
+
'head-drift',
|
|
25
|
+
'not-contained',
|
|
26
|
+
'unit-unreadable',
|
|
27
|
+
'ancestry-unreadable',
|
|
28
|
+
'preclose-unreadable',
|
|
29
|
+
'preclose-head-drift',
|
|
30
|
+
'preclose-not-open',
|
|
31
|
+
'close-failed',
|
|
32
|
+
'blocked-component',
|
|
33
|
+
])
|
|
34
|
+
const TERMINAL_UNIT_OUTCOMES = new Set(['closed-superseded', 'already-closed', 'already-merged'])
|
|
35
|
+
const FAILED_UNIT_OUTCOMES = new Set([
|
|
36
|
+
'head-drift',
|
|
37
|
+
'not-contained',
|
|
38
|
+
'unit-unreadable',
|
|
39
|
+
'ancestry-unreadable',
|
|
40
|
+
'preclose-unreadable',
|
|
41
|
+
'preclose-head-drift',
|
|
42
|
+
'preclose-not-open',
|
|
43
|
+
'close-failed',
|
|
44
|
+
'blocked-component',
|
|
45
|
+
])
|
|
46
|
+
|
|
47
|
+
function normalizedPr(kind, requestedNumber, live) {
|
|
48
|
+
if (!isObject(live)) throw new Error(`${kind} #${requestedNumber} returned no structured observation`)
|
|
49
|
+
if (!Number.isInteger(live.number) || live.number <= 0) throw new Error(`${kind} #${requestedNumber} returned missing or malformed numeric identity`)
|
|
50
|
+
if (live.number !== requestedNumber) throw new Error(`${kind} #${requestedNumber} returned identity ${live.number}`)
|
|
51
|
+
if (!nonEmpty(live.state)) throw new Error(`${kind} #${requestedNumber} returned no state`)
|
|
52
|
+
return { ...clone(live), number: requestedNumber }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function candidateUnitEvidence(component, generation) {
|
|
56
|
+
const candidate = component?.candidate
|
|
57
|
+
if (!isObject(candidate) || candidate.generation !== generation || candidate.frozen?.generation !== generation) {
|
|
58
|
+
throw new Error(`component ${component?.id ?? '(unknown)'} has no frozen candidate evidence for delivered generation ${generation}`)
|
|
59
|
+
}
|
|
60
|
+
if (!Array.isArray(candidate.frozen.unitEvidence)) {
|
|
61
|
+
throw new Error(`component ${component.id} frozen unitEvidence is missing`)
|
|
62
|
+
}
|
|
63
|
+
return candidate.frozen.unitEvidence
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function reconciliationTargets(manifest) {
|
|
67
|
+
if (manifest?.finalization !== undefined) throw new Error('contained unit PR reconciliation is pre-finalization only')
|
|
68
|
+
if (!nonEmpty(manifest?.repository)) throw new Error('repository is required for contained unit PR reconciliation')
|
|
69
|
+
if (!nonEmpty(manifest?.targetBranch)) throw new Error('targetBranch is required for contained unit PR reconciliation')
|
|
70
|
+
const units = Array.isArray(manifest?.units) ? manifest.units : []
|
|
71
|
+
const byId = new Map(units.map((unit) => [unit?.id, unit]))
|
|
72
|
+
const targets = []
|
|
73
|
+
|
|
74
|
+
for (const component of Array.isArray(manifest?.components) ? manifest.components : []) {
|
|
75
|
+
const delivery = component?.delivery
|
|
76
|
+
if (!isObject(delivery) || delivery.outcome !== 'merged') continue
|
|
77
|
+
const componentPr = refNumber(delivery.pr)
|
|
78
|
+
const publishedPr = refNumber(component.pr)
|
|
79
|
+
if (componentPr == null || publishedPr !== componentPr) {
|
|
80
|
+
throw new Error(`component ${component?.id ?? '(unknown)'} has no unambiguous published combined PR`)
|
|
81
|
+
}
|
|
82
|
+
if (!Number.isSafeInteger(delivery.generation) || delivery.generation < 1 || !SHA_RE.test(delivery.mergedSha ?? '')) {
|
|
83
|
+
throw new Error(`component ${component.id} has malformed delivered generation or merge SHA`)
|
|
84
|
+
}
|
|
85
|
+
const evidence = candidateUnitEvidence(component, delivery.generation)
|
|
86
|
+
const evidenceById = new Map(evidence.map((entry) => [entry?.unitId, entry]))
|
|
87
|
+
const linkedUnits = []
|
|
88
|
+
for (const unitId of Array.isArray(component.units) ? component.units : []) {
|
|
89
|
+
const unit = byId.get(unitId)
|
|
90
|
+
if (!unit || !same(unit.deliveryRef, { componentId: component.id, generation: delivery.generation })) continue
|
|
91
|
+
const unitPr = refNumber(unit.pr)
|
|
92
|
+
if (unitPr == null || unitPr === componentPr) continue
|
|
93
|
+
const reviewed = evidenceById.get(unitId)
|
|
94
|
+
if (!isObject(reviewed) || refNumber(reviewed.pr) !== unitPr) continue
|
|
95
|
+
if (!SHA_RE.test(reviewed.headSha ?? '') || reviewed.preliminaryReview?.verdict !== 'PASS'
|
|
96
|
+
|| reviewed.preliminaryReview?.headSha !== reviewed.headSha) {
|
|
97
|
+
throw new Error(`component ${component.id} unit ${unitId} has no exact reviewed unit head in publication evidence`)
|
|
98
|
+
}
|
|
99
|
+
linkedUnits.push({ unitId, pr: unitPr, reviewedHeadSha: reviewed.headSha })
|
|
100
|
+
}
|
|
101
|
+
if (linkedUnits.length) targets.push({ component, delivery, componentPr, linkedUnits })
|
|
102
|
+
}
|
|
103
|
+
return targets
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function supersessionComment({ componentPr, reviewedHeadSha, targetRef, mergedSha }) {
|
|
107
|
+
return `Closing this unit PR as superseded by combined PR #${componentPr}. The exact reviewed unit head ${reviewedHeadSha} is contained in freshly fetched ${targetRef}; the combined component merged as ${mergedSha}.`
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function componentRecord(target, fetchedTarget, at) {
|
|
111
|
+
return {
|
|
112
|
+
at,
|
|
113
|
+
target: {
|
|
114
|
+
branch: fetchedTarget.branch,
|
|
115
|
+
ref: fetchedTarget.ref,
|
|
116
|
+
headSha: fetchedTarget.headSha,
|
|
117
|
+
...(nonEmpty(fetchedTarget.fetchedAt) ? { fetchedAt: fetchedTarget.fetchedAt } : {}),
|
|
118
|
+
},
|
|
119
|
+
componentPr: target.componentPr,
|
|
120
|
+
generation: target.delivery.generation,
|
|
121
|
+
mergedSha: target.delivery.mergedSha,
|
|
122
|
+
component: null,
|
|
123
|
+
outcome: null,
|
|
124
|
+
units: target.linkedUnits.map((unit) => ({
|
|
125
|
+
...unit,
|
|
126
|
+
live: null,
|
|
127
|
+
headMatches: null,
|
|
128
|
+
ancestry: null,
|
|
129
|
+
outcome: 'blocked-component',
|
|
130
|
+
})),
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export async function reconcileContainedUnitPrs(manifest, boundary) {
|
|
135
|
+
const out = clone(manifest)
|
|
136
|
+
const targets = reconciliationTargets(out)
|
|
137
|
+
let fetchedTarget
|
|
138
|
+
try {
|
|
139
|
+
fetchedTarget = await boundary.fetchTarget(out.targetBranch)
|
|
140
|
+
} catch (error) {
|
|
141
|
+
return { ok: false, errors: [`fresh target fetch failed: ${error.message ?? error}`], manifest: out, target: null, reconciliations: [] }
|
|
142
|
+
}
|
|
143
|
+
if (!isObject(fetchedTarget) || fetchedTarget.branch !== out.targetBranch || !nonEmpty(fetchedTarget.ref) || !nonEmpty(fetchedTarget.headSha)) {
|
|
144
|
+
return { ok: false, errors: ['fresh target fetch returned no matching branch/ref/head SHA'], manifest: out, target: fetchedTarget ?? null, reconciliations: [] }
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const at = boundary.now()
|
|
148
|
+
const records = targets.map((target) => componentRecord(target, fetchedTarget, at))
|
|
149
|
+
const errors = []
|
|
150
|
+
|
|
151
|
+
// Phase one observes every component and unit head before any outward mutation.
|
|
152
|
+
for (let index = 0; index < targets.length; index++) {
|
|
153
|
+
const target = targets[index]
|
|
154
|
+
const record = records[index]
|
|
155
|
+
try {
|
|
156
|
+
record.component = normalizedPr('component PR', target.componentPr, await boundary.readPr(target.componentPr, out.repository))
|
|
157
|
+
} catch (error) {
|
|
158
|
+
record.outcome = 'component-unreadable'
|
|
159
|
+
errors.push(`component ${target.component.id} PR #${target.componentPr} could not be verified live: ${error.message ?? error}`)
|
|
160
|
+
continue
|
|
161
|
+
}
|
|
162
|
+
if (record.component.state !== 'MERGED' || record.component.merged !== true) {
|
|
163
|
+
record.outcome = 'component-not-merged'
|
|
164
|
+
errors.push(`component ${target.component.id} PR #${target.componentPr} is not live-verified merged`)
|
|
165
|
+
continue
|
|
166
|
+
}
|
|
167
|
+
if (record.component.mergeCommitSha !== target.delivery.mergedSha) {
|
|
168
|
+
record.outcome = 'component-merge-sha-mismatch'
|
|
169
|
+
errors.push(`component ${target.component.id} PR #${target.componentPr} merge SHA is ${record.component.mergeCommitSha ?? 'missing'}, expected ${target.delivery.mergedSha}`)
|
|
170
|
+
continue
|
|
171
|
+
}
|
|
172
|
+
record.outcome = 'component-merged'
|
|
173
|
+
|
|
174
|
+
for (const unit of record.units) {
|
|
175
|
+
try {
|
|
176
|
+
unit.live = normalizedPr('unit PR', unit.pr, await boundary.readPr(unit.pr, out.repository))
|
|
177
|
+
} catch (error) {
|
|
178
|
+
unit.outcome = 'unit-unreadable'
|
|
179
|
+
unit.error = error.message ?? String(error)
|
|
180
|
+
errors.push(`unit ${unit.unitId} PR #${unit.pr} could not be verified live: ${unit.error}`)
|
|
181
|
+
continue
|
|
182
|
+
}
|
|
183
|
+
unit.headMatches = unit.live.headSha === unit.reviewedHeadSha
|
|
184
|
+
if (unit.live.state === 'MERGED' || unit.live.merged === true) {
|
|
185
|
+
unit.outcome = 'already-merged'
|
|
186
|
+
continue
|
|
187
|
+
}
|
|
188
|
+
if (unit.live.state === 'CLOSED') {
|
|
189
|
+
unit.outcome = 'already-closed'
|
|
190
|
+
continue
|
|
191
|
+
}
|
|
192
|
+
if (unit.live.state !== 'OPEN') {
|
|
193
|
+
unit.outcome = 'unit-unreadable'
|
|
194
|
+
unit.error = `unsupported live state ${unit.live.state}`
|
|
195
|
+
errors.push(`unit ${unit.unitId} PR #${unit.pr} returned ${unit.error}`)
|
|
196
|
+
continue
|
|
197
|
+
}
|
|
198
|
+
if (!unit.headMatches) {
|
|
199
|
+
unit.outcome = 'head-drift'
|
|
200
|
+
errors.push(`unit ${unit.unitId} PR #${unit.pr} head ${unit.live.headSha ?? 'missing'} does not equal reviewed head ${unit.reviewedHeadSha}`)
|
|
201
|
+
continue
|
|
202
|
+
}
|
|
203
|
+
let contained
|
|
204
|
+
try {
|
|
205
|
+
contained = await boundary.isAncestor(unit.reviewedHeadSha, fetchedTarget.ref)
|
|
206
|
+
} catch (error) {
|
|
207
|
+
unit.outcome = 'ancestry-unreadable'
|
|
208
|
+
unit.error = error.message ?? String(error)
|
|
209
|
+
errors.push(`unit ${unit.unitId} ancestry could not be verified: ${unit.error}`)
|
|
210
|
+
continue
|
|
211
|
+
}
|
|
212
|
+
unit.ancestry = { targetRef: fetchedTarget.ref, contained: contained === true }
|
|
213
|
+
if (contained !== true) {
|
|
214
|
+
unit.outcome = 'not-contained'
|
|
215
|
+
errors.push(`unit ${unit.unitId} reviewed head ${unit.reviewedHeadSha} is not an ancestor of freshly fetched ${fetchedTarget.ref}`)
|
|
216
|
+
continue
|
|
217
|
+
}
|
|
218
|
+
unit.outcome = 'pending-close'
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Phase two re-reads each eligible head immediately before the close mutation.
|
|
223
|
+
for (let index = 0; index < targets.length; index++) {
|
|
224
|
+
const target = targets[index]
|
|
225
|
+
const record = records[index]
|
|
226
|
+
if (record.outcome !== 'component-merged') continue
|
|
227
|
+
for (const unit of record.units.filter((entry) => entry.outcome === 'pending-close')) {
|
|
228
|
+
let preclose
|
|
229
|
+
try {
|
|
230
|
+
preclose = normalizedPr('unit PR', unit.pr, await boundary.readPr(unit.pr, out.repository))
|
|
231
|
+
} catch (error) {
|
|
232
|
+
unit.outcome = 'preclose-unreadable'
|
|
233
|
+
unit.error = error.message ?? String(error)
|
|
234
|
+
errors.push(`unit ${unit.unitId} PR #${unit.pr} pre-close read failed: ${unit.error}`)
|
|
235
|
+
continue
|
|
236
|
+
}
|
|
237
|
+
if (preclose.headSha !== unit.reviewedHeadSha) {
|
|
238
|
+
unit.outcome = 'preclose-head-drift'
|
|
239
|
+
unit.live = preclose
|
|
240
|
+
unit.headMatches = false
|
|
241
|
+
errors.push(`unit ${unit.unitId} PR #${unit.pr} moved to ${preclose.headSha ?? 'missing'} before close`)
|
|
242
|
+
continue
|
|
243
|
+
}
|
|
244
|
+
if (preclose.state !== 'OPEN' || preclose.merged === true) {
|
|
245
|
+
unit.outcome = preclose.state === 'MERGED' || preclose.merged === true ? 'already-merged' : preclose.state === 'CLOSED' ? 'already-closed' : 'preclose-not-open'
|
|
246
|
+
unit.live = preclose
|
|
247
|
+
if (unit.outcome === 'preclose-not-open') errors.push(`unit ${unit.unitId} PR #${unit.pr} is ${preclose.state}, not OPEN, before close`)
|
|
248
|
+
continue
|
|
249
|
+
}
|
|
250
|
+
unit.comment = supersessionComment({
|
|
251
|
+
componentPr: target.componentPr,
|
|
252
|
+
reviewedHeadSha: unit.reviewedHeadSha,
|
|
253
|
+
targetRef: fetchedTarget.ref,
|
|
254
|
+
mergedSha: target.delivery.mergedSha,
|
|
255
|
+
})
|
|
256
|
+
try {
|
|
257
|
+
const closed = normalizedPr('closed unit PR', unit.pr, await boundary.closePr(unit.pr, out.repository, unit.comment))
|
|
258
|
+
if (!['CLOSED', 'MERGED'].includes(closed.state)) throw new Error(`close returned state ${closed.state}`)
|
|
259
|
+
unit.live = closed
|
|
260
|
+
unit.outcome = closed.state === 'MERGED' || closed.merged === true ? 'already-merged' : 'closed-superseded'
|
|
261
|
+
} catch (error) {
|
|
262
|
+
unit.outcome = 'close-failed'
|
|
263
|
+
unit.error = error.message ?? String(error)
|
|
264
|
+
errors.push(`unit ${unit.unitId} PR #${unit.pr} close failed: ${unit.error}`)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
for (let index = 0; index < targets.length; index++) {
|
|
270
|
+
const delivery = targets[index].component.delivery
|
|
271
|
+
delivery.reconciliations = [...(Array.isArray(delivery.reconciliations) ? delivery.reconciliations : []), records[index]]
|
|
272
|
+
}
|
|
273
|
+
const recordErrors = reconciliationErrors(out)
|
|
274
|
+
if (recordErrors.length) throw new Error(`invalid reconciliation result: ${recordErrors[0]}`)
|
|
275
|
+
return {
|
|
276
|
+
ok: errors.length === 0 && records.every((record) => record.outcome === 'component-merged'
|
|
277
|
+
&& record.units.every((unit) => !FAILED_UNIT_OUTCOMES.has(unit.outcome))),
|
|
278
|
+
errors,
|
|
279
|
+
manifest: out,
|
|
280
|
+
target: fetchedTarget,
|
|
281
|
+
reconciliations: records,
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export function unitPrReconciliationStatus(manifest) {
|
|
286
|
+
let targets
|
|
287
|
+
try {
|
|
288
|
+
targets = reconciliationTargets(manifest)
|
|
289
|
+
} catch (error) {
|
|
290
|
+
return { state: 'invalid', required: true, complete: false, reason: error.message ?? String(error), components: [] }
|
|
291
|
+
}
|
|
292
|
+
if (!targets.length) return { state: 'not-required', required: false, complete: true, reason: 'no delivered combined component has explicitly published, distinct unit PRs', components: [] }
|
|
293
|
+
const components = targets.map((target) => {
|
|
294
|
+
const latest = Array.isArray(target.delivery.reconciliations) ? target.delivery.reconciliations.at(-1) : null
|
|
295
|
+
const observed = new Map((Array.isArray(latest?.units) ? latest.units : []).map((unit) => [unit?.unitId, unit]))
|
|
296
|
+
const pendingUnits = target.linkedUnits
|
|
297
|
+
.filter((unit) => !TERMINAL_UNIT_OUTCOMES.has(observed.get(unit.unitId)?.outcome))
|
|
298
|
+
.map((unit) => unit.unitId)
|
|
299
|
+
return { componentId: target.component.id, componentPr: target.componentPr, pendingUnits, complete: pendingUnits.length === 0 }
|
|
300
|
+
})
|
|
301
|
+
const complete = components.every((component) => component.complete)
|
|
302
|
+
return {
|
|
303
|
+
state: complete ? 'complete' : 'required',
|
|
304
|
+
required: true,
|
|
305
|
+
complete,
|
|
306
|
+
reason: complete ? 'all linked unit PRs have terminal live observations' : 'delivered combined components still have unreconciled unit PRs',
|
|
307
|
+
components,
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export function reconciliationErrors(manifest) {
|
|
312
|
+
const errors = []
|
|
313
|
+
const units = new Map((Array.isArray(manifest?.units) ? manifest.units : []).map((unit) => [unit?.id, unit]))
|
|
314
|
+
for (const [componentIndex, component] of (Array.isArray(manifest?.components) ? manifest.components : []).entries()) {
|
|
315
|
+
const reconciliations = component?.delivery?.reconciliations
|
|
316
|
+
if (reconciliations === undefined) continue
|
|
317
|
+
const label = `components[${componentIndex}] (${component?.id ?? 'unknown'}).delivery.reconciliations`
|
|
318
|
+
if (!Array.isArray(reconciliations)) { errors.push(`${label} must be an array`); continue }
|
|
319
|
+
for (const [recordIndex, record] of reconciliations.entries()) {
|
|
320
|
+
const at = `${label}[${recordIndex}]`
|
|
321
|
+
if (!isObject(record)) { errors.push(`${at} must be an object`); continue }
|
|
322
|
+
const unknown = Object.keys(record).filter((key) => !['at', 'target', 'componentPr', 'generation', 'mergedSha', 'component', 'outcome', 'units'].includes(key))
|
|
323
|
+
if (unknown.length) errors.push(`${at} has unknown property ${unknown[0]}`)
|
|
324
|
+
if (!nonEmpty(record.at) || !nonEmpty(record.target?.ref) || !SHA_RE.test(record.target?.headSha ?? '')) errors.push(`${at} requires timestamp and fresh target ref/head`)
|
|
325
|
+
if (record.target?.branch !== manifest.targetBranch || record.target?.ref !== `origin/${manifest.targetBranch}`) errors.push(`${at}.target must equal the freshly fetched origin targetBranch`)
|
|
326
|
+
if (record.componentPr !== refNumber(component.delivery?.pr) || record.generation !== component.delivery?.generation || record.mergedSha !== component.delivery?.mergedSha) {
|
|
327
|
+
errors.push(`${at} must bind the canonical component delivery PR, generation, and merge SHA`)
|
|
328
|
+
}
|
|
329
|
+
if (!COMPONENT_OUTCOMES.has(record.outcome)) errors.push(`${at}.outcome is invalid`)
|
|
330
|
+
if (record.component != null && record.component.number !== record.componentPr) errors.push(`${at}.component identity is stale`)
|
|
331
|
+
if (record.outcome === 'component-merged'
|
|
332
|
+
&& (record.component?.state !== 'MERGED' || record.component?.merged !== true || record.component?.mergeCommitSha !== record.mergedSha)) {
|
|
333
|
+
errors.push(`${at}.component does not prove the recorded merged outcome at the canonical merge SHA`)
|
|
334
|
+
}
|
|
335
|
+
if (!Array.isArray(record.units)) { errors.push(`${at}.units must be an array`); continue }
|
|
336
|
+
const publishedEvidence = new Map((Array.isArray(component.candidate?.frozen?.unitEvidence) ? component.candidate.frozen.unitEvidence : [])
|
|
337
|
+
.map((entry) => [entry?.unitId, entry]))
|
|
338
|
+
const seen = new Set()
|
|
339
|
+
for (const [unitIndex, row] of record.units.entries()) {
|
|
340
|
+
const unitAt = `${at}.units[${unitIndex}]`
|
|
341
|
+
if (!isObject(row)) { errors.push(`${unitAt} must be an object`); continue }
|
|
342
|
+
const unknownUnit = Object.keys(row).filter((key) => !['unitId', 'pr', 'reviewedHeadSha', 'live', 'headMatches', 'ancestry', 'outcome', 'comment', 'error'].includes(key))
|
|
343
|
+
if (unknownUnit.length) errors.push(`${unitAt} has unknown property ${unknownUnit[0]}`)
|
|
344
|
+
if (!nonEmpty(row.unitId) || seen.has(row.unitId)) errors.push(`${unitAt}.unitId must be non-empty and unique`)
|
|
345
|
+
seen.add(row.unitId)
|
|
346
|
+
if (!UNIT_OUTCOMES.has(row.outcome)) errors.push(`${unitAt}.outcome is invalid`)
|
|
347
|
+
if (!SHA_RE.test(row.reviewedHeadSha ?? '') || refNumber(row.pr) == null) errors.push(`${unitAt} requires unit PR and reviewed head`)
|
|
348
|
+
const unit = units.get(row.unitId)
|
|
349
|
+
if (!unit || !same(unit.deliveryRef, { componentId: component.id, generation: record.generation })) errors.push(`${unitAt} is not linked to this delivered component generation`)
|
|
350
|
+
const published = publishedEvidence.get(row.unitId)
|
|
351
|
+
if (!published || refNumber(published.pr) !== row.pr || published.headSha !== row.reviewedHeadSha
|
|
352
|
+
|| published.preliminaryReview?.verdict !== 'PASS' || published.preliminaryReview?.headSha !== row.reviewedHeadSha) {
|
|
353
|
+
errors.push(`${unitAt} does not match the component's exact published reviewed-unit evidence`)
|
|
354
|
+
}
|
|
355
|
+
if (row.live != null && row.live.number !== row.pr) errors.push(`${unitAt}.live identity is stale`)
|
|
356
|
+
if (row.ancestry != null && (row.ancestry.targetRef !== record.target?.ref || typeof row.ancestry.contained !== 'boolean')) errors.push(`${unitAt}.ancestry is stale`)
|
|
357
|
+
if (row.outcome === 'closed-superseded'
|
|
358
|
+
&& (row.live?.state !== 'CLOSED' || row.headMatches !== true || row.ancestry?.contained !== true)) {
|
|
359
|
+
errors.push(`${unitAt} closed-superseded outcome lacks exact-head, ancestry, or terminal-state proof`)
|
|
360
|
+
}
|
|
361
|
+
if (row.outcome === 'already-closed' && row.live?.state !== 'CLOSED') errors.push(`${unitAt} already-closed outcome lacks CLOSED state`)
|
|
362
|
+
if (row.outcome === 'already-merged' && row.live?.state !== 'MERGED' && row.live?.merged !== true) errors.push(`${unitAt} already-merged outcome lacks MERGED state`)
|
|
363
|
+
if (row.outcome === 'head-drift' && row.headMatches !== false) errors.push(`${unitAt} head-drift outcome lacks a mismatched live head`)
|
|
364
|
+
if (row.outcome === 'not-contained' && row.ancestry?.contained !== false) errors.push(`${unitAt} not-contained outcome lacks negative fresh-target ancestry`)
|
|
365
|
+
if (row.outcome === 'closed-superseded') {
|
|
366
|
+
for (const expected of [`#${record.componentPr}`, row.reviewedHeadSha, record.target.ref, record.mergedSha]) {
|
|
367
|
+
if (!nonEmpty(row.comment) || !row.comment.includes(expected)) errors.push(`${unitAt}.comment must name combined PR, reviewed head, target ref, and merge SHA`)
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return errors
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function runJson(command, args, cwd) {
|
|
377
|
+
return JSON.parse(execFileSync(command, args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }))
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export function createLiveReconciliationBoundary({ cwd = process.cwd(), now = () => new Date().toISOString() } = {}) {
|
|
381
|
+
const readPr = async (id, repository) => {
|
|
382
|
+
if (!Number.isInteger(id) || !nonEmpty(repository)) throw new Error('PR number and repository are required')
|
|
383
|
+
const view = runJson('gh', ['pr', 'view', String(id), '--repo', repository, '--json', 'number,state,mergedAt,mergeCommit,url,headRefOid'], cwd)
|
|
384
|
+
return {
|
|
385
|
+
number: view.number,
|
|
386
|
+
state: view.state,
|
|
387
|
+
merged: view.state === 'MERGED' || nonEmpty(view.mergedAt),
|
|
388
|
+
mergedAt: view.mergedAt ?? null,
|
|
389
|
+
mergeCommitSha: view.mergeCommit?.oid ?? null,
|
|
390
|
+
headSha: view.headRefOid ?? null,
|
|
391
|
+
url: view.url,
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return {
|
|
395
|
+
now,
|
|
396
|
+
fetchTarget: async (branch) => {
|
|
397
|
+
if (!nonEmpty(branch)) throw new Error('targetBranch is not recorded')
|
|
398
|
+
execFileSync('git', ['fetch', 'origin', branch], { cwd, stdio: ['ignore', 'ignore', 'pipe'] })
|
|
399
|
+
const ref = `origin/${branch}`
|
|
400
|
+
const headSha = execFileSync('git', ['rev-parse', ref], { cwd, encoding: 'utf8' }).trim()
|
|
401
|
+
return { remote: 'origin', branch, ref, headSha, fetchedAt: now() }
|
|
402
|
+
},
|
|
403
|
+
isAncestor: async (headSha, ref) => {
|
|
404
|
+
const result = spawnSync('git', ['merge-base', '--is-ancestor', headSha, ref], { cwd, encoding: 'utf8' })
|
|
405
|
+
if (result.status === 0) return true
|
|
406
|
+
if (result.status === 1) return false
|
|
407
|
+
throw new Error(result.stderr?.trim() || `git merge-base --is-ancestor exited ${result.status ?? 'without status'}`)
|
|
408
|
+
},
|
|
409
|
+
readPr,
|
|
410
|
+
closePr: async (id, repository, comment) => {
|
|
411
|
+
execFileSync('gh', ['pr', 'close', String(id), '--repo', repository, '--comment', comment], { cwd, stdio: ['ignore', 'ignore', 'pipe'] })
|
|
412
|
+
return readPr(id, repository)
|
|
413
|
+
},
|
|
414
|
+
}
|
|
415
|
+
}
|