@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,345 +0,0 @@
1
- import { readFileSync } from 'node:fs'
2
-
3
- import {
4
- defineCurrentTurnCapabilities,
5
- defineQuestionAnswers,
6
- defineQuestionSpec,
7
- normalizeQuestionResponses,
8
- planStructuredQuestions,
9
- } from '../../harness-runtime/index.mjs'
10
- import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
11
-
12
- const AUTONOMY_OPTIONS = Object.freeze([
13
- Object.freeze({
14
- id: 'autonomous',
15
- label: 'Autonomous',
16
- description: 'Pre-authorize reversible parks and delivery to the target branch.',
17
- }),
18
- Object.freeze({
19
- id: 'supervised',
20
- label: 'Supervised',
21
- description: 'Stop for each decision that requires human authorization.',
22
- }),
23
- ])
24
-
25
- function isRecord(value) {
26
- return value !== null && typeof value === 'object' && !Array.isArray(value)
27
- }
28
-
29
- function nonEmptyString(value) {
30
- return typeof value === 'string' && value.trim().length > 0
31
- }
32
-
33
- function invalid(message) {
34
- throw new TypeError(`Invalid Resolve Issues pre-flight: ${message}`)
35
- }
36
-
37
- function defineOption(option, label) {
38
- if (!isRecord(option)
39
- || !nonEmptyString(option.id)
40
- || !nonEmptyString(option.label)
41
- || !nonEmptyString(option.description)) {
42
- invalid(`${label} contains a malformed option`)
43
- }
44
- return Object.freeze({
45
- id: option.id,
46
- label: option.label,
47
- description: option.description,
48
- ...(nonEmptyString(option.family) ? { family: option.family } : {}),
49
- ...(nonEmptyString(option.effort) ? { effort: option.effort } : {}),
50
- })
51
- }
52
-
53
- function defineChoiceSet(value, label) {
54
- if (!isRecord(value) || !Array.isArray(value.options) || !nonEmptyString(value.recommended)) {
55
- invalid(`${label} choices require options and a recommended id`)
56
- }
57
- const ids = new Set()
58
- const options = value.options.map((option) => {
59
- if (isRecord(option) && ids.has(option.id)) invalid(`${label} choices contain a duplicate option`)
60
- const defined = defineOption(option, `${label} choices`)
61
- ids.add(defined.id)
62
- return defined
63
- })
64
- if (!ids.has(value.recommended)) invalid(`${label} recommendation is not an option`)
65
- return Object.freeze({ recommended: value.recommended, options: Object.freeze(options) })
66
- }
67
-
68
- // The reviewer slot is never asked (pre-flight.md step 2): it is FILLED from a
69
- // ranking the caller supplies -- the team default first, then the diversity
70
- // ladder -- and resolved against the answered implementer, because "reviewer !=
71
- // implementer" is the only thing that can collide and it is decidable without a
72
- // human. Accepts { default }, { candidates: [...] }, both, or the legacy asked
73
- // shape { recommended, options }, which ranks the recommendation first.
74
- function defineReviewRanking(value, label) {
75
- if (!isRecord(value)) invalid(`${label} requires a default and/or ranked candidates`)
76
- const teamDefault = value.default === undefined ? null : defineOption(value.default, `${label} default`)
77
- const supplied = []
78
- if (Array.isArray(value.candidates)) {
79
- for (const candidate of value.candidates) supplied.push(defineOption(candidate, `${label} candidates`))
80
- } else if (value.options !== undefined || value.recommended !== undefined) {
81
- const choices = defineChoiceSet(value, label)
82
- const recommended = choices.options.find((option) => option.id === choices.recommended)
83
- supplied.push(recommended, ...choices.options.filter((option) => option.id !== choices.recommended))
84
- }
85
-
86
- const ranked = []
87
- const ids = new Set()
88
- for (const option of [...(teamDefault ? [teamDefault] : []), ...supplied]) {
89
- if (ids.has(option.id)) continue
90
- ids.add(option.id)
91
- ranked.push(option)
92
- }
93
- if (ranked.length === 0) invalid(`${label} requires a default and/or ranked candidates`)
94
- return Object.freeze({ default: teamDefault, candidates: Object.freeze(ranked) })
95
- }
96
-
97
- function question(id, header, prompt, choiceSet) {
98
- return defineQuestionSpec({
99
- id,
100
- header,
101
- prompt,
102
- options: choiceSet.options.map(({ id: optionId, label, description }) => ({
103
- id: optionId,
104
- label,
105
- description,
106
- })),
107
- recommendationOrder: [choiceSet.recommended],
108
- })
109
- }
110
-
111
- function metadataEntries(choiceSet) {
112
- return choiceSet.options.map((option) => [option.id, option])
113
- }
114
-
115
- export function planPreflightQuestions(value) {
116
- if (!isRecord(value)) invalid('input must be an object')
117
- const capabilities = defineCurrentTurnCapabilities(value.capabilities)
118
- const implementation = defineChoiceSet(value.implementation, 'implementation')
119
- const target = defineChoiceSet(value.target, 'target branch')
120
- const review = defineReviewRanking(value.review, 'review')
121
- // Autonomy is FILLED, not asked — same shape as the reviewer slot. Completing
122
- // pre-flight records `autonomous` (and therefore mergeShippable-on) unless the
123
- // human overrides in the answer batch or prompt. An unset field on a manifest
124
- // that never ran pre-flight still resolves to supervised elsewhere; this fill
125
- // is what makes a completed pre-flight a recorded authorization.
126
- const autonomy = Object.freeze({ recommended: 'autonomous', options: AUTONOMY_OPTIONS })
127
-
128
- const questions = [
129
- question('implementation', 'Implement', 'Which model should implement every unit in this run?', implementation),
130
- question('target_branch', 'Target', 'Which fetched remote branch should every unit target?', target),
131
- ]
132
- const interaction = planStructuredQuestions(capabilities, questions)
133
- const metadata = Object.freeze(Object.fromEntries([
134
- ...metadataEntries(implementation),
135
- ...review.candidates.map((option) => [option.id, option]),
136
- ]))
137
-
138
- return Object.freeze({
139
- capabilities,
140
- questions: Object.freeze(questions),
141
- interaction,
142
- // Filled slots stated in the pre-flight summary; `record` may honour overrides.
143
- defaulted: Object.freeze({
144
- review: review.candidates[0].id,
145
- autonomy: autonomy.recommended,
146
- }),
147
- reviewRanking: Object.freeze(review.candidates.map((option) => option.id)),
148
- freeTextQuestions: Object.freeze(interaction.kind === 'fallback'
149
- ? questions.map(({ id, prompt }) => Object.freeze({ questionId: id, prompt }))
150
- : []),
151
- selections: Object.freeze({
152
- implementation,
153
- review,
154
- target,
155
- autonomy,
156
- }),
157
- modelMetadata: metadata,
158
- })
159
- }
160
-
161
- function singleAnswer(answers, questionId) {
162
- const values = answers[questionId]
163
- if (!Array.isArray(values) || values.length !== 1 || !nonEmptyString(values[0])) {
164
- invalid(`${questionId} requires exactly one answer`)
165
- }
166
- return values[0]
167
- }
168
-
169
- function selectedOption(choiceSet, id, { allowCustom = false } = {}) {
170
- const option = choiceSet.options?.find((candidate) => candidate.id === id)
171
- if (option) return option
172
- if (allowCustom) return Object.freeze({ id, label: id, description: 'Human-named value.' })
173
- invalid(`answer ${JSON.stringify(id)} is not available for its question`)
174
- }
175
-
176
- function modelPoint(models, slot, option) {
177
- models[slot] = option.id
178
- if (nonEmptyString(option.family)) models[`${slot}Family`] = option.family
179
- if (nonEmptyString(option.effort) && option.effort !== 'high') models[`${slot}Effort`] = option.effort
180
- }
181
-
182
- // Resolve the reviewer fill now that the implementer is answered. Order: the
183
- // human's own override (they named it in the prompt), then the ranking's first
184
- // candidate that is not the implementer. Only a ranking with no distinct
185
- // candidate at all -- a single-model harness -- yields the implementer's own id,
186
- // and that is recorded as NOT INDEPENDENT rather than asked, because there is
187
- // nothing for a human to pick.
188
- function resolveReviewer(session, answers, implementation, customAllowed) {
189
- const { default: teamDefault, candidates } = session.selections.review
190
- if (Object.hasOwn(answers, 'review')) {
191
- const named = singleAnswer(answers, 'review')
192
- const option = selectedOption({ options: candidates }, named, { allowCustom: customAllowed })
193
- return Object.freeze({ option, reason: 'human-named' })
194
- }
195
- const distinct = candidates.find((candidate) => candidate.id !== implementation.id)
196
- if (!distinct) {
197
- return Object.freeze({ option: candidates[0], reason: 'no-distinct-candidate' })
198
- }
199
- const reason = teamDefault && distinct.id === teamDefault.id ? 'team-default' : 'ladder'
200
- return Object.freeze({ option: distinct, reason })
201
- }
202
-
203
- export function modelDiversity(implementation, review) {
204
- if (implementation.id === review.id) {
205
- return Object.freeze({
206
- status: 'not-independent',
207
- independent: false,
208
- reason: 'identical-model-ids',
209
- })
210
- }
211
- if (nonEmptyString(implementation.family)
212
- && nonEmptyString(review.family)
213
- && implementation.family === review.family) {
214
- return Object.freeze({
215
- status: 'reduced-diversity',
216
- independent: true,
217
- reason: 'same-family-different-model-ids',
218
- })
219
- }
220
- return Object.freeze({ status: 'independent', independent: true, reason: null })
221
- }
222
-
223
- export function recordPreflightResponses(session, nativeResponses, options = {}) {
224
- if (session?.interaction?.kind !== 'native') {
225
- invalid('native responses require a native question plan')
226
- }
227
- const answers = normalizeQuestionResponses(session.interaction, nativeResponses)
228
- return recordPreflightAnswers(session, answers, options)
229
- }
230
-
231
- export function recordPreflightAnswers(session, answerValue, { allowHumanNamed = false } = {}) {
232
- if (!isRecord(session) || !isRecord(session.selections)) invalid('question session is malformed')
233
- const answers = defineQuestionAnswers(answerValue)
234
- if (Object.keys(answers).length === 0) {
235
- return Object.freeze({
236
- cancelled: true,
237
- manifestPatch: null,
238
- diversity: null,
239
- reviewFill: null,
240
- autonomyFill: null,
241
- })
242
- }
243
-
244
- const expectedIds = session.questions.map((item) => item.id)
245
- // `review` and `autonomy` are never planned questions; a human who names either
246
- // outright is honoured as an override rather than bounced.
247
- const acceptedIds = [...expectedIds, 'review', 'autonomy']
248
- if (expectedIds.some((id) => !Object.hasOwn(answers, id))
249
- || Object.keys(answers).some((id) => !acceptedIds.includes(id))) {
250
- invalid('answers must complete exactly the planned question batch')
251
- }
252
-
253
- const customAllowed = allowHumanNamed || session.interaction.kind === 'fallback'
254
- const implementationId = singleAnswer(answers, 'implementation')
255
- let implementation = selectedOption(session.selections.implementation, implementationId, {
256
- allowCustom: customAllowed,
257
- })
258
- implementation = session.modelMetadata[implementation.id] ?? implementation
259
-
260
- const reviewFill = resolveReviewer(session, answers, implementation, customAllowed)
261
- const review = session.modelMetadata[reviewFill.option.id] ?? reviewFill.option
262
-
263
- const targetId = singleAnswer(answers, 'target_branch')
264
- selectedOption(session.selections.target, targetId, { allowCustom: customAllowed })
265
-
266
- let autonomy
267
- let autonomyFill
268
- if (Object.hasOwn(answers, 'autonomy')) {
269
- autonomy = singleAnswer(answers, 'autonomy')
270
- selectedOption(session.selections.autonomy, autonomy)
271
- autonomyFill = Object.freeze({ id: autonomy, reason: 'human-named' })
272
- } else {
273
- autonomy = session.defaulted?.autonomy || session.selections.autonomy.recommended
274
- selectedOption(session.selections.autonomy, autonomy)
275
- autonomyFill = Object.freeze({ id: autonomy, reason: 'default' })
276
- }
277
-
278
- const models = {}
279
- modelPoint(models, 'implementation', implementation)
280
- modelPoint(models, 'review', review)
281
- const diversity = modelDiversity(implementation, review)
282
- return Object.freeze({
283
- cancelled: false,
284
- manifestPatch: Object.freeze({
285
- currentTurnCapabilities: session.capabilities,
286
- models: Object.freeze(models),
287
- targetBranch: targetId,
288
- autonomy,
289
- }),
290
- diversity,
291
- reviewFill: Object.freeze({ id: review.id, reason: reviewFill.reason }),
292
- autonomyFill,
293
- })
294
- }
295
-
296
- const CLI_USAGE = `preflight-questions <plan|record|record-native>
297
-
298
- Reads one JSON object from stdin and writes JSON to stdout.
299
- plan pre-flight input -> neutral questions + planned native/fallback interaction
300
- record { preflight, answers, allowHumanNamed? } -> complete manifest patch
301
- record-native { preflight, responses, allowHumanNamed? } -> normalized complete manifest patch
302
-
303
- Exit 0 = result emitted; 1 = invalid input/contract; 2 = usage error.`
304
-
305
- export function runCli(argv, {
306
- input = () => readFileSync(0, 'utf8'),
307
- output = (text) => process.stdout.write(text),
308
- error = (text) => process.stderr.write(text),
309
- } = {}) {
310
- const command = argv[0]
311
- if (command === '--help' || command === '-h' || command === 'help') {
312
- output(`${CLI_USAGE}\n`)
313
- return 0
314
- }
315
- if (!['plan', 'record', 'record-native'].includes(command) || argv.length !== 1) {
316
- error(`${CLI_USAGE}\n`)
317
- return 2
318
- }
319
-
320
- try {
321
- const value = JSON.parse(input())
322
- const result = command === 'plan'
323
- ? planPreflightQuestions(value)
324
- : command === 'record'
325
- ? recordPreflightAnswers(
326
- planPreflightQuestions(value.preflight),
327
- value.answers,
328
- { allowHumanNamed: value.allowHumanNamed === true },
329
- )
330
- : recordPreflightResponses(
331
- planPreflightQuestions(value.preflight),
332
- value.responses,
333
- { allowHumanNamed: value.allowHumanNamed === true },
334
- )
335
- output(`${JSON.stringify(result, null, 2)}\n`)
336
- return 0
337
- } catch (cause) {
338
- error(`preflight-questions: ${cause.message}\n`)
339
- return 1
340
- }
341
- }
342
-
343
- if (isMainModule(import.meta.url)) {
344
- process.exitCode = runCli(process.argv.slice(2))
345
- }