@1aboveio/skills 0.19.3 → 0.20.2

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.
Files changed (206) hide show
  1. package/README.md +9 -4
  2. package/package.json +1 -1
  3. package/runtime/skills/distribution/generated/recipes.json +54 -48
  4. package/runtime/skills/distribution/scripts/bundles.mjs +113 -7
  5. package/runtime/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -6
  6. package/runtime/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +3 -36
  7. package/skills/cicd-pipeline/cloud-build/SKILL.md +6 -6
  8. package/skills/cicd-pipeline/mergify/SKILL.md +1 -1
  9. package/skills/engineering/engineering-runtime/coherence/workflow.json +15 -84
  10. package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -6
  11. package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +3 -36
  12. package/skills/engineering/rush-release/SKILL.md +46 -25
  13. package/skills/engineering/rush-release/evals/evals.json +22 -8
  14. package/skills/engineering/rush-release/references/cut.md +21 -4
  15. package/skills/engineering/rush-release/references/preflight.md +25 -6
  16. package/skills/engineering/rush-release/references/promotion.md +70 -0
  17. package/skills/engineering/rush-release/references/publish.md +49 -16
  18. package/skills/engineering/rush-release/scripts/plan.mjs +33 -7
  19. package/skills/engineering/smoke/SKILL.md +4 -4
  20. package/skills/engineering/smoke/references/manifest.md +3 -3
  21. package/skills/payment/payment-analysis/SKILL.md +5 -3
  22. package/skills/payment/tld-detection/SKILL.md +163 -0
  23. package/skills/payment/tld-detection/agents/openai.yaml +9 -0
  24. package/skills/payment/tld-detection/evals/evals.json +107 -0
  25. package/skills/payment/tld-detection/references/clean.md +51 -0
  26. package/skills/payment/tld-detection/references/clustering.md +219 -0
  27. package/skills/payment/tld-detection/references/decision.md +85 -0
  28. package/skills/payment/tld-detection/references/report-template.md +169 -0
  29. package/skills/payment/tld-detection/references/terminology.md +69 -0
  30. package/skills/payment/tld-detection/references/workflow.md +78 -0
  31. package/skills/payment/tld-detection/scripts/detect_ladders.py +390 -0
  32. package/skills/payment/tld-detection/tests/test_detect_ladders.py +132 -0
  33. package/skills/engineering/resolve-issues/SKILL.md +0 -168
  34. package/skills/engineering/resolve-issues/agents/openai.yaml +0 -9
  35. package/skills/engineering/resolve-issues/generated/workflow-repair-policy.json +0 -499
  36. package/skills/engineering/resolve-issues/references/breaker.md +0 -82
  37. package/skills/engineering/resolve-issues/references/deliverables.md +0 -27
  38. package/skills/engineering/resolve-issues/references/delivery.md +0 -108
  39. package/skills/engineering/resolve-issues/references/evidence-lane.md +0 -21
  40. package/skills/engineering/resolve-issues/references/exact-head-ci.md +0 -287
  41. package/skills/engineering/resolve-issues/references/fan-out.md +0 -33
  42. package/skills/engineering/resolve-issues/references/finalization.md +0 -68
  43. package/skills/engineering/resolve-issues/references/guarantees.md +0 -10
  44. package/skills/engineering/resolve-issues/references/high-risk.md +0 -29
  45. package/skills/engineering/resolve-issues/references/incidents/848/README.md +0 -156
  46. package/skills/engineering/resolve-issues/references/intake.md +0 -86
  47. package/skills/engineering/resolve-issues/references/integration-gate.md +0 -53
  48. package/skills/engineering/resolve-issues/references/interference.md +0 -87
  49. package/skills/engineering/resolve-issues/references/loop.md +0 -134
  50. package/skills/engineering/resolve-issues/references/model-catalog.md +0 -9
  51. package/skills/engineering/resolve-issues/references/postmortem.md +0 -27
  52. package/skills/engineering/resolve-issues/references/pre-flight-model-slots.md +0 -41
  53. package/skills/engineering/resolve-issues/references/pre-flight-recording-and-checkout.md +0 -48
  54. package/skills/engineering/resolve-issues/references/pre-flight.md +0 -41
  55. package/skills/engineering/resolve-issues/references/regression-checklist.md +0 -26
  56. package/skills/engineering/resolve-issues/references/run-state.md +0 -288
  57. package/skills/engineering/resolve-issues/references/sandboxed-testing.md +0 -48
  58. package/skills/engineering/resolve-issues/references/spawn-contract.md +0 -96
  59. package/skills/engineering/resolve-issues/references/terminal-evidence-journal.md +0 -40
  60. package/skills/engineering/resolve-issues/references/why.md +0 -653
  61. package/skills/engineering/resolve-issues/schemas/fix-round.schema.json +0 -49
  62. package/skills/engineering/resolve-issues/scripts/combine-and-verify.mjs +0 -721
  63. package/skills/engineering/resolve-issues/scripts/component-candidate.mjs +0 -962
  64. package/skills/engineering/resolve-issues/scripts/contract-revision.mjs +0 -220
  65. package/skills/engineering/resolve-issues/scripts/detect-delivery-mode.mjs +0 -420
  66. package/skills/engineering/resolve-issues/scripts/detect-target-branch.mjs +0 -256
  67. package/skills/engineering/resolve-issues/scripts/detect-workspace-mode.mjs +0 -168
  68. package/skills/engineering/resolve-issues/scripts/discover-models.mjs +0 -9
  69. package/skills/engineering/resolve-issues/scripts/doctrine.mjs +0 -62
  70. package/skills/engineering/resolve-issues/scripts/evidence-lifecycle-contract.mjs +0 -191
  71. package/skills/engineering/resolve-issues/scripts/exact-head-ci.mjs +0 -413
  72. package/skills/engineering/resolve-issues/scripts/exact-head-github-provider.mjs +0 -332
  73. package/skills/engineering/resolve-issues/scripts/finalize.mjs +0 -488
  74. package/skills/engineering/resolve-issues/scripts/fix-rounds.mjs +0 -3307
  75. package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-circular-1001.json +0 -16
  76. package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-valid-sequencing.json +0 -51
  77. package/skills/engineering/resolve-issues/scripts/fixtures/fmm-express-830-component-candidate.json +0 -17
  78. package/skills/engineering/resolve-issues/scripts/fixtures/head-check-set-1081.json +0 -166
  79. package/skills/engineering/resolve-issues/scripts/gate-value-series.mjs +0 -92
  80. package/skills/engineering/resolve-issues/scripts/guide-index.mjs +0 -73
  81. package/skills/engineering/resolve-issues/scripts/head-check-set.mjs +0 -159
  82. package/skills/engineering/resolve-issues/scripts/interference.mjs +0 -427
  83. package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +0 -9
  84. package/skills/engineering/resolve-issues/scripts/next-operations.mjs +0 -419
  85. package/skills/engineering/resolve-issues/scripts/postmortem.mjs +0 -909
  86. package/skills/engineering/resolve-issues/scripts/preflight-questions.mjs +0 -345
  87. package/skills/engineering/resolve-issues/scripts/reconcile-contained-unit-prs.mjs +0 -415
  88. package/skills/engineering/resolve-issues/scripts/release-state-contract.mjs +0 -697
  89. package/skills/engineering/resolve-issues/scripts/report.mjs +0 -494
  90. package/skills/engineering/resolve-issues/scripts/required-check-plan.mjs +0 -172
  91. package/skills/engineering/resolve-issues/scripts/round-metadata.mjs +0 -79
  92. package/skills/engineering/resolve-issues/scripts/run-state-review6-cases.mjs +0 -334
  93. package/skills/engineering/resolve-issues/scripts/run-state.mjs +0 -4792
  94. package/skills/engineering/resolve-issues/scripts/sandbox-selftest.mjs +0 -395
  95. package/skills/engineering/resolve-issues/scripts/spawn-contract.mjs +0 -290
  96. package/skills/engineering/resolve-issues/scripts/terminal-dispositions.mjs +0 -170
  97. package/skills/engineering/resolve-issues/scripts/terminal-evidence-journal.mjs +0 -293
  98. package/skills/engineering/resolve-issues/scripts/unit-kind.mjs +0 -197
  99. package/skills/engineering/resolve-issues/scripts/unit-lifecycle.mjs +0 -127
  100. package/skills/engineering/resolve-issues/scripts/watch-delivery.mjs +0 -893
  101. package/skills/engineering/resolve-issues/scripts/workspaces.mjs +0 -829
  102. package/skills/engineering/resolve-issues/workflows/independent-review.workflow.js +0 -290
  103. package/skills/engineering/resolve-issues/workflows/prior-art-scan.workflow.js +0 -80
  104. package/skills/engineering/resolve-issues/workflows/workflow-smoke.mjs +0 -102
  105. package/skills/engineering/resolve-release/LICENSE +0 -3
  106. package/skills/engineering/resolve-release/SKILL.md +0 -113
  107. package/skills/engineering/resolve-release/agents/openai.yaml +0 -9
  108. package/skills/engineering/resolve-release/references/assembly.md +0 -137
  109. package/skills/engineering/resolve-release/references/auto-when-green.md +0 -56
  110. package/skills/engineering/resolve-release/references/candidate.md +0 -167
  111. package/skills/engineering/resolve-release/references/exposure.md +0 -178
  112. package/skills/engineering/resolve-release/references/handoff.md +0 -24
  113. package/skills/engineering/resolve-release/references/postmortem.md +0 -230
  114. package/skills/engineering/resolve-release/references/preflight.md +0 -208
  115. package/skills/engineering/resolve-release/references/principles.md +0 -94
  116. package/skills/engineering/resolve-release/references/regression-checklist.md +0 -36
  117. package/skills/engineering/resolve-release/references/related-skills.md +0 -13
  118. package/skills/engineering/resolve-release/references/routing.md +0 -149
  119. package/skills/engineering/resolve-release/references/verified-sha-github-flow.md +0 -285
  120. package/skills/engineering/resolve-release/references/versioning.md +0 -202
  121. package/skills/engineering/resolve-release/references/why.md +0 -53
  122. package/skills/engineering/resolve-release/scripts/adapter-completion-artifact.mjs +0 -389
  123. package/skills/engineering/resolve-release/scripts/build-changes.mjs +0 -209
  124. package/skills/engineering/resolve-release/scripts/candidate-hygiene.mjs +0 -407
  125. package/skills/engineering/resolve-release/scripts/candidate-identity.mjs +0 -904
  126. package/skills/engineering/resolve-release/scripts/candidate-traffic.mjs +0 -81
  127. package/skills/engineering/resolve-release/scripts/checked-adapter-loader.mjs +0 -612
  128. package/skills/engineering/resolve-release/scripts/close-attempt.mjs +0 -135
  129. package/skills/engineering/resolve-release/scripts/closeout-release.mjs +0 -161
  130. package/skills/engineering/resolve-release/scripts/doctrine.mjs +0 -106
  131. package/skills/engineering/resolve-release/scripts/durable-processing.mjs +0 -522
  132. package/skills/engineering/resolve-release/scripts/ensure-target-green.mjs +0 -659
  133. package/skills/engineering/resolve-release/scripts/evidence-bundle.mjs +0 -1014
  134. package/skills/engineering/resolve-release/scripts/finalize-release.mjs +0 -526
  135. package/skills/engineering/resolve-release/scripts/fixtures/durable-processing-adapter.mjs +0 -169
  136. package/skills/engineering/resolve-release/scripts/green-gate.mjs +0 -599
  137. package/skills/engineering/resolve-release/scripts/isolated-adapter-evaluator.mjs +0 -752
  138. package/skills/engineering/resolve-release/scripts/metadata-pr-status.mjs +0 -56
  139. package/skills/engineering/resolve-release/scripts/metadata-sync.mjs +0 -1538
  140. package/skills/engineering/resolve-release/scripts/postmortem.mjs +0 -381
  141. package/skills/engineering/resolve-release/scripts/preflight-probes.mjs +0 -510
  142. package/skills/engineering/resolve-release/scripts/production-endpoints.mjs +0 -326
  143. package/skills/engineering/resolve-release/scripts/rc-circuit-breaker.mjs +0 -272
  144. package/skills/engineering/resolve-release/scripts/report.mjs +0 -417
  145. package/skills/engineering/resolve-release/scripts/reprobe-credentials.mjs +0 -114
  146. package/skills/engineering/resolve-release/scripts/revalidate-candidate.mjs +0 -238
  147. package/skills/engineering/resolve-release/scripts/review-packet.mjs +0 -503
  148. package/skills/engineering/resolve-release/scripts/rollback-floor.mjs +0 -263
  149. package/skills/engineering/resolve-release/scripts/version-assert.mjs +0 -339
  150. package/skills/engineering/resolve-release/scripts/version-postmortem.mjs +0 -485
  151. package/skills/engineering/resolve-release/scripts/version.mjs +0 -1199
  152. package/skills/engineering/resolve-release/scripts/watch-candidate-delivery.mjs +0 -449
  153. package/skills/engineering/resolve-release/vendor/ACORN-LICENSE +0 -21
  154. package/skills/engineering/resolve-release/vendor/README.md +0 -60
  155. package/skills/engineering/resolve-release/vendor/acorn.mjs +0 -6233
  156. package/skills/engineering/resolve-release/vendor/quickjs/core/LICENSE +0 -21
  157. package/skills/engineering/resolve-release/vendor/quickjs/core/README.md +0 -341
  158. package/skills/engineering/resolve-release/vendor/quickjs/core/README.template.md +0 -70
  159. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs +0 -2
  160. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs.map +0 -1
  161. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs +0 -7
  162. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs.map +0 -1
  163. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.mts +0 -2033
  164. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.ts +0 -2033
  165. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js +0 -7
  166. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js.map +0 -1
  167. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs +0 -2
  168. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs.map +0 -1
  169. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs +0 -2
  170. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs.map +0 -1
  171. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs +0 -2
  172. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs.map +0 -1
  173. package/skills/engineering/resolve-release/vendor/quickjs/core/package.json +0 -49
  174. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/LICENSE +0 -21
  175. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/README.md +0 -5
  176. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.mts +0 -549
  177. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.ts +0 -549
  178. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js +0 -2
  179. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js.map +0 -1
  180. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs +0 -2
  181. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs.map +0 -1
  182. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/package.json +0 -36
  183. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/LICENSE +0 -47
  184. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/README.md +0 -82
  185. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.d.ts +0 -11
  186. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.mjs +0 -22
  187. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cjs +0 -21
  188. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.cjs +0 -21
  189. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.d.ts +0 -11
  190. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.d.ts +0 -11
  191. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.mjs +0 -25
  192. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.wasm +0 -0
  193. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.mts +0 -85
  194. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.ts +0 -85
  195. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js +0 -2
  196. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js.map +0 -1
  197. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs +0 -2
  198. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs.map +0 -1
  199. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.mts +0 -20
  200. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.ts +0 -20
  201. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js +0 -2
  202. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js.map +0 -1
  203. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs +0 -2
  204. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs.map +0 -1
  205. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/package.json +0 -61
  206. /package/skills/{engineering/resolve-issues → payment/tld-detection}/LICENSE +0 -0
@@ -1,332 +0,0 @@
1
- // GitHub provider for exact-head-ci.mjs. Reads one operation as JSON on stdin and
2
- // writes one JSON response. It never exposes enqueue, approve, merge, review-write,
3
- // or queue-write operations.
4
-
5
- import fs from 'node:fs'
6
- import { execFileSync } from 'node:child_process'
7
- import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
8
- import { providerWorkflowIdentityMatches } from '../../engineering-runtime/scripts/exact-head-artifact.mjs'
9
-
10
- const PROVIDER_HANDLERS = Object.freeze({
11
- snapshot,
12
- retarget: mutate,
13
- 'set-open': mutate,
14
- 'set-draft': mutate,
15
- 'set-labels': mutate,
16
- 'set-queue-inactive': deactivateQueue,
17
- 'dispatch-workflow': dispatch,
18
- 'read-workflow': readWorkflow,
19
- 'read-publish-only-checks': readPublishOnlyChecks,
20
- 'read-queue-execution': readQueueExecution,
21
- })
22
-
23
- export const PROVIDER_OPERATIONS = Object.freeze(Object.keys(PROVIDER_HANDLERS))
24
-
25
- function isObject(value) {
26
- return value !== null && typeof value === 'object' && !Array.isArray(value)
27
- }
28
-
29
- function strings(value) {
30
- return Array.isArray(value) && value.every((item) => typeof item === 'string' && item.trim())
31
- }
32
-
33
- export function validateProviderRequest(request) {
34
- const errors = []
35
- if (!isObject(request)) return { ok: false, errors: ['provider request must be an object'] }
36
- if (!PROVIDER_OPERATIONS.includes(request.operation)) errors.push(`unsupported provider operation "${request.operation}"`)
37
- if (typeof request.repository !== 'string' || !/^[^/\s]+\/[^/\s]+$/.test(request.repository)) errors.push('repository must be owner/name')
38
- if (!Number.isInteger(request.pr) || request.pr < 1) errors.push('pr must be a positive integer')
39
- const config = request.providerConfig
40
- const readOnlyQueueExecution = request.operation === 'read-queue-execution'
41
- const needsSnapshotConfig = ['snapshot', 'retarget', 'set-open', 'set-draft', 'set-labels', 'set-queue-inactive', 'read-publish-only-checks'].includes(request.operation)
42
- const needsDeactivationConfig = request.operation === 'set-queue-inactive'
43
- const needsDispatchConfig = request.operation === 'dispatch-workflow'
44
- if (!readOnlyQueueExecution && !isObject(config)) errors.push('providerConfig must be an object')
45
- if (!readOnlyQueueExecution && config?.ghCommand !== undefined && (typeof config.ghCommand !== 'string' || !config.ghCommand.trim())) errors.push('providerConfig.ghCommand must be a non-empty string')
46
-
47
- if (needsSnapshotConfig) {
48
- if (!strings(config?.queueActiveLabels)) errors.push('providerConfig.queueActiveLabels must be an array of strings (use [] when no label represents queue membership)')
49
- if (typeof config?.queueProvider !== 'string' || !config.queueProvider.trim()) errors.push('providerConfig.queueProvider must be a non-empty string')
50
- }
51
-
52
- if (needsDeactivationConfig) {
53
- const deactivateArgs = config?.queueDeactivateArgs
54
- const deactivateBodyIndex = Array.isArray(deactivateArgs) ? deactivateArgs.indexOf('--body') : -1
55
- const deactivateBody = deactivateBodyIndex >= 0 ? deactivateArgs[deactivateBodyIndex + 1] : ''
56
- const nonDeactivationBody = typeof deactivateBody === 'string' ? deactivateBody.replace(/\b(?:dequeue|unqueue)\b/gi, '') : ''
57
- const safeDeactivation = Array.isArray(deactivateArgs)
58
- && deactivateArgs.length === 7
59
- && deactivateArgs.slice(0, 6).every((arg, index) => arg === ['pr', 'comment', '{pr}', '--repo', '{repository}', '--body'][index])
60
- && typeof deactivateBody === 'string'
61
- && /\b(?:dequeue|unqueue)\b/i.test(deactivateBody)
62
- && !/\b(?:queue|enqueue|approve|merge|review)\b/i.test(nonDeactivationBody)
63
- if (!strings(deactivateArgs)) errors.push('providerConfig.queueDeactivateArgs must be an array of strings')
64
- if (Array.isArray(config?.queueActiveLabels) && config.queueActiveLabels.length > 0 && Array.isArray(deactivateArgs) && deactivateArgs.length === 0) errors.push('providerConfig.queueDeactivateArgs cannot be empty when queueActiveLabels can detect active membership')
65
- if (Array.isArray(config?.queueActiveLabels) && config.queueActiveLabels.length > 0 && !safeDeactivation) errors.push('providerConfig.queueDeactivateArgs must be a direct gh pr comment deactivation and cannot enqueue, approve, merge, or write reviews')
66
- }
67
-
68
- if (needsDispatchConfig) {
69
- for (const field of ['creationTimeoutMs', 'creationPollIntervalMs']) {
70
- if (!Number.isInteger(config?.[field]) || config[field] < 1) errors.push(`providerConfig.${field} must be a positive integer`)
71
- }
72
- }
73
- if (request.operation === 'read-workflow') {
74
- if (typeof request.runId !== 'string' && typeof request.runId !== 'number') errors.push('runId must identify the provider run')
75
- if (typeof request.workflowId !== 'string' || !request.workflowId.trim()) errors.push('workflowId must identify the expected provider workflow')
76
- if (typeof request.headSha !== 'string' || !/^[0-9a-f]{40}$/i.test(request.headSha)) errors.push('headSha must be a full 40-character commit SHA')
77
- }
78
- return { ok: errors.length === 0, errors }
79
- }
80
-
81
- const DEFAULT_BOUNDARY = Object.freeze({ execFileSync })
82
-
83
- function gh(request, args, boundary) {
84
- return boundary.execFileSync(request.providerConfig?.ghCommand || 'gh', args, {
85
- encoding: 'utf8', maxBuffer: 32 * 1024 * 1024,
86
- }).trim()
87
- }
88
-
89
- function ghJson(request, args, boundary) {
90
- const text = gh(request, args, boundary)
91
- return text ? JSON.parse(text) : null
92
- }
93
-
94
- function pause(ms) {
95
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms)
96
- }
97
-
98
- export function snapshotFromView(view, config) {
99
- const labels = (view.labels || []).map((label) => typeof label === 'string' ? label : label.name).filter(Boolean).sort()
100
- const activeLabels = new Set(config.queueActiveLabels)
101
- const matchingLabels = labels.filter((label) => activeLabels.has(label))
102
- return {
103
- base: view.baseRefName,
104
- headSha: view.headRefOid,
105
- open: view.state === 'OPEN',
106
- draft: view.isDraft === true,
107
- labels,
108
- queue: {
109
- provider: config.queueProvider,
110
- state: matchingLabels.length ? 'active' : 'inactive',
111
- active: matchingLabels.length > 0,
112
- matchingLabels,
113
- },
114
- reviews: {
115
- decision: view.reviewDecision || null,
116
- latest: (view.latestReviews || []).map(({ id, author, state, submittedAt, commit }) => ({
117
- id: id || null,
118
- author: author?.login || null,
119
- state: state || null,
120
- submittedAt: submittedAt || null,
121
- commitOid: commit?.oid || null,
122
- })),
123
- },
124
- }
125
- }
126
-
127
- export function labelDelta(current, target) {
128
- const have = new Set(current)
129
- const want = new Set(target)
130
- return {
131
- add: [...want].filter((label) => !have.has(label)).sort(),
132
- remove: [...have].filter((label) => !want.has(label)).sort(),
133
- }
134
- }
135
-
136
- export function chooseCreatedRun(runs, { headSha, startedAt }) {
137
- return (runs || [])
138
- .filter((run) => run.headSha === headSha && Date.parse(run.createdAt) >= Date.parse(startedAt))
139
- .sort((left, right) => Date.parse(left.createdAt) - Date.parse(right.createdAt))[0] || null
140
- }
141
-
142
- function snapshot(request, boundary) {
143
- const view = ghJson(request, ['pr', 'view', String(request.pr), '--repo', request.repository, '--json', 'baseRefName,headRefOid,state,isDraft,labels,reviewDecision,latestReviews'], boundary)
144
- return snapshotFromView(view, request.providerConfig)
145
- }
146
-
147
- function mutate(request, boundary) {
148
- const base = ['--repo', request.repository]
149
- const current = snapshot(request, boundary)
150
- if (request.operation === 'retarget') {
151
- if (current.base === request.base) return { ok: true, unchanged: true }
152
- gh(request, ['pr', 'edit', String(request.pr), ...base, '--base', request.base], boundary)
153
- } else if (request.operation === 'set-open') {
154
- if (current.open === request.open) return { ok: true, unchanged: true }
155
- gh(request, ['pr', request.open ? 'reopen' : 'close', String(request.pr), ...base], boundary)
156
- } else if (request.operation === 'set-draft') {
157
- if (current.draft === request.draft) return { ok: true, unchanged: true }
158
- gh(request, request.draft
159
- ? ['pr', 'ready', String(request.pr), ...base, '--undo']
160
- : ['pr', 'ready', String(request.pr), ...base], boundary)
161
- } else if (request.operation === 'set-labels') {
162
- const delta = labelDelta(current.labels, request.labels)
163
- for (const label of delta.remove) gh(request, ['pr', 'edit', String(request.pr), ...base, '--remove-label', label], boundary)
164
- for (const label of delta.add) gh(request, ['pr', 'edit', String(request.pr), ...base, '--add-label', label], boundary)
165
- }
166
- return { ok: true }
167
- }
168
-
169
- function deactivateQueue(request, boundary) {
170
- const current = snapshot(request, boundary)
171
- if (!current.queue.active) return { ok: true, alreadyInactive: true }
172
- const args = request.providerConfig.queueDeactivateArgs.map((arg) => arg
173
- .replaceAll('{pr}', String(request.pr))
174
- .replaceAll('{repository}', request.repository))
175
- gh(request, args, boundary)
176
- return { ok: true, alreadyInactive: false }
177
- }
178
-
179
- function dispatch(request, boundary) {
180
- const startedAt = new Date().toISOString()
181
- const args = ['workflow', 'run', request.workflow, '--repo', request.repository, '--ref', request.ref]
182
- for (const [key, value] of Object.entries(request.inputs || {})) args.push('-f', `${key}=${String(value)}`)
183
- gh(request, args, boundary)
184
- const deadline = Date.now() + request.providerConfig.creationTimeoutMs
185
- while (Date.now() <= deadline) {
186
- const runs = ghJson(request, ['run', 'list', '--repo', request.repository, '--workflow', request.workflow, '--event', 'workflow_dispatch', '--limit', '100', '--json', 'databaseId,status,conclusion,headSha,createdAt'], boundary)
187
- const run = chooseCreatedRun(runs, { headSha: request.headSha, startedAt })
188
- if (run) return { runId: run.databaseId }
189
- pause(request.providerConfig.creationPollIntervalMs)
190
- }
191
- throw new Error(`workflow-creation-failure: no ${request.workflow} run appeared at ${request.headSha} within ${request.providerConfig.creationTimeoutMs}ms`)
192
- }
193
-
194
- function readWorkflow(request, boundary) {
195
- const run = ghJson(request, ['api', `repos/${request.repository}/actions/runs/${request.runId}`], boundary)
196
- const workflow = { id: run?.workflow_id, name: run?.name, path: run?.path }
197
- if (String(run?.id) !== String(request.runId)) throw new Error(`workflow run identity mismatch: expected run ${request.runId}, observed ${run?.id ?? 'missing'}`)
198
- if (run?.head_sha !== request.headSha) throw new Error(`workflow head-drift: expected ${request.headSha}, observed ${run?.head_sha ?? 'missing'}`)
199
- if (!providerWorkflowIdentityMatches(request.workflowId, workflow)) {
200
- throw new Error(`workflow identity mismatch: expected ${request.workflowId}, observed ${workflow.name || workflow.path || workflow.id || 'missing'}`)
201
- }
202
- const pages = ghJson(request, ['api', '--paginate', '--slurp', `repos/${request.repository}/actions/runs/${request.runId}/jobs?per_page=100`], boundary) || []
203
- const jobs = pages.flatMap((page) => page.jobs || []).map(({ id, name, status, conclusion }) => ({ id, name, status, conclusion }))
204
- return { runId: run.id, workflow, status: run.status, conclusion: run.conclusion, headSha: run.head_sha, jobs }
205
- }
206
- const MERGIFY_PAYLOAD_RE = /-\*- Mergify Payload -\*-\s*\n(\{[\s\S]*?\})\s*\n-\*- Mergify Payload End -\*-/
207
-
208
- function mergedQueuePr(comments) {
209
- const status = (comments || []).filter((comment) => comment?.author?.login === 'mergify' && /"state"\s*:\s*"merged"/.test(comment?.body || ''))
210
- const ids = status.map((comment) => /Checks passed\s*[^#]*#(\d+)/i.exec(comment.body || '')?.[1]).filter(Boolean)
211
- return ids.length === 1 ? Number(ids[0]) : null
212
- }
213
-
214
- function queuePrNumber(value) {
215
- return Number.isInteger(value) && value > 0 ? value : null
216
- }
217
-
218
- function activeQueuePr(comments) {
219
- let queuePr = null
220
- for (const comment of Array.isArray(comments) ? comments : []) {
221
- if (comment?.author?.login !== 'mergify') continue
222
- const match = MERGIFY_PAYLOAD_RE.exec(comment?.body || '')
223
- if (!match) continue
224
- let payload
225
- try { payload = JSON.parse(match[1]) } catch { continue }
226
- const candidate = queuePrNumber(payload?.speculative_check_pr)
227
- if (candidate) queuePr = candidate
228
- }
229
- return queuePr
230
- }
231
-
232
- function queueCheckState(run) {
233
- const conclusion = String(run?.conclusion ?? '').toLowerCase()
234
- if (conclusion === 'success') return 'success'
235
- if (['failure', 'error', 'timed_out', 'cancelled', 'action_required', 'startup_failure'].includes(conclusion)) return 'failure'
236
- if (['neutral', 'skipped'].includes(conclusion)) return conclusion
237
- const status = String(run?.status ?? run?.state ?? '').toLowerCase()
238
- if (['queued', 'requested', 'waiting', 'pending'].includes(status)) return 'queued'
239
- if (['in_progress', 'running'].includes(status)) return 'running'
240
- return 'queued'
241
- }
242
-
243
- function queueObservationStatus(checks, wantedCount) {
244
- if (checks.some((check) => check.state === 'failure')) return 'failure'
245
- if (checks.length === wantedCount && checks.every((check) => check.state === 'success')) return 'success'
246
- if (checks.some((check) => check.state === 'running')) return 'running'
247
- return 'queued'
248
- }
249
-
250
- function readQueueExecution(request, boundary) {
251
- const source = ghJson(request, ['pr', 'view', String(request.pr), '--repo', request.repository, '--json', 'headRefOid,comments'], boundary)
252
- if (source?.headRefOid !== request.prHeadSha) throw new Error(`queue-execution PR-head drift: expected ${request.prHeadSha}, observed ${source?.headRefOid ?? 'missing'}`)
253
- const mergedPr = mergedQueuePr(source.comments)
254
- const queuePr = mergedPr ?? activeQueuePr(source.comments)
255
- if (!queuePr) throw new Error('queue-execution unavailable or ambiguous: Mergify status did not identify one synthetic draft PR')
256
- const queue = ghJson(request, ['api', `repos/${request.repository}/pulls/${queuePr}`], boundary)
257
- const queueHeadSha = queue?.head?.sha
258
- if (typeof queueHeadSha !== 'string' || !/^[0-9a-f]{40}$/i.test(queueHeadSha) || queueHeadSha === request.prHeadSha) {
259
- throw new Error('queue-execution unavailable: synthetic queue PR has no distinct full head SHA')
260
- }
261
- const pages = ghJson(request, ['api', '--paginate', '--slurp', `repos/${request.repository}/commits/${queueHeadSha}/check-runs?per_page=100`], boundary) || []
262
- const wanted = new Set(request.names || [])
263
- const runs = pages.flatMap((page) => page.check_runs || []).filter((run) => wanted.has(run.name))
264
- const byName = new Map()
265
- for (const run of runs) {
266
- if (byName.has(run.name)) throw new Error(`queue-execution ambiguous: duplicate check run ${run.name} on synthetic head`)
267
- byName.set(run.name, run)
268
- }
269
- if (mergedPr) {
270
- if (byName.size !== wanted.size) throw new Error('queue-execution unavailable: one or more required queue-head checks are missing')
271
- return {
272
- version: 1, kind: 'queue-execution', repository: request.repository, pr: request.pr,
273
- prHeadSha: request.prHeadSha, queuePr, queueHeadSha, provider: 'github',
274
- checks: [...wanted].sort().map((name) => ({ name, provider: 'github', conclusion: byName.get(name).conclusion, headSha: queueHeadSha })),
275
- status: 'pass',
276
- }
277
- }
278
- const checks = [...wanted].sort().flatMap((name) => {
279
- const run = byName.get(name)
280
- return run ? [{
281
- name, provider: 'github', status: run.status ?? null, conclusion: run.conclusion ?? null,
282
- state: queueCheckState(run), headSha: queueHeadSha,
283
- }] : []
284
- })
285
- return {
286
- version: 1, kind: 'queue-execution-observation', repository: request.repository, pr: request.pr,
287
- prHeadSha: request.prHeadSha, queuePr, queueHeadSha, provider: 'github', checks,
288
- status: queueObservationStatus(checks, wanted.size),
289
- }
290
- }
291
-
292
- function readPublishOnlyChecks(request, boundary) {
293
- const live = snapshot(request, boundary)
294
- if (live.headSha !== request.headSha) throw new Error(`publish-only head-drift: expected ${request.headSha}, observed ${live.headSha}`)
295
- const pages = ghJson(request, ['api', '--paginate', '--slurp', `repos/${request.repository}/commits/${request.headSha}/check-runs?per_page=100`], boundary) || []
296
- const checks = pages.flatMap((page) => page.check_runs || [])
297
- const requested = new Set(request.names || [])
298
- return {
299
- checks: checks.filter((check) => requested.has(check.name)).map((check) => ({
300
- name: check.name,
301
- provider: 'github',
302
- repository: request.repository,
303
- pr: request.pr,
304
- headSha: request.headSha,
305
- conclusion: check.conclusion,
306
- })),
307
- }
308
- }
309
-
310
-
311
- export function handleProviderRequest(request, boundary = DEFAULT_BOUNDARY) {
312
- const verdict = validateProviderRequest(request)
313
- if (!verdict.ok) throw new Error(`invalid GitHub provider request: ${verdict.errors.join('; ')}`)
314
- return PROVIDER_HANDLERS[request.operation](request, boundary)
315
- }
316
-
317
- function main() {
318
- if (process.argv.includes('--help') || process.argv.includes('-h')) {
319
- console.log('usage: exact-head-github-provider.mjs # reads one exact-head provider operation as JSON on stdin')
320
- return 0
321
- }
322
- try {
323
- const request = JSON.parse(fs.readFileSync(0, 'utf8'))
324
- process.stdout.write(`${JSON.stringify(handleProviderRequest(request))}\n`)
325
- return 0
326
- } catch (error) {
327
- console.error(`exact-head-github-provider: ${String(error.message || error)}`)
328
- return 1
329
- }
330
- }
331
-
332
- if (isMainModule(import.meta.url)) process.exit(main())