@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,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
- }