@danceiny/gotry 0.0.1-rc.16 → 0.0.1-rc.18

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 (229) hide show
  1. package/README.md +161 -116
  2. package/README.zh-CN.md +173 -144
  3. package/bin/gotry-booking-copilot.js +53 -0
  4. package/bin/gotry-bootstrap.js +113 -66
  5. package/bin/gotry-inner.js +436 -70
  6. package/bin/gotry-runtime-resolution.d.ts +27 -0
  7. package/bin/gotry-runtime-resolution.js +50 -0
  8. package/bin/gotry.js +1 -1
  9. package/cordis.gotry-patch.yml +5 -1
  10. package/dist/capabilities/agent-reach-deep.js +1 -1
  11. package/dist/capabilities/agent-reach.js +1 -1
  12. package/dist/capabilities/anything.js +1 -1
  13. package/dist/capabilities/artifacts.js +1 -1
  14. package/dist/capabilities/effect.js +1 -1
  15. package/dist/capabilities/fact-log.js +1 -1
  16. package/dist/capabilities/flyai.js +20 -6
  17. package/dist/capabilities/hbcli.js +1 -1
  18. package/dist/capabilities/incident-log.js +1 -1
  19. package/dist/capabilities/model-override.js +18 -0
  20. package/dist/capabilities/opensky.js +1 -1
  21. package/dist/capabilities/resilience.js +1 -1
  22. package/dist/capabilities/session/action-cache.js +1 -1
  23. package/dist/capabilities/session/adapters/ctrip-flight.js +1 -1
  24. package/dist/capabilities/session/adapters/meituan-local.js +1 -1
  25. package/dist/capabilities/session/benchmark.js +1 -1
  26. package/dist/capabilities/session/extension-bridge.js +19 -6
  27. package/dist/capabilities/session/extension-channel.js +3 -3
  28. package/dist/capabilities/session/extension-distribution.js +234 -0
  29. package/dist/capabilities/session/extract.js +1 -1
  30. package/dist/capabilities/session/golden-score.js +92 -0
  31. package/dist/capabilities/session/health-watch.js +1 -1
  32. package/dist/capabilities/session/read-guard.js +1 -1
  33. package/dist/capabilities/session/static-flight-golden.js +137 -0
  34. package/dist/capabilities/session/transport.js +1 -1
  35. package/dist/capabilities/session/wizard.js +21 -251
  36. package/dist/capabilities/session-consent.js +1 -1
  37. package/dist/capabilities/session-login.js +11 -5
  38. package/dist/capabilities/session-search.js +46 -4
  39. package/dist/capabilities/weather.js +168 -46
  40. package/dist/data/session-golden-20.json +25 -0
  41. package/dist/data/sf-golden-manifest.json +102 -0
  42. package/dist/data/sf-static-routes.json +91 -0
  43. package/dist/scripts/action-cache-tests.js +1 -1
  44. package/dist/scripts/agent-planning-budget-e2e.js +227 -0
  45. package/dist/scripts/agent-planning-budget-tests.js +173 -0
  46. package/dist/scripts/agent-reach-deep-tests.js +1 -1
  47. package/dist/scripts/agent-reach-tests.js +1 -1
  48. package/dist/scripts/agent-reach-wrapper-tests.js +1 -1
  49. package/dist/scripts/anything-tests.js +1 -1
  50. package/dist/scripts/async-collect.js +1 -1
  51. package/dist/scripts/benchmark-environment-bridge-e2e.js +981 -0
  52. package/dist/scripts/benchmark-environment-bridge-tests.js +2544 -0
  53. package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +335 -0
  54. package/dist/scripts/booking-copilot-availability-policy-v2-tests.js +1355 -0
  55. package/dist/scripts/booking-copilot-bin-proof-tests.js +89 -0
  56. package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +113 -0
  57. package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +356 -0
  58. package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +557 -0
  59. package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +140 -0
  60. package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +202 -0
  61. package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +102 -0
  62. package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +374 -0
  63. package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +447 -0
  64. package/dist/scripts/booking-copilot-runtime-proof-tests.js +205 -0
  65. package/dist/scripts/booking-copilot-server-proof-tests.js +317 -0
  66. package/dist/scripts/booking-copilot-startup-proof-tests.js +283 -0
  67. package/dist/scripts/booking-copilot-v2-runtime-proof-tests.js +3935 -0
  68. package/dist/scripts/booking-saga-tests.js +1 -1
  69. package/dist/scripts/booking-surface-contract-proof-tests.js +393 -0
  70. package/dist/scripts/booking-surface-v2-contract-proof-tests.js +1174 -0
  71. package/dist/scripts/bootstrap-tests.js +45 -39
  72. package/dist/scripts/build-changelog.js +1 -1
  73. package/dist/scripts/changelog-tests.js +1 -1
  74. package/dist/scripts/companion-tests.js +1 -1
  75. package/dist/scripts/diff-test.js +1 -1
  76. package/dist/scripts/dsh-runtime-closure-tests.js +225 -0
  77. package/dist/scripts/dsh-runtime-closure.js +150 -0
  78. package/dist/scripts/effect-tests.js +1 -1
  79. package/dist/scripts/engine-run.js +1 -1
  80. package/dist/scripts/engine-tests.js +1 -1
  81. package/dist/scripts/evaluation-cadence-tests.js +347 -0
  82. package/dist/scripts/evaluation-contract-tests.js +574 -0
  83. package/dist/scripts/extension-distribution-cli.js +35 -0
  84. package/dist/scripts/extension-distribution-tests.js +341 -0
  85. package/dist/scripts/extension-tests.js +128 -23
  86. package/dist/scripts/fact-gate-tests.js +1 -1
  87. package/dist/scripts/flyai-tests.js +1 -1
  88. package/dist/scripts/hbcli-e2e-tests.js +1 -1
  89. package/dist/scripts/hbcli-tests.js +1 -1
  90. package/dist/scripts/health-watch-cli.js +1 -1
  91. package/dist/scripts/i18n-tests.js +1 -1
  92. package/dist/scripts/incident-tests.js +1 -1
  93. package/dist/scripts/journey-tests.js +1 -1
  94. package/dist/scripts/ledger-tests.js +1 -1
  95. package/dist/scripts/ledger-workflow-crash.js +1 -1
  96. package/dist/scripts/memory-capture-tests.js +1 -1
  97. package/dist/scripts/memory-decay-tests.js +1 -1
  98. package/dist/scripts/memory-metrics.js +1 -1
  99. package/dist/scripts/memory-value-report.js +1 -1
  100. package/dist/scripts/model-override-e2e.js +176 -0
  101. package/dist/scripts/nightly-evidence-tests.js +1 -1
  102. package/dist/scripts/nightly-evidence.js +1 -1
  103. package/dist/scripts/nudge-digest.js +1 -1
  104. package/dist/scripts/onboarding-tests.js +21 -53
  105. package/dist/scripts/opensky-check.js +1 -1
  106. package/dist/scripts/opensky-tests.js +1 -1
  107. package/dist/scripts/pnpm-dsh-closure-proof.js +20 -0
  108. package/dist/scripts/price-drift-tests.js +1 -1
  109. package/dist/scripts/price-drift-watch.js +1 -1
  110. package/dist/scripts/probe-poi-tests.js +1 -1
  111. package/dist/scripts/product-metrics.js +1 -1
  112. package/dist/scripts/publish-preverify.js +40 -4
  113. package/dist/scripts/realtime-pricing-tests.js +1 -1
  114. package/dist/scripts/replay-async.js +1 -1
  115. package/dist/scripts/replay-real.js +1 -1
  116. package/dist/scripts/replay.js +1 -1
  117. package/dist/scripts/session-attach-diagnose.js +1 -1
  118. package/dist/scripts/session-attach-poc.js +1 -1
  119. package/dist/scripts/session-benchmark.js +1 -1
  120. package/dist/scripts/session-extract-tests.js +1 -1
  121. package/dist/scripts/session-login.js +1 -1
  122. package/dist/scripts/session-tests.js +70 -20
  123. package/dist/scripts/sf-live-benchmark.js +338 -0
  124. package/dist/scripts/sf-live-cli-tests.js +21 -0
  125. package/dist/scripts/sf-soft-score-tests.js +108 -0
  126. package/dist/scripts/sf-summary.js +93 -0
  127. package/dist/scripts/skeleton-check.js +1 -1
  128. package/dist/scripts/skeleton-integration-test.js +1 -1
  129. package/dist/scripts/skills-contract-tests.js +1 -1
  130. package/dist/scripts/smoke-session-gate-tests.js +29 -0
  131. package/dist/scripts/smoke.js +79 -33
  132. package/dist/scripts/state-cli-tests.js +1 -1
  133. package/dist/scripts/state-cli.js +1 -1
  134. package/dist/scripts/static-golden-tests.js +299 -0
  135. package/dist/scripts/time-eval-tests.js +1 -1
  136. package/dist/scripts/travel-timeline-tests.js +1 -1
  137. package/dist/scripts/unified-tests.js +1 -1
  138. package/dist/scripts/weather-tests.js +694 -44
  139. package/dist/scripts/z3-race-tests.js +1 -1
  140. package/dist/src/artifact-gate.js +1 -1
  141. package/dist/src/benchmark-agent-conformance.js +370 -0
  142. package/dist/src/benchmark-environment-bridge.js +384 -0
  143. package/dist/src/benchmark-headless-child-diagnostics.js +173 -0
  144. package/dist/src/benchmark-tool-isolation.js +124 -0
  145. package/dist/src/bookable-facts.js +1 -1
  146. package/dist/src/booking-saga.js +1 -1
  147. package/dist/src/booking-surface/availability-policy-v2.js +830 -0
  148. package/dist/src/booking-surface/canonical-schema.js +113 -0
  149. package/dist/src/booking-surface/contracts-v2.js +89 -0
  150. package/dist/src/booking-surface/contracts.js +46 -0
  151. package/dist/src/booking-surface/dsh-planner.js +453 -0
  152. package/dist/src/booking-surface/dsh-plugin.js +93 -0
  153. package/dist/src/booking-surface/error-codes.js +94 -0
  154. package/dist/src/booking-surface/index.js +15 -0
  155. package/dist/src/booking-surface/profile.js +68 -0
  156. package/dist/src/booking-surface/runtime-v2.js +1771 -0
  157. package/dist/src/booking-surface/runtime.js +351 -0
  158. package/dist/src/booking-surface/server-v2.js +334 -0
  159. package/dist/src/booking-surface/server.js +302 -0
  160. package/dist/src/booking-surface/startup.js +159 -0
  161. package/dist/src/booking-surface/validation-v2.js +319 -0
  162. package/dist/src/booking-surface/validation.js +809 -0
  163. package/dist/src/bridge.js +1 -1
  164. package/dist/src/companions.js +1 -1
  165. package/dist/src/contracts.js +1 -1
  166. package/dist/src/dsh-llm.js +1 -1
  167. package/dist/src/engine.js +1 -1
  168. package/dist/src/evaluation-cadence.js +234 -0
  169. package/dist/src/evaluation-contracts.js +906 -0
  170. package/dist/src/i18n.js +1 -1
  171. package/dist/src/index.js +50 -19
  172. package/dist/src/journey.js +1 -1
  173. package/dist/src/loop.js +1 -1
  174. package/dist/src/memory-capture.js +1 -1
  175. package/dist/src/memory-decay.js +1 -1
  176. package/dist/src/memory-utility.js +1 -1
  177. package/dist/src/mock-llm.js +1 -1
  178. package/dist/src/model.js +1 -1
  179. package/dist/src/realtime-pricing.js +1 -1
  180. package/dist/src/slot-spec.js +1 -1
  181. package/dist/src/state-ledger.js +2 -1
  182. package/dist/src/time-anchor.js +1 -1
  183. package/dist/src/tool-budget.js +136 -0
  184. package/dist/src/tool-packet.js +1 -1
  185. package/dist/src/travel-slots.js +1 -1
  186. package/dist/src/travel-timeline.js +1 -1
  187. package/dist/src/unified.js +1 -1
  188. package/dist/src/wish-pool.js +1 -1
  189. package/dist/src/z3-shared.js +1 -1
  190. package/extension/README.md +31 -7
  191. package/package.json +286 -11
  192. package/schemas/booking.surface.v1.schema.json +927 -0
  193. package/schemas/booking.surface.v2.schema.json +61 -0
  194. package/ts/capabilities/flyai.ts +16 -3
  195. package/ts/capabilities/session/extension-bridge.ts +37 -14
  196. package/ts/capabilities/session/extension-channel.ts +6 -3
  197. package/ts/capabilities/session/extension-distribution.ts +264 -0
  198. package/ts/capabilities/session/golden-score.ts +139 -0
  199. package/ts/capabilities/session/health-watch.ts +1 -1
  200. package/ts/capabilities/session/static-flight-golden.ts +209 -0
  201. package/ts/capabilities/session/wizard.ts +34 -176
  202. package/ts/capabilities/session-login.ts +15 -5
  203. package/ts/capabilities/session-search.ts +40 -3
  204. package/ts/capabilities/weather.ts +141 -52
  205. package/ts/package.json +3 -3
  206. package/ts/src/benchmark-agent-conformance.ts +448 -0
  207. package/ts/src/benchmark-environment-bridge.ts +348 -0
  208. package/ts/src/benchmark-headless-child-diagnostics.ts +184 -0
  209. package/ts/src/benchmark-tool-isolation.ts +166 -0
  210. package/ts/src/booking-surface/availability-policy-v2.ts +523 -0
  211. package/ts/src/booking-surface/canonical-schema.js +113 -0
  212. package/ts/src/booking-surface/contracts-v2.ts +118 -0
  213. package/ts/src/booking-surface/contracts.ts +380 -0
  214. package/ts/src/booking-surface/dsh-planner.ts +452 -0
  215. package/ts/src/booking-surface/dsh-plugin.js +93 -0
  216. package/ts/src/booking-surface/error-codes.ts +101 -0
  217. package/ts/src/booking-surface/index.ts +12 -0
  218. package/ts/src/booking-surface/profile.ts +42 -0
  219. package/ts/src/booking-surface/runtime-v2.ts +1466 -0
  220. package/ts/src/booking-surface/runtime.ts +483 -0
  221. package/ts/src/booking-surface/server-v2.ts +247 -0
  222. package/ts/src/booking-surface/server.ts +324 -0
  223. package/ts/src/booking-surface/startup.ts +196 -0
  224. package/ts/src/booking-surface/validation-v2.ts +205 -0
  225. package/ts/src/booking-surface/validation.ts +453 -0
  226. package/ts/src/index.ts +64 -11
  227. package/ts/src/state-ledger.ts +1 -0
  228. package/ts/src/tool-budget.ts +165 -0
  229. package/dist/scripts/wizard-bootstrap.js +0 -32
@@ -0,0 +1,448 @@
1
+ /** Provider-neutral execution and terminal contract for benchmark agents. */
2
+
3
+ import type { Context } from '@deepseek-ai/cordis'
4
+ import { createUserMessage } from '@deepseek-ai/dsh-llm'
5
+ import {
6
+ classifyBenchmarkTurnEnd,
7
+ createBenchmarkDiagnosticArbiter,
8
+ emitBenchmarkChildDiagnostic,
9
+ type BenchmarkChildFailureCode,
10
+ } from './benchmark-headless-child-diagnostics.ts'
11
+
12
+ export const MAX_CONFORMANCE_RETRIES = 1 as const
13
+ export const BENCHMARK_BRIDGE_CALL_REQUIRED = 'BENCHMARK_BRIDGE_CALL_REQUIRED'
14
+ export const BENCHMARK_BRIDGE_CALL_FAILED = 'BENCHMARK_BRIDGE_CALL_FAILED'
15
+ export const BENCHMARK_BRIDGE_TIMED_OUT = 'BENCHMARK_BRIDGE_TIMED_OUT'
16
+ export const BENCHMARK_BRIDGE_RUNNER_FAILED = 'BENCHMARK_BRIDGE_RUNNER_FAILED'
17
+ export const BENCHMARK_BRIDGE_SPAWN_FAILED = 'BENCHMARK_BRIDGE_SPAWN_FAILED'
18
+ export const BENCHMARK_BRIDGE_OUTPUT_TRUNCATED = 'BENCHMARK_BRIDGE_OUTPUT_TRUNCATED'
19
+ export const BENCHMARK_TERMINAL_INVALID = 'BENCHMARK_TERMINAL_INVALID'
20
+ export const BENCHMARK_BRIDGE_RETRY_CALL_NOT_ALLOWED = 'BENCHMARK_BRIDGE_RETRY_CALL_NOT_ALLOWED'
21
+ export const BENCHMARK_CONFORMANCE_STATE_UNAVAILABLE = 'BENCHMARK_CONFORMANCE_STATE_UNAVAILABLE'
22
+
23
+ const IDENTIFIER = /^[A-Za-z][A-Za-z0-9_.-]*$/
24
+ const MAX_TERMINAL_BYTES = 1024 * 1024
25
+
26
+ export interface TerminalOutputConfig {
27
+ tag: string
28
+ max_bytes: number
29
+ }
30
+
31
+ export type TerminalOutputValue =
32
+ | { ok: true; value: Record<string, unknown> }
33
+ | { ok: false; error: 'invalid_terminal_output' }
34
+
35
+ export interface BenchmarkBridgeProjection {
36
+ readonly toolName: string
37
+ readonly allowedTools: readonly string[]
38
+ readonly terminal: Readonly<TerminalOutputConfig>
39
+ }
40
+
41
+ type RetryMode = 'none' | 'call' | 'terminal'
42
+
43
+ interface TurnState {
44
+ readonly turn: number
45
+ readonly validCallIds: Set<string>
46
+ retryCount: number
47
+ retryMode: RetryMode
48
+ successfulResultStep?: number
49
+ bridgeCallFailed: boolean
50
+ bridgeFailureCode?: string
51
+ retryRedispatchAttempted: boolean
52
+ lastAssistant?: {
53
+ step: number
54
+ text: string
55
+ interrupted: boolean
56
+ }
57
+ }
58
+
59
+ export type BenchmarkConformanceDecision =
60
+ | { kind: 'accept' }
61
+ | { kind: 'steer'; mode: Exclude<RetryMode, 'none'> }
62
+ | { kind: 'reject'; code: string }
63
+
64
+ export interface BenchmarkAgentConformance {
65
+ readonly retryMode: RetryMode
66
+ readonly retryCount: number
67
+ observe(event: unknown): void
68
+ stopping(turn: number): BenchmarkConformanceDecision
69
+ guardBridgeExecution(): string | undefined
70
+ }
71
+
72
+ function plainObject(value: unknown): value is Record<string, unknown> {
73
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
74
+ }
75
+
76
+ export function validateTerminalOutputConfig(value: unknown): value is TerminalOutputConfig {
77
+ if (!plainObject(value)) return false
78
+ const keys = Object.keys(value).sort()
79
+ return JSON.stringify(keys) === JSON.stringify(['max_bytes', 'tag'])
80
+ && typeof value.tag === 'string'
81
+ && IDENTIFIER.test(value.tag)
82
+ && typeof value.max_bytes === 'number'
83
+ && Number.isInteger(value.max_bytes)
84
+ && value.max_bytes >= 1
85
+ && value.max_bytes <= MAX_TERMINAL_BYTES
86
+ }
87
+
88
+ function invalidTerminal(): TerminalOutputValue {
89
+ return { ok: false, error: 'invalid_terminal_output' }
90
+ }
91
+
92
+ /** Parse exactly one configured tag pair containing one JSON object. */
93
+ export function parseBenchmarkTerminal(raw: string, config: TerminalOutputConfig): TerminalOutputValue {
94
+ if (!validateTerminalOutputConfig(config)) return invalidTerminal()
95
+ if (Buffer.byteLength(raw, 'utf8') > config.max_bytes) return invalidTerminal()
96
+
97
+ const trimmed = raw.trim()
98
+ const opening = `<${config.tag}>`
99
+ const closing = `</${config.tag}>`
100
+ if (!trimmed.startsWith(opening) || !trimmed.endsWith(closing)) return invalidTerminal()
101
+ if (trimmed.indexOf(opening) !== trimmed.lastIndexOf(opening)
102
+ || trimmed.indexOf(closing) !== trimmed.lastIndexOf(closing)) return invalidTerminal()
103
+ const body = trimmed.slice(opening.length, -closing.length)
104
+ if (body.length === 0 || body.includes('```')) return invalidTerminal()
105
+
106
+ try {
107
+ const value: unknown = JSON.parse(body)
108
+ return plainObject(value) ? { ok: true, value } : invalidTerminal()
109
+ } catch {
110
+ return invalidTerminal()
111
+ }
112
+ }
113
+
114
+ /** Backward-compatible name used by the bridge contract tests. */
115
+ export const validateTerminalOutput = parseBenchmarkTerminal
116
+
117
+ function eventData(event: unknown): { type: string; data: Record<string, unknown> } | undefined {
118
+ if (!plainObject(event) || typeof event.type !== 'string' || !plainObject(event.data)) return undefined
119
+ return { type: event.type, data: event.data }
120
+ }
121
+
122
+ function eventTurn(data: Record<string, unknown>): number | undefined {
123
+ return typeof data.turn === 'number' && Number.isInteger(data.turn) ? data.turn : undefined
124
+ }
125
+
126
+ function parseToolArguments(value: unknown): Record<string, unknown> | undefined {
127
+ if (plainObject(value)) return value
128
+ if (typeof value !== 'string') return undefined
129
+ try {
130
+ const parsed: unknown = JSON.parse(value)
131
+ return plainObject(parsed) ? parsed : undefined
132
+ } catch {
133
+ return undefined
134
+ }
135
+ }
136
+
137
+ function assistantText(data: Record<string, unknown>): { text: string; interrupted: boolean } | undefined {
138
+ if (!plainObject(data.message) || !Array.isArray(data.message.content)) return undefined
139
+ const text = data.message.content
140
+ .filter(block => plainObject(block) && block.type === 'text' && typeof block.text === 'string')
141
+ .map(block => String((block as Record<string, unknown>).text))
142
+ .join('')
143
+ return { text, interrupted: data.interrupted === true }
144
+ }
145
+
146
+ function bridgeResultStatus(data: Record<string, unknown>, callId: string): { ok: true } | { ok: false; code: string } | undefined {
147
+ if (!plainObject(data.message) || !plainObject(data.message.source)) return undefined
148
+ if (data.message.source.callId !== callId || !Array.isArray(data.message.content)) return undefined
149
+ const block = data.message.content.find(candidate => plainObject(candidate)
150
+ && candidate.type === 'tool-result'
151
+ && candidate.toolCallId === callId)
152
+ if (!plainObject(block) || block.isError === true || !Array.isArray(block.content)) return undefined
153
+ const text = block.content
154
+ .filter(candidate => plainObject(candidate) && candidate.type === 'text' && typeof candidate.text === 'string')
155
+ .map(candidate => String((candidate as Record<string, unknown>).text))
156
+ .join('')
157
+ try {
158
+ const parsed: unknown = JSON.parse(text)
159
+ if (!plainObject(parsed)) return undefined
160
+ if (parsed.ok === true) return { ok: true }
161
+ if (parsed.ok === false && typeof parsed.error === 'string') {
162
+ const code = parsed.error === 'timed_out'
163
+ ? BENCHMARK_BRIDGE_TIMED_OUT
164
+ : parsed.error === 'runner_failed'
165
+ ? BENCHMARK_BRIDGE_RUNNER_FAILED
166
+ : parsed.error === 'spawn_failed'
167
+ ? BENCHMARK_BRIDGE_SPAWN_FAILED
168
+ : parsed.error === 'output_truncated'
169
+ ? BENCHMARK_BRIDGE_OUTPUT_TRUNCATED
170
+ : BENCHMARK_BRIDGE_CALL_FAILED
171
+ return { ok: false, code }
172
+ }
173
+ return undefined
174
+ } catch {
175
+ return undefined
176
+ }
177
+ }
178
+
179
+ export function benchmarkChildFailureForConformanceCode(code: string): BenchmarkChildFailureCode {
180
+ if (code === BENCHMARK_BRIDGE_TIMED_OUT) return 'child_bridge_timed_out'
181
+ if (code === BENCHMARK_BRIDGE_RUNNER_FAILED) return 'child_bridge_runner_failed'
182
+ if (code === BENCHMARK_BRIDGE_SPAWN_FAILED) return 'child_bridge_spawn_failed'
183
+ if (code === BENCHMARK_BRIDGE_OUTPUT_TRUNCATED) return 'child_bridge_output_truncated'
184
+ if (code === BENCHMARK_BRIDGE_CALL_FAILED) return 'child_bridge_failure'
185
+ return 'child_conformance_failure'
186
+ }
187
+
188
+ function newTurn(turn: number): TurnState {
189
+ return {
190
+ turn,
191
+ validCallIds: new Set(),
192
+ retryCount: 0,
193
+ retryMode: 'none',
194
+ bridgeCallFailed: false,
195
+ retryRedispatchAttempted: false,
196
+ }
197
+ }
198
+
199
+ /** Deterministic controller used by both runtime wiring and offline contracts. */
200
+ export function createBenchmarkAgentConformance(projection: BenchmarkBridgeProjection): BenchmarkAgentConformance {
201
+ let state: TurnState | undefined
202
+
203
+ const controller: BenchmarkAgentConformance = {
204
+ get retryMode() { return state?.retryMode ?? 'none' },
205
+ get retryCount() { return state?.retryCount ?? 0 },
206
+
207
+ observe(rawEvent: unknown): void {
208
+ const event = eventData(rawEvent)
209
+ if (!event) return
210
+ const turn = eventTurn(event.data)
211
+
212
+ if (event.type === 'turn/start' && turn !== undefined) {
213
+ state = newTurn(turn)
214
+ return
215
+ }
216
+ if (event.type === 'turn/end') {
217
+ if (state && turn === state.turn) state = undefined
218
+ return
219
+ }
220
+ if (!state || turn !== state.turn) return
221
+
222
+ if (event.type === 'tool/call') {
223
+ if (event.data.name !== projection.toolName) return
224
+ if (state.retryMode === 'terminal') {
225
+ state.retryRedispatchAttempted = true
226
+ return
227
+ }
228
+ if (typeof event.data.callId !== 'string') return
229
+ const args = parseToolArguments(event.data.arguments)
230
+ const query = args && plainObject(args.query) ? args.query : undefined
231
+ if (query?.action === 'call'
232
+ && typeof query.tool === 'string'
233
+ && projection.allowedTools.includes(query.tool)) {
234
+ state.validCallIds.add(event.data.callId)
235
+ }
236
+ return
237
+ }
238
+
239
+ if (event.type === 'tool/result') {
240
+ if (!plainObject(event.data.message) || !plainObject(event.data.message.source)) return
241
+ const callId = event.data.message.source.callId
242
+ if (typeof callId !== 'string' || !state.validCallIds.has(callId)) return
243
+ const resultStatus = bridgeResultStatus(event.data, callId)
244
+ if (resultStatus?.ok === true) {
245
+ state.successfulResultStep = typeof event.data.step === 'number'
246
+ ? event.data.step
247
+ : state.successfulResultStep
248
+ } else {
249
+ state.bridgeCallFailed = true
250
+ state.bridgeFailureCode = resultStatus?.code ?? BENCHMARK_BRIDGE_CALL_FAILED
251
+ }
252
+ return
253
+ }
254
+
255
+ if (event.type === 'assistant/message') {
256
+ const assistant = assistantText(event.data)
257
+ if (!assistant || typeof event.data.step !== 'number') return
258
+ state.lastAssistant = { step: event.data.step, ...assistant }
259
+ }
260
+ },
261
+
262
+ stopping(turn: number): BenchmarkConformanceDecision {
263
+ if (!state || state.turn !== turn) {
264
+ return { kind: 'reject', code: BENCHMARK_CONFORMANCE_STATE_UNAVAILABLE }
265
+ }
266
+ if (state.retryRedispatchAttempted) {
267
+ return { kind: 'reject', code: BENCHMARK_BRIDGE_RETRY_CALL_NOT_ALLOWED }
268
+ }
269
+ if (state.successfulResultStep === undefined) {
270
+ if (state.bridgeCallFailed) {
271
+ return { kind: 'reject', code: state.bridgeFailureCode ?? BENCHMARK_BRIDGE_CALL_FAILED }
272
+ }
273
+ if (state.retryCount >= MAX_CONFORMANCE_RETRIES) {
274
+ return { kind: 'reject', code: BENCHMARK_BRIDGE_CALL_REQUIRED }
275
+ }
276
+ state.retryCount += 1
277
+ state.retryMode = 'call'
278
+ return { kind: 'steer', mode: 'call' }
279
+ }
280
+
281
+ const terminal = state.lastAssistant
282
+ const terminalIsValid = terminal !== undefined
283
+ && !terminal.interrupted
284
+ && terminal.step > state.successfulResultStep
285
+ && parseBenchmarkTerminal(terminal.text, projection.terminal).ok
286
+ if (terminalIsValid) return { kind: 'accept' }
287
+ if (state.retryCount >= MAX_CONFORMANCE_RETRIES) {
288
+ return { kind: 'reject', code: BENCHMARK_TERMINAL_INVALID }
289
+ }
290
+ state.retryCount += 1
291
+ state.retryMode = 'terminal'
292
+ return { kind: 'steer', mode: 'terminal' }
293
+ },
294
+
295
+ guardBridgeExecution(): string | undefined {
296
+ return state?.retryMode === 'terminal'
297
+ ? BENCHMARK_BRIDGE_RETRY_CALL_NOT_ALLOWED
298
+ : undefined
299
+ },
300
+ }
301
+ return controller
302
+ }
303
+
304
+ type Disposer = () => void | Promise<void>
305
+ type ScopedAgent = {
306
+ id?: unknown
307
+ session?: object
308
+ steer?: (message: unknown) => void
309
+ ctx?: {
310
+ tools?: { guard?: (check: (execution: { name: string }) => string | undefined) => unknown }
311
+ effect?: (action: () => unknown, label?: string) => unknown
312
+ on?: (event: string, listener: (...args: any[]) => unknown, options?: { prepend?: boolean }) => unknown
313
+ }
314
+ }
315
+ type EventBus = {
316
+ on?: (event: string, listener: (...args: any[]) => unknown, options?: { prepend?: boolean }) => unknown
317
+ }
318
+
319
+ function requireDisposer(value: unknown, capability: string): Disposer {
320
+ if (typeof value !== 'function') throw new Error(`benchmark conformance ${capability} disposer unavailable`)
321
+ return value as Disposer
322
+ }
323
+
324
+ function correctionMessage(mode: Exclude<RetryMode, 'none'>, projection: BenchmarkBridgeProjection) {
325
+ const text = mode === 'call'
326
+ ? `BENCHMARK_CONFORMANCE_CALL: Execute exactly one native ${projection.toolName} action:"call" now. Describing an intended CLI, shell, or Python command does not execute it.`
327
+ : `BENCHMARK_CONFORMANCE_TERMINAL: Reuse the existing successful tool result. Do not call any tool. Reply only <${projection.terminal.tag}>{"result":"..."}</${projection.terminal.tag}> with one JSON object.`
328
+ return createUserMessage({
329
+ content: [{ type: 'text' as const, text }],
330
+ source: { kind: 'plugin' as const, plugin: 'gotry-benchmark-agent-conformance' },
331
+ })
332
+ }
333
+
334
+ function systemSection(projection: BenchmarkBridgeProjection): { name: string; text: string } {
335
+ const allowed = projection.allowedTools.join(', ')
336
+ return {
337
+ name: 'benchmark:agent-conformance',
338
+ text: [
339
+ 'Benchmark execution contract:',
340
+ `- Translate every task instruction to use a CLI, shell, Python, or agent_env.cli into the native tool ${projection.toolName}; do not merely describe the intended command.`,
341
+ `- Call it with exactly {"query":{"action":"call","tool":"<one of: ${allowed}>","arguments":{...}}}.`,
342
+ '- action:"tools" is discovery only and does not satisfy the required environment call.',
343
+ `- After a successful tool result, reply only <${projection.terminal.tag}>{...one JSON object...}</${projection.terminal.tag}> with no prose or code fence.`,
344
+ '- If a terminal-format correction arrives, reuse the existing result and do not call the tool again.',
345
+ ].join('\n'),
346
+ }
347
+ }
348
+
349
+ /** Install conformance only after the exact benchmark bridge isolation layer. */
350
+ export function installBenchmarkAgentConformance(
351
+ ctx: Context,
352
+ projection: BenchmarkBridgeProjection,
353
+ diagnosticWriter: (code: BenchmarkChildFailureCode) => void = emitBenchmarkChildDiagnostic,
354
+ ): void {
355
+ const bus = ctx as unknown as EventBus
356
+ if (typeof bus.on !== 'function') throw new Error('benchmark conformance event bus unavailable')
357
+
358
+ const byAgent = new WeakMap<object, BenchmarkAgentConformance>()
359
+ const bySession = new WeakMap<object, BenchmarkAgentConformance>()
360
+ const sessionKeys = new WeakMap<object, string>()
361
+ let sessionOrdinal = 0
362
+ const diagnostics = createBenchmarkDiagnosticArbiter(diagnosticWriter)
363
+
364
+ bus.on('agent/created', (payload: { agent?: ScopedAgent }) => {
365
+ const agent = payload.agent
366
+ if (!agent || typeof agent !== 'object' || !agent.session) {
367
+ throw new Error('benchmark conformance created agent unavailable')
368
+ }
369
+ if (typeof agent.steer !== 'function') throw new Error('benchmark conformance steering unavailable')
370
+ if (typeof agent.ctx?.tools?.guard !== 'function') throw new Error('benchmark conformance scoped guard unavailable')
371
+ if (typeof agent.ctx.effect !== 'function') throw new Error('benchmark conformance scoped effect unavailable')
372
+ if (typeof agent.ctx.on !== 'function') throw new Error('benchmark conformance scoped event bus unavailable')
373
+
374
+ const controller = createBenchmarkAgentConformance(projection)
375
+ byAgent.set(agent, controller)
376
+ bySession.set(agent.session, controller)
377
+ sessionKeys.set(agent.session, `session-${++sessionOrdinal}`)
378
+ try {
379
+ requireDisposer(agent.ctx.effect.call(agent.ctx, function* () {
380
+ yield requireDisposer(agent.ctx!.tools!.guard!(execution => {
381
+ if (execution.name !== projection.toolName) return undefined
382
+ return controller.guardBridgeExecution()
383
+ }), 'scoped guard')
384
+ yield requireDisposer(agent.ctx!.on!.call(agent.ctx, 'system-prompt/assemble', async (
385
+ _assembly: unknown,
386
+ _context: unknown,
387
+ next?: () => Promise<unknown>,
388
+ ) => {
389
+ if (typeof next !== 'function') throw new Error('benchmark conformance assembly continuation unavailable')
390
+ const result = await next()
391
+ if (!plainObject(result)) throw new Error('benchmark conformance assembly result unavailable')
392
+ const sections = Array.isArray(result.sections) ? result.sections : []
393
+ return { ...result, sections: [...sections, systemSection(projection)] }
394
+ }, { prepend: true }), 'scoped assembly listener')
395
+ }, 'benchmark-agent-conformance'), 'scoped effect')
396
+ } catch (error) {
397
+ byAgent.delete(agent)
398
+ bySession.delete(agent.session)
399
+ throw error
400
+ }
401
+ })
402
+
403
+ bus.on('session/event', (session: object, event: unknown) => {
404
+ bySession.get(session)?.observe(event)
405
+ if (typeof event === 'object' && event !== null && (event as { type?: unknown }).type === 'turn/end') {
406
+ const key = sessionKeys.get(session)
407
+ if (key !== undefined) {
408
+ diagnostics.offer(key, classifyBenchmarkTurnEnd((event as { data?: { reason?: unknown } }).data?.reason))
409
+ diagnostics.flush(key)
410
+ }
411
+ }
412
+ })
413
+ bus.on('session/disposed', (session: object) => {
414
+ const key = sessionKeys.get(session)
415
+ if (key !== undefined) diagnostics.flush(key)
416
+ sessionKeys.delete(session)
417
+ bySession.delete(session)
418
+ })
419
+ bus.on('agent/disposed', (payload: { agent?: ScopedAgent }) => {
420
+ const agent = payload.agent
421
+ if (!agent || typeof agent !== 'object') return
422
+ byAgent.delete(agent)
423
+ if (agent.session) bySession.delete(agent.session)
424
+ })
425
+ bus.on('agent/turn-stopping', (payload: { agent?: ScopedAgent; session?: object; turn?: number }) => {
426
+ const agent = payload.agent
427
+ const session = agent?.session ?? payload.session
428
+ const key = session && typeof session === 'object' ? sessionKeys.get(session) : undefined
429
+ if (!agent || typeof agent !== 'object' || typeof payload.turn !== 'number') {
430
+ if (key !== undefined) diagnostics.offer(key, 'child_conformance_failure')
431
+ else diagnosticWriter('child_conformance_failure')
432
+ throw new Error(BENCHMARK_CONFORMANCE_STATE_UNAVAILABLE)
433
+ }
434
+ const controller = byAgent.get(agent)
435
+ if (!controller) {
436
+ if (key !== undefined) diagnostics.offer(key, 'child_conformance_failure')
437
+ else diagnosticWriter('child_conformance_failure')
438
+ throw new Error(BENCHMARK_CONFORMANCE_STATE_UNAVAILABLE)
439
+ }
440
+ const decision = controller.stopping(payload.turn)
441
+ if (decision.kind === 'reject') {
442
+ if (key !== undefined) diagnostics.offer(key, benchmarkChildFailureForConformanceCode(decision.code))
443
+ else diagnosticWriter(benchmarkChildFailureForConformanceCode(decision.code))
444
+ throw new Error(decision.code)
445
+ }
446
+ if (decision.kind === 'steer') agent.steer!(correctionMessage(decision.mode, projection))
447
+ }, { prepend: true })
448
+ }