@1aboveio/skills 0.19.3 → 0.20.1

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 (197) 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/mergify/SKILL.md +1 -1
  8. package/skills/engineering/engineering-runtime/coherence/workflow.json +14 -83
  9. package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -6
  10. package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +3 -36
  11. package/skills/engineering/smoke/SKILL.md +1 -1
  12. package/skills/payment/payment-analysis/SKILL.md +5 -3
  13. package/skills/payment/tld-detection/SKILL.md +163 -0
  14. package/skills/payment/tld-detection/agents/openai.yaml +9 -0
  15. package/skills/payment/tld-detection/evals/evals.json +107 -0
  16. package/skills/payment/tld-detection/references/clean.md +51 -0
  17. package/skills/payment/tld-detection/references/clustering.md +219 -0
  18. package/skills/payment/tld-detection/references/decision.md +85 -0
  19. package/skills/payment/tld-detection/references/report-template.md +169 -0
  20. package/skills/payment/tld-detection/references/terminology.md +69 -0
  21. package/skills/payment/tld-detection/references/workflow.md +78 -0
  22. package/skills/payment/tld-detection/scripts/detect_ladders.py +390 -0
  23. package/skills/payment/tld-detection/tests/test_detect_ladders.py +132 -0
  24. package/skills/engineering/resolve-issues/SKILL.md +0 -168
  25. package/skills/engineering/resolve-issues/agents/openai.yaml +0 -9
  26. package/skills/engineering/resolve-issues/generated/workflow-repair-policy.json +0 -499
  27. package/skills/engineering/resolve-issues/references/breaker.md +0 -82
  28. package/skills/engineering/resolve-issues/references/deliverables.md +0 -27
  29. package/skills/engineering/resolve-issues/references/delivery.md +0 -108
  30. package/skills/engineering/resolve-issues/references/evidence-lane.md +0 -21
  31. package/skills/engineering/resolve-issues/references/exact-head-ci.md +0 -287
  32. package/skills/engineering/resolve-issues/references/fan-out.md +0 -33
  33. package/skills/engineering/resolve-issues/references/finalization.md +0 -68
  34. package/skills/engineering/resolve-issues/references/guarantees.md +0 -10
  35. package/skills/engineering/resolve-issues/references/high-risk.md +0 -29
  36. package/skills/engineering/resolve-issues/references/incidents/848/README.md +0 -156
  37. package/skills/engineering/resolve-issues/references/intake.md +0 -86
  38. package/skills/engineering/resolve-issues/references/integration-gate.md +0 -53
  39. package/skills/engineering/resolve-issues/references/interference.md +0 -87
  40. package/skills/engineering/resolve-issues/references/loop.md +0 -134
  41. package/skills/engineering/resolve-issues/references/model-catalog.md +0 -9
  42. package/skills/engineering/resolve-issues/references/postmortem.md +0 -27
  43. package/skills/engineering/resolve-issues/references/pre-flight-model-slots.md +0 -41
  44. package/skills/engineering/resolve-issues/references/pre-flight-recording-and-checkout.md +0 -48
  45. package/skills/engineering/resolve-issues/references/pre-flight.md +0 -41
  46. package/skills/engineering/resolve-issues/references/regression-checklist.md +0 -26
  47. package/skills/engineering/resolve-issues/references/run-state.md +0 -288
  48. package/skills/engineering/resolve-issues/references/sandboxed-testing.md +0 -48
  49. package/skills/engineering/resolve-issues/references/spawn-contract.md +0 -96
  50. package/skills/engineering/resolve-issues/references/terminal-evidence-journal.md +0 -40
  51. package/skills/engineering/resolve-issues/references/why.md +0 -653
  52. package/skills/engineering/resolve-issues/schemas/fix-round.schema.json +0 -49
  53. package/skills/engineering/resolve-issues/scripts/combine-and-verify.mjs +0 -721
  54. package/skills/engineering/resolve-issues/scripts/component-candidate.mjs +0 -962
  55. package/skills/engineering/resolve-issues/scripts/contract-revision.mjs +0 -220
  56. package/skills/engineering/resolve-issues/scripts/detect-delivery-mode.mjs +0 -420
  57. package/skills/engineering/resolve-issues/scripts/detect-target-branch.mjs +0 -256
  58. package/skills/engineering/resolve-issues/scripts/detect-workspace-mode.mjs +0 -168
  59. package/skills/engineering/resolve-issues/scripts/discover-models.mjs +0 -9
  60. package/skills/engineering/resolve-issues/scripts/doctrine.mjs +0 -62
  61. package/skills/engineering/resolve-issues/scripts/evidence-lifecycle-contract.mjs +0 -191
  62. package/skills/engineering/resolve-issues/scripts/exact-head-ci.mjs +0 -413
  63. package/skills/engineering/resolve-issues/scripts/exact-head-github-provider.mjs +0 -332
  64. package/skills/engineering/resolve-issues/scripts/finalize.mjs +0 -488
  65. package/skills/engineering/resolve-issues/scripts/fix-rounds.mjs +0 -3307
  66. package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-circular-1001.json +0 -16
  67. package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-valid-sequencing.json +0 -51
  68. package/skills/engineering/resolve-issues/scripts/fixtures/fmm-express-830-component-candidate.json +0 -17
  69. package/skills/engineering/resolve-issues/scripts/fixtures/head-check-set-1081.json +0 -166
  70. package/skills/engineering/resolve-issues/scripts/gate-value-series.mjs +0 -92
  71. package/skills/engineering/resolve-issues/scripts/guide-index.mjs +0 -73
  72. package/skills/engineering/resolve-issues/scripts/head-check-set.mjs +0 -159
  73. package/skills/engineering/resolve-issues/scripts/interference.mjs +0 -427
  74. package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +0 -9
  75. package/skills/engineering/resolve-issues/scripts/next-operations.mjs +0 -419
  76. package/skills/engineering/resolve-issues/scripts/postmortem.mjs +0 -909
  77. package/skills/engineering/resolve-issues/scripts/preflight-questions.mjs +0 -345
  78. package/skills/engineering/resolve-issues/scripts/reconcile-contained-unit-prs.mjs +0 -415
  79. package/skills/engineering/resolve-issues/scripts/release-state-contract.mjs +0 -697
  80. package/skills/engineering/resolve-issues/scripts/report.mjs +0 -494
  81. package/skills/engineering/resolve-issues/scripts/required-check-plan.mjs +0 -172
  82. package/skills/engineering/resolve-issues/scripts/round-metadata.mjs +0 -79
  83. package/skills/engineering/resolve-issues/scripts/run-state-review6-cases.mjs +0 -334
  84. package/skills/engineering/resolve-issues/scripts/run-state.mjs +0 -4792
  85. package/skills/engineering/resolve-issues/scripts/sandbox-selftest.mjs +0 -395
  86. package/skills/engineering/resolve-issues/scripts/spawn-contract.mjs +0 -290
  87. package/skills/engineering/resolve-issues/scripts/terminal-dispositions.mjs +0 -170
  88. package/skills/engineering/resolve-issues/scripts/terminal-evidence-journal.mjs +0 -293
  89. package/skills/engineering/resolve-issues/scripts/unit-kind.mjs +0 -197
  90. package/skills/engineering/resolve-issues/scripts/unit-lifecycle.mjs +0 -127
  91. package/skills/engineering/resolve-issues/scripts/watch-delivery.mjs +0 -893
  92. package/skills/engineering/resolve-issues/scripts/workspaces.mjs +0 -829
  93. package/skills/engineering/resolve-issues/workflows/independent-review.workflow.js +0 -290
  94. package/skills/engineering/resolve-issues/workflows/prior-art-scan.workflow.js +0 -80
  95. package/skills/engineering/resolve-issues/workflows/workflow-smoke.mjs +0 -102
  96. package/skills/engineering/resolve-release/LICENSE +0 -3
  97. package/skills/engineering/resolve-release/SKILL.md +0 -113
  98. package/skills/engineering/resolve-release/agents/openai.yaml +0 -9
  99. package/skills/engineering/resolve-release/references/assembly.md +0 -137
  100. package/skills/engineering/resolve-release/references/auto-when-green.md +0 -56
  101. package/skills/engineering/resolve-release/references/candidate.md +0 -167
  102. package/skills/engineering/resolve-release/references/exposure.md +0 -178
  103. package/skills/engineering/resolve-release/references/handoff.md +0 -24
  104. package/skills/engineering/resolve-release/references/postmortem.md +0 -230
  105. package/skills/engineering/resolve-release/references/preflight.md +0 -208
  106. package/skills/engineering/resolve-release/references/principles.md +0 -94
  107. package/skills/engineering/resolve-release/references/regression-checklist.md +0 -36
  108. package/skills/engineering/resolve-release/references/related-skills.md +0 -13
  109. package/skills/engineering/resolve-release/references/routing.md +0 -149
  110. package/skills/engineering/resolve-release/references/verified-sha-github-flow.md +0 -285
  111. package/skills/engineering/resolve-release/references/versioning.md +0 -202
  112. package/skills/engineering/resolve-release/references/why.md +0 -53
  113. package/skills/engineering/resolve-release/scripts/adapter-completion-artifact.mjs +0 -389
  114. package/skills/engineering/resolve-release/scripts/build-changes.mjs +0 -209
  115. package/skills/engineering/resolve-release/scripts/candidate-hygiene.mjs +0 -407
  116. package/skills/engineering/resolve-release/scripts/candidate-identity.mjs +0 -904
  117. package/skills/engineering/resolve-release/scripts/candidate-traffic.mjs +0 -81
  118. package/skills/engineering/resolve-release/scripts/checked-adapter-loader.mjs +0 -612
  119. package/skills/engineering/resolve-release/scripts/close-attempt.mjs +0 -135
  120. package/skills/engineering/resolve-release/scripts/closeout-release.mjs +0 -161
  121. package/skills/engineering/resolve-release/scripts/doctrine.mjs +0 -106
  122. package/skills/engineering/resolve-release/scripts/durable-processing.mjs +0 -522
  123. package/skills/engineering/resolve-release/scripts/ensure-target-green.mjs +0 -659
  124. package/skills/engineering/resolve-release/scripts/evidence-bundle.mjs +0 -1014
  125. package/skills/engineering/resolve-release/scripts/finalize-release.mjs +0 -526
  126. package/skills/engineering/resolve-release/scripts/fixtures/durable-processing-adapter.mjs +0 -169
  127. package/skills/engineering/resolve-release/scripts/green-gate.mjs +0 -599
  128. package/skills/engineering/resolve-release/scripts/isolated-adapter-evaluator.mjs +0 -752
  129. package/skills/engineering/resolve-release/scripts/metadata-pr-status.mjs +0 -56
  130. package/skills/engineering/resolve-release/scripts/metadata-sync.mjs +0 -1538
  131. package/skills/engineering/resolve-release/scripts/postmortem.mjs +0 -381
  132. package/skills/engineering/resolve-release/scripts/preflight-probes.mjs +0 -510
  133. package/skills/engineering/resolve-release/scripts/production-endpoints.mjs +0 -326
  134. package/skills/engineering/resolve-release/scripts/rc-circuit-breaker.mjs +0 -272
  135. package/skills/engineering/resolve-release/scripts/report.mjs +0 -417
  136. package/skills/engineering/resolve-release/scripts/reprobe-credentials.mjs +0 -114
  137. package/skills/engineering/resolve-release/scripts/revalidate-candidate.mjs +0 -238
  138. package/skills/engineering/resolve-release/scripts/review-packet.mjs +0 -503
  139. package/skills/engineering/resolve-release/scripts/rollback-floor.mjs +0 -263
  140. package/skills/engineering/resolve-release/scripts/version-assert.mjs +0 -339
  141. package/skills/engineering/resolve-release/scripts/version-postmortem.mjs +0 -485
  142. package/skills/engineering/resolve-release/scripts/version.mjs +0 -1199
  143. package/skills/engineering/resolve-release/scripts/watch-candidate-delivery.mjs +0 -449
  144. package/skills/engineering/resolve-release/vendor/ACORN-LICENSE +0 -21
  145. package/skills/engineering/resolve-release/vendor/README.md +0 -60
  146. package/skills/engineering/resolve-release/vendor/acorn.mjs +0 -6233
  147. package/skills/engineering/resolve-release/vendor/quickjs/core/LICENSE +0 -21
  148. package/skills/engineering/resolve-release/vendor/quickjs/core/README.md +0 -341
  149. package/skills/engineering/resolve-release/vendor/quickjs/core/README.template.md +0 -70
  150. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs +0 -2
  151. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs.map +0 -1
  152. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs +0 -7
  153. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs.map +0 -1
  154. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.mts +0 -2033
  155. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.ts +0 -2033
  156. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js +0 -7
  157. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js.map +0 -1
  158. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs +0 -2
  159. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs.map +0 -1
  160. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs +0 -2
  161. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs.map +0 -1
  162. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs +0 -2
  163. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs.map +0 -1
  164. package/skills/engineering/resolve-release/vendor/quickjs/core/package.json +0 -49
  165. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/LICENSE +0 -21
  166. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/README.md +0 -5
  167. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.mts +0 -549
  168. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.ts +0 -549
  169. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js +0 -2
  170. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js.map +0 -1
  171. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs +0 -2
  172. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs.map +0 -1
  173. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/package.json +0 -36
  174. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/LICENSE +0 -47
  175. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/README.md +0 -82
  176. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.d.ts +0 -11
  177. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.mjs +0 -22
  178. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cjs +0 -21
  179. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.cjs +0 -21
  180. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.d.ts +0 -11
  181. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.d.ts +0 -11
  182. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.mjs +0 -25
  183. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.wasm +0 -0
  184. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.mts +0 -85
  185. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.ts +0 -85
  186. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js +0 -2
  187. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js.map +0 -1
  188. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs +0 -2
  189. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs.map +0 -1
  190. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.mts +0 -20
  191. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.ts +0 -20
  192. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js +0 -2
  193. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js.map +0 -1
  194. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs +0 -2
  195. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs.map +0 -1
  196. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/package.json +0 -61
  197. /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())