@knights-eye-chess/ai-analysis 0.0.0-stage → 0.1.0-dev.14

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 (258) hide show
  1. package/LICENSE +235 -0
  2. package/LICENSING.md +26 -0
  3. package/NOTICE +5 -0
  4. package/NPM-PUBLISHING.md +24 -0
  5. package/README.md +141 -2
  6. package/SOURCE-ORIGIN.json +16 -0
  7. package/THIRD_PARTY_NOTICES.md +18 -0
  8. package/build.mjs +22 -0
  9. package/dist/answer-pipeline.test.mjs +375 -0
  10. package/dist/chunk-PLKNJRPF.js +10662 -0
  11. package/dist/chunk-XQDZJOYD.js +2515 -0
  12. package/dist/index.js +146 -0
  13. package/dist/owner-tests/chess-reasoning-compact-search-preparation.test.mjs +963 -0
  14. package/dist/owner-tests/mechanism-encoding.test.mjs +529 -0
  15. package/dist/owner-tests/move-mechanism-facts.test.mjs +396 -0
  16. package/dist/owner-tests/pipeline-host-preparation.test.mjs +10556 -0
  17. package/dist/owner-tests/position-preparation.test.mjs +625 -0
  18. package/dist/owner-tests/preparation-consolidation.test.mjs +1052 -0
  19. package/dist/owner-tests/prose-reference-admission.test.mjs +1770 -0
  20. package/dist/owner-tests/score-comparison-notices.test.mjs +240 -0
  21. package/dist/owner-tests/simple-engine-presentation.test.mjs +233 -0
  22. package/dist/owner-tests/tool-input-loop-guard.test.mjs +78 -0
  23. package/dist/research.js +2274 -0
  24. package/dist/runtime-closure.json +103 -0
  25. package/dist/shared-runtime-closure.json +39 -0
  26. package/dist/shared.js +152 -0
  27. package/dist/types/ai-request-failure.d.ts +14 -0
  28. package/dist/types/ai-request-limits.d.ts +4 -0
  29. package/dist/types/ai-routing-diagnostics.d.ts +14 -0
  30. package/dist/types/chess-reasoning/ablation-adaptive-evidence-loop.d.ts +127 -0
  31. package/dist/types/chess-reasoning/ablation-adaptive-runtime.d.ts +178 -0
  32. package/dist/types/chess-reasoning/ablation-direct-synthesis.d.ts +1030 -0
  33. package/dist/types/chess-reasoning/ablation-evidence-bundle.d.ts +185 -0
  34. package/dist/types/chess-reasoning/ablation-evidence-capture.d.ts +37 -0
  35. package/dist/types/chess-reasoning/ablation-lean-direct-runtime.d.ts +193 -0
  36. package/dist/types/chess-reasoning/ablation-model-facing-evidence.d.ts +38 -0
  37. package/dist/types/chess-reasoning/ablation-transport-correction.d.ts +13 -0
  38. package/dist/types/chess-reasoning/ai-sdk-runtime-support.d.ts +93 -0
  39. package/dist/types/chess-reasoning/answer-host-contracts.d.ts +59 -0
  40. package/dist/types/chess-reasoning/answer-model-connector.d.ts +68 -0
  41. package/dist/types/chess-reasoning/answer-pipeline-exports.d.ts +98 -0
  42. package/dist/types/chess-reasoning/answer-pipeline.d.ts +41 -0
  43. package/dist/types/chess-reasoning/answer-reference-validation.d.ts +40 -0
  44. package/dist/types/chess-reasoning/answer-tool-host.d.ts +8 -0
  45. package/dist/types/chess-reasoning/branch-expansion-policy.d.ts +13 -0
  46. package/dist/types/chess-reasoning/branch-expansion.d.ts +39 -0
  47. package/dist/types/chess-reasoning/causal-claim-checks.d.ts +21 -0
  48. package/dist/types/chess-reasoning/chess-reference-dictionary.d.ts +13 -0
  49. package/dist/types/chess-reasoning/classification-question-target.d.ts +22 -0
  50. package/dist/types/chess-reasoning/classification-reassessment.d.ts +31 -0
  51. package/dist/types/chess-reasoning/compact-search-preparation.d.ts +7 -0
  52. package/dist/types/chess-reasoning/concept-registry.d.ts +99 -0
  53. package/dist/types/chess-reasoning/conversation-context.d.ts +12 -0
  54. package/dist/types/chess-reasoning/engine-search-failure.d.ts +7 -0
  55. package/dist/types/chess-reasoning/evidence-citation-normalization.d.ts +9 -0
  56. package/dist/types/chess-reasoning/evidence-licenses.d.ts +57 -0
  57. package/dist/types/chess-reasoning/evidence-selector-contract.d.ts +5 -0
  58. package/dist/types/chess-reasoning/existing-analysis-context.d.ts +104 -0
  59. package/dist/types/chess-reasoning/fact-observation-provider.d.ts +15 -0
  60. package/dist/types/chess-reasoning/fact-provider.d.ts +111 -0
  61. package/dist/types/chess-reasoning/fresh-engine-pv-witnesses.d.ts +67 -0
  62. package/dist/types/chess-reasoning/historical-prose.d.ts +23 -0
  63. package/dist/types/chess-reasoning/idea-graph.d.ts +34 -0
  64. package/dist/types/chess-reasoning/initial-search-plan.d.ts +37 -0
  65. package/dist/types/chess-reasoning/lossless-evidence-sharing.d.ts +18 -0
  66. package/dist/types/chess-reasoning/matched-comparison.d.ts +10 -0
  67. package/dist/types/chess-reasoning/material-accounting.d.ts +80 -0
  68. package/dist/types/chess-reasoning/material-format.d.ts +4 -0
  69. package/dist/types/chess-reasoning/mechanical-fact-provider.d.ts +33 -0
  70. package/dist/types/chess-reasoning/mechanical-ray-facts.d.ts +19 -0
  71. package/dist/types/chess-reasoning/mechanism-presentation.d.ts +9 -0
  72. package/dist/types/chess-reasoning/move-mechanism-facts.d.ts +45 -0
  73. package/dist/types/chess-reasoning/native-answer-connector.d.ts +4 -0
  74. package/dist/types/chess-reasoning/opening-source-contracts.d.ts +54 -0
  75. package/dist/types/chess-reasoning/opening-source-credits.d.ts +16 -0
  76. package/dist/types/chess-reasoning/opponent-threat-preparation.d.ts +7 -0
  77. package/dist/types/chess-reasoning/piece-identities.d.ts +11 -0
  78. package/dist/types/chess-reasoning/poc-contracts.d.ts +1026 -0
  79. package/dist/types/chess-reasoning/poc-hypotheses.d.ts +74 -0
  80. package/dist/types/chess-reasoning/poc-move-witnesses.d.ts +13 -0
  81. package/dist/types/chess-reasoning/poc-observations.d.ts +23 -0
  82. package/dist/types/chess-reasoning/poc-piece-refs.d.ts +12 -0
  83. package/dist/types/chess-reasoning/poc-plan-model.d.ts +45 -0
  84. package/dist/types/chess-reasoning/poc-semantic-text.d.ts +8 -0
  85. package/dist/types/chess-reasoning/poc-tools.d.ts +81 -0
  86. package/dist/types/chess-reasoning/portable-answer-runtime.d.ts +291 -0
  87. package/dist/types/chess-reasoning/position-analysis-contracts.d.ts +31 -0
  88. package/dist/types/chess-reasoning/position-analysis-scope.d.ts +3 -0
  89. package/dist/types/chess-reasoning/preparation-consolidation.d.ts +21 -0
  90. package/dist/types/chess-reasoning/production-observation-provider.d.ts +16 -0
  91. package/dist/types/chess-reasoning/question-routing.d.ts +326 -0
  92. package/dist/types/chess-reasoning/recorded-main-line.d.ts +37 -0
  93. package/dist/types/chess-reasoning/recorded-position-tools.d.ts +11 -0
  94. package/dist/types/chess-reasoning/recorded-reference-context.d.ts +13 -0
  95. package/dist/types/chess-reasoning/recorded-selected-classification.d.ts +36 -0
  96. package/dist/types/chess-reasoning/reference-limits.d.ts +2 -0
  97. package/dist/types/chess-reasoning/research-exports.d.ts +197 -0
  98. package/dist/types/chess-reasoning/saved-score-presentation.d.ts +14 -0
  99. package/dist/types/chess-reasoning/score-comparison-notices.d.ts +33 -0
  100. package/dist/types/chess-reasoning/server-simple-policy.d.ts +31 -0
  101. package/dist/types/chess-reasoning/simple-agent-config.d.ts +73 -0
  102. package/dist/types/chess-reasoning/simple-board-analysis.d.ts +85 -0
  103. package/dist/types/chess-reasoning/simple-compact-evidence.d.ts +7 -0
  104. package/dist/types/chess-reasoning/simple-completion.d.ts +23 -0
  105. package/dist/types/chess-reasoning/simple-engine-presentation.d.ts +3 -0
  106. package/dist/types/chess-reasoning/simple-evidence-preparation.d.ts +17 -0
  107. package/dist/types/chess-reasoning/simple-evidence-view.d.ts +17 -0
  108. package/dist/types/chess-reasoning/simple-explanation-coverage.d.ts +90 -0
  109. package/dist/types/chess-reasoning/simple-fact-delivery.d.ts +43 -0
  110. package/dist/types/chess-reasoning/simple-fallback-premise.d.ts +5 -0
  111. package/dist/types/chess-reasoning/simple-prose-references.d.ts +108 -0
  112. package/dist/types/chess-reasoning/simple-runtime-version.d.ts +1 -0
  113. package/dist/types/chess-reasoning/stable.d.ts +2 -0
  114. package/dist/types/chess-reasoning/tool-input-loop-guard.d.ts +5 -0
  115. package/dist/types/chess-reasoning/types.d.ts +180 -0
  116. package/dist/types/chess-reasoning/visible-support-lines.d.ts +12 -0
  117. package/dist/types/chess-reasoning/wikibooks-index.d.ts +30 -0
  118. package/dist/types/chess-reasoning/wikibooks-tool-context.d.ts +10 -0
  119. package/dist/types/player-perspective.d.ts +16 -0
  120. package/dist/types/shared-exports.d.ts +22 -0
  121. package/docs/API.md +82 -0
  122. package/docs/OWNERSHIP-ADOPTION.md +35 -0
  123. package/docs/OWNERSHIP-DRIFT.json +55 -0
  124. package/docs/RESEARCH-API.md +28 -0
  125. package/licenses/third-party/INVENTORY.json +202 -0
  126. package/licenses/third-party/ai-7.0.85/LICENSE +13 -0
  127. package/licenses/third-party/ai-sdk--gateway-4.0.69/LICENSE +13 -0
  128. package/licenses/third-party/ai-sdk--provider-4.0.9/LICENSE +13 -0
  129. package/licenses/third-party/ai-sdk--provider-utils-5.0.34/APACHE-2.0.txt +73 -0
  130. package/licenses/third-party/ai-sdk--provider-utils-5.0.34/src/to-json-schema/zod3-to-json-schema/LICENSE +16 -0
  131. package/licenses/third-party/chess.js-1.4.0/LICENSE +23 -0
  132. package/licenses/third-party/eventsource-parser-3.1.1/LICENSE +21 -0
  133. package/licenses/third-party/json-schema-0.4.0/LICENSE +195 -0
  134. package/licenses/third-party/standard-schema--spec-1.1.0/LICENSE +21 -0
  135. package/licenses/third-party/types--json-schema-7.0.15/LICENSE +21 -0
  136. package/licenses/third-party/types--node-22.19.19/LICENSE +21 -0
  137. package/licenses/third-party/undici-7.30.0/LICENSE +21 -0
  138. package/licenses/third-party/undici-7.30.0/lib/web/fetch/LICENSE +21 -0
  139. package/licenses/third-party/undici-types-6.21.0/LICENSE +21 -0
  140. package/licenses/third-party/vercel--oidc-3.2.0/LICENSE +202 -0
  141. package/licenses/third-party/workflow--serde-4.1.0/APACHE-2.0.txt +73 -0
  142. package/licenses/third-party/workflow--serde-4.1.0/LICENSE.md +3 -0
  143. package/licenses/third-party/zod-4.6.5/LICENSE +21 -0
  144. package/npm-release.json +5 -0
  145. package/package.json +72 -4
  146. package/scripts/check-release-tooling.mjs +22 -0
  147. package/scripts/pack.mjs +68 -0
  148. package/scripts/publish-reviewed.mjs +72 -0
  149. package/scripts/release-tooling.json +13 -0
  150. package/scripts/update-dependency.mjs +44 -0
  151. package/scripts/verify-release.mjs +52 -0
  152. package/src/ai-request-failure.ts +34 -0
  153. package/src/ai-request-limits.ts +4 -0
  154. package/src/ai-routing-diagnostics.ts +33 -0
  155. package/src/chess-reasoning/ablation-adaptive-evidence-loop.ts +515 -0
  156. package/src/chess-reasoning/ablation-adaptive-runtime.ts +924 -0
  157. package/src/chess-reasoning/ablation-direct-synthesis.ts +1128 -0
  158. package/src/chess-reasoning/ablation-evidence-bundle.ts +726 -0
  159. package/src/chess-reasoning/ablation-evidence-capture.ts +513 -0
  160. package/src/chess-reasoning/ablation-lean-direct-runtime.ts +670 -0
  161. package/src/chess-reasoning/ablation-model-facing-evidence.ts +212 -0
  162. package/src/chess-reasoning/ablation-transport-correction.ts +106 -0
  163. package/src/chess-reasoning/ai-sdk-runtime-support.ts +381 -0
  164. package/src/chess-reasoning/answer-host-contracts.ts +10 -0
  165. package/src/chess-reasoning/answer-model-connector.ts +83 -0
  166. package/src/chess-reasoning/answer-pipeline-exports.ts +98 -0
  167. package/src/chess-reasoning/answer-pipeline.ts +195 -0
  168. package/src/chess-reasoning/answer-reference-validation.ts +124 -0
  169. package/src/chess-reasoning/answer-tool-host.ts +10 -0
  170. package/src/chess-reasoning/branch-expansion-policy.ts +32 -0
  171. package/src/chess-reasoning/branch-expansion.ts +80 -0
  172. package/src/chess-reasoning/causal-claim-checks.ts +256 -0
  173. package/src/chess-reasoning/chess-reference-dictionary.ts +21 -0
  174. package/src/chess-reasoning/classification-question-target.ts +30 -0
  175. package/src/chess-reasoning/classification-reassessment.ts +34 -0
  176. package/src/chess-reasoning/compact-search-preparation.ts +125 -0
  177. package/src/chess-reasoning/concept-registry.ts +275 -0
  178. package/src/chess-reasoning/conversation-context.ts +29 -0
  179. package/src/chess-reasoning/engine-search-failure.ts +11 -0
  180. package/src/chess-reasoning/evidence-citation-normalization.ts +15 -0
  181. package/src/chess-reasoning/evidence-licenses.ts +166 -0
  182. package/src/chess-reasoning/evidence-selector-contract.ts +5 -0
  183. package/src/chess-reasoning/existing-analysis-context.ts +544 -0
  184. package/src/chess-reasoning/fact-observation-provider.ts +134 -0
  185. package/src/chess-reasoning/fact-provider.ts +250 -0
  186. package/src/chess-reasoning/fresh-engine-pv-witnesses.ts +128 -0
  187. package/src/chess-reasoning/historical-prose.ts +116 -0
  188. package/src/chess-reasoning/idea-graph.ts +224 -0
  189. package/src/chess-reasoning/initial-search-plan.ts +115 -0
  190. package/src/chess-reasoning/lossless-evidence-sharing.ts +135 -0
  191. package/src/chess-reasoning/matched-comparison.ts +40 -0
  192. package/src/chess-reasoning/material-accounting.ts +55 -0
  193. package/src/chess-reasoning/material-format.ts +47 -0
  194. package/src/chess-reasoning/mechanical-fact-provider.ts +1602 -0
  195. package/src/chess-reasoning/mechanical-ray-facts.ts +123 -0
  196. package/src/chess-reasoning/mechanism-presentation.ts +94 -0
  197. package/src/chess-reasoning/move-mechanism-facts.ts +185 -0
  198. package/src/chess-reasoning/native-answer-connector.ts +13 -0
  199. package/src/chess-reasoning/opening-source-contracts.ts +47 -0
  200. package/src/chess-reasoning/opening-source-credits.ts +53 -0
  201. package/src/chess-reasoning/opponent-threat-preparation.ts +98 -0
  202. package/src/chess-reasoning/piece-identities.ts +159 -0
  203. package/src/chess-reasoning/poc-contracts.ts +1097 -0
  204. package/src/chess-reasoning/poc-hypotheses.ts +759 -0
  205. package/src/chess-reasoning/poc-move-witnesses.ts +170 -0
  206. package/src/chess-reasoning/poc-observations.ts +611 -0
  207. package/src/chess-reasoning/poc-piece-refs.ts +62 -0
  208. package/src/chess-reasoning/poc-plan-model.ts +345 -0
  209. package/src/chess-reasoning/poc-semantic-text.ts +10 -0
  210. package/src/chess-reasoning/poc-tools.ts +978 -0
  211. package/src/chess-reasoning/portable-answer-runtime.ts +684 -0
  212. package/src/chess-reasoning/position-analysis-contracts.ts +88 -0
  213. package/src/chess-reasoning/position-analysis-scope.ts +20 -0
  214. package/src/chess-reasoning/preparation-consolidation.ts +91 -0
  215. package/src/chess-reasoning/production-observation-provider.ts +41 -0
  216. package/src/chess-reasoning/question-routing.ts +332 -0
  217. package/src/chess-reasoning/recorded-main-line.ts +55 -0
  218. package/src/chess-reasoning/recorded-position-tools.ts +78 -0
  219. package/src/chess-reasoning/recorded-reference-context.ts +44 -0
  220. package/src/chess-reasoning/recorded-selected-classification.ts +54 -0
  221. package/src/chess-reasoning/reference-limits.ts +2 -0
  222. package/src/chess-reasoning/research-exports.ts +197 -0
  223. package/src/chess-reasoning/saved-score-presentation.ts +6 -0
  224. package/src/chess-reasoning/score-comparison-notices.ts +115 -0
  225. package/src/chess-reasoning/server-simple-policy.ts +75 -0
  226. package/src/chess-reasoning/simple-agent-config.ts +58 -0
  227. package/src/chess-reasoning/simple-board-analysis.ts +57 -0
  228. package/src/chess-reasoning/simple-compact-evidence.ts +79 -0
  229. package/src/chess-reasoning/simple-completion.ts +37 -0
  230. package/src/chess-reasoning/simple-engine-presentation.ts +95 -0
  231. package/src/chess-reasoning/simple-evidence-preparation.ts +32 -0
  232. package/src/chess-reasoning/simple-evidence-view.ts +69 -0
  233. package/src/chess-reasoning/simple-explanation-coverage.ts +118 -0
  234. package/src/chess-reasoning/simple-fact-delivery.ts +52 -0
  235. package/src/chess-reasoning/simple-fallback-premise.ts +65 -0
  236. package/src/chess-reasoning/simple-prose-references.ts +528 -0
  237. package/src/chess-reasoning/simple-runtime-version.ts +2 -0
  238. package/src/chess-reasoning/stable.ts +18 -0
  239. package/src/chess-reasoning/tool-input-loop-guard.ts +38 -0
  240. package/src/chess-reasoning/types.ts +195 -0
  241. package/src/chess-reasoning/visible-support-lines.ts +44 -0
  242. package/src/chess-reasoning/wikibooks-index.ts +56 -0
  243. package/src/chess-reasoning/wikibooks-tool-context.ts +91 -0
  244. package/src/player-perspective.ts +41 -0
  245. package/src/shared-exports.ts +23 -0
  246. package/test/answer-pipeline.test.mjs +375 -0
  247. package/test/owner/chess-reasoning-compact-search-preparation.test.mjs +111 -0
  248. package/test/owner/mechanism-encoding.test.mjs +78 -0
  249. package/test/owner/move-mechanism-facts.test.mjs +105 -0
  250. package/test/owner/pipeline-host-preparation.test.mjs +115 -0
  251. package/test/owner/position-preparation.test.mjs +22 -0
  252. package/test/owner/preparation-consolidation.test.mjs +74 -0
  253. package/test/owner/prose-reference-admission.test.mjs +26 -0
  254. package/test/owner/score-comparison-notices.test.mjs +116 -0
  255. package/test/owner/simple-engine-presentation.test.mjs +50 -0
  256. package/test/owner/tool-input-loop-guard.test.mjs +25 -0
  257. package/test-types.mts +23 -0
  258. package/tsconfig.json +22 -0
@@ -0,0 +1,625 @@
1
+ // test/owner/position-preparation.test.mjs
2
+ import test from "node:test";
3
+ import assert from "node:assert/strict";
4
+ import { Chess as Chess13 } from "chess.js";
5
+
6
+ // src/chess-reasoning/initial-search-plan.ts
7
+ import { Chess as Chess12 } from "chess.js";
8
+
9
+ // src/chess-reasoning/saved-score-presentation.ts
10
+ function savedScorePresentation(a) {
11
+ const finiteCp = (cp, mate) => mate !== null || cp !== null && Math.abs(cp) >= 1e5 ? null : cp;
12
+ const beforeCp = finiteCp(a.beforeCp, a.mateBefore), afterCp = finiteCp(a.afterCp, a.mateAfter);
13
+ return { beforeCp, afterCp, lossCp: a.mateBefore !== null || a.mateAfter !== null || beforeCp === null || afterCp === null || a.lossCp === 9999 ? null : a.lossCp, mateBefore: a.mateBefore, mateAfter: a.mateAfter };
14
+ }
15
+
16
+ // src/chess-reasoning/recorded-main-line.ts
17
+ import { Chess as Chess6 } from "chess.js";
18
+
19
+ // src/chess-reasoning/material-accounting.ts
20
+ import { Chess } from "chess.js";
21
+
22
+ // src/chess-reasoning/poc-contracts.ts
23
+ import { Chess as Chess5 } from "chess.js";
24
+
25
+ // src/chess-reasoning/poc-piece-refs.ts
26
+ import { Chess as Chess3, SQUARES as SQUARES2 } from "chess.js";
27
+
28
+ // src/chess-reasoning/piece-identities.ts
29
+ import { Chess as Chess2, SQUARES } from "chess.js";
30
+
31
+ // src/chess-reasoning/move-mechanism-facts.ts
32
+ import { Chess as Chess4, SQUARES as SQUARES3 } from "chess.js";
33
+
34
+ // src/chess-reasoning/evidence-licenses.ts
35
+ var EVIDENCE_LICENSE = Object.freeze({
36
+ CHESS_LEGALITY: "chess.legality",
37
+ CHESS_IDENTITY: "chess.identity",
38
+ CHESS_POSITION_FACT: "chess.position-fact",
39
+ ENGINE_BOUNDED_CONTINUATION: "engine.bounded-continuation",
40
+ ENGINE_BOUNDED_COMPARISON: "engine.bounded-comparison",
41
+ ENGINE_BOUNDED_SCORE: "engine.bounded-score",
42
+ ENGINE_BOUNDED_RESPONSE_COVERAGE: "engine.bounded-response-coverage",
43
+ COVERAGE_EXHAUSTIVE: "coverage.exhaustive",
44
+ ATTENTION_AFFORDANCE: "attention.affordance",
45
+ SEMANTIC_REVIEWED_STATE: "semantic.reviewed-state",
46
+ WORKFLOW_AUDIT: "workflow.audit"
47
+ });
48
+ var LICENSES = new Set(Object.values(EVIDENCE_LICENSE));
49
+
50
+ // src/chess-reasoning/stable.ts
51
+ function stableHash(value) {
52
+ const text = stableJson(value);
53
+ let hash = 2166136261;
54
+ for (let index = 0; index < text.length; index += 1) {
55
+ hash ^= text.charCodeAt(index);
56
+ hash = Math.imul(hash, 16777619) >>> 0;
57
+ }
58
+ return hash.toString(16).padStart(8, "0");
59
+ }
60
+ function stableJson(value) {
61
+ if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
62
+ if (value && typeof value === "object") {
63
+ const record = value;
64
+ return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`).join(",")}}`;
65
+ }
66
+ return JSON.stringify(value);
67
+ }
68
+
69
+ // src/chess-reasoning/poc-contracts.ts
70
+ var REASONING_POC_VERSION = "conceptual-explanation-poc/57";
71
+ var DEFAULT_REASONING_RUN_CONTROLS = Object.freeze({
72
+ maxModelSteps: 15,
73
+ maxToolCalls: 16,
74
+ maxProbeCalls: 5,
75
+ maxEvidenceRecords: 48,
76
+ maxObservationRecords: 48,
77
+ maxObservationsPresented: 16,
78
+ maxHypotheses: 16,
79
+ maxOutputChars: 2400,
80
+ maxProviderOutputChars: 64e3,
81
+ maxWallTimeMs: 3e4
82
+ });
83
+ var POSITION_CONTEXT_KEYS = /* @__PURE__ */ new Set(["kind", "nodeId", "parentNodeId", "historyStartFen", "fenBefore", "fenAfter", "historyUci", "moveUci", "moveSan"]);
84
+ function validateReasoningPositionContext(value) {
85
+ if (!value || typeof value !== "object") throw new Error("Reasoning position context must be an object");
86
+ for (const key of Object.keys(value)) if (!POSITION_CONTEXT_KEYS.has(key)) throw new Error(`Unsupported reasoning position context field: ${key}`);
87
+ if (!value.nodeId?.trim()) throw new Error("Reasoning position context requires nodeId");
88
+ if (!Array.isArray(value.historyUci) || value.historyUci.some((move) => !/^[a-h][1-8][a-h][1-8][qrbn]?$/.test(move))) throw new Error("Reasoning position context historyUci must contain UCI moves");
89
+ if (value.kind !== void 0 && value.kind !== "position") throw new Error("Invalid context kind");
90
+ if (!value.kind && !/^[a-h][1-8][a-h][1-8][qrbn]?$/.test(value.moveUci)) throw new Error("Reasoning position context moveUci is invalid");
91
+ if (!value.kind && !value.moveSan?.trim()) throw new Error("Reasoning position context requires moveSan");
92
+ const history = value.historyStartFen ? new Chess5(value.historyStartFen) : new Chess5();
93
+ for (const [index, moveUci] of value.historyUci.entries()) {
94
+ let replayed;
95
+ try {
96
+ replayed = history.move({ from: moveUci.slice(0, 2), to: moveUci.slice(2, 4), promotion: moveUci.slice(4) || void 0 });
97
+ } catch {
98
+ replayed = null;
99
+ }
100
+ if (!replayed) throw new Error(`Reasoning position context historyUci is illegal at index ${index}`);
101
+ }
102
+ if (history.fen() !== new Chess5(value.fenBefore).fen()) throw new Error("Reasoning position context historyUci does not replay to fenBefore");
103
+ if (value.kind === "position") {
104
+ if (value.moveUci !== "" || value.moveSan !== "" || value.parentNodeId || value.historyUci.length || value.fenBefore !== value.fenAfter || !value.historyStartFen || new Chess5(value.historyStartFen).fen() !== value.fenBefore)
105
+ throw new Error("Invalid starting-position context");
106
+ return { ...value, historyUci: [] };
107
+ }
108
+ const before = new Chess5(value.fenBefore);
109
+ let applied;
110
+ try {
111
+ applied = before.move({ from: value.moveUci.slice(0, 2), to: value.moveUci.slice(2, 4), promotion: value.moveUci.slice(4) || void 0 });
112
+ } catch {
113
+ applied = null;
114
+ }
115
+ if (!applied) throw new Error("Reasoning position context target move is illegal in fenBefore");
116
+ if (applied.san !== value.moveSan) throw new Error("Reasoning position context moveSan does not match the target move");
117
+ if (before.fen() !== value.fenAfter) throw new Error("Reasoning position context fenAfter does not match the target move");
118
+ return { ...value, historyUci: [...value.historyUci] };
119
+ }
120
+ function reasoningContextHash(context2) {
121
+ const checked = validateReasoningPositionContext(context2);
122
+ return stableHash({ nodeId: checked.nodeId, parentNodeId: checked.parentNodeId || null, historyStartFen: checked.historyStartFen || null, fenBefore: checked.fenBefore, fenAfter: checked.fenAfter, historyUci: checked.historyUci, moveUci: checked.moveUci });
123
+ }
124
+
125
+ // src/chess-reasoning/recorded-main-line.ts
126
+ function validRecordedAnalysis(value, before, after, uci2) {
127
+ if (!value || value.version !== "recorded-move-analysis/1" || value.fenBefore !== before || value.fenAfter !== after || value.moveUci !== uci2) return false;
128
+ const boundedText = (s, max) => typeof s === "string" && s.length > 0 && s.length <= max && /^[a-zA-Z0-9@._/ +:-]+$/.test(s);
129
+ const depth = (n) => Number.isInteger(n) && n > 0 && n <= 256;
130
+ const score = (n) => n === null || typeof n === "number" && Number.isFinite(n) && Math.abs(n) <= 1e6;
131
+ return boundedText(value.engine, 64) && boundedText(value.classification, 40) && depth(value.actualDepth) && depth(value.requestedDepth) && Number.isInteger(value.classifierVersion) && value.classifierVersion > 0 && value.classifierVersion <= 1e5 && [value.beforeCp, value.afterCp, value.lossCp, value.mateBefore, value.mateAfter].every(score);
132
+ }
133
+ function recordedMainLineResult(line, context2) {
134
+ if (!line || !Array.isArray(line.moves) || line.moves.length > 512 || !Number.isInteger(line.selectedIndex) || line.selectedIndex < -1 || !Number.isInteger(line.totalPlies) || line.totalPlies < line.moves.length || line.selectedIndex >= line.totalPlies || line.truncated !== line.totalPlies > line.moves.length) throw Error("Invalid recorded main line.");
135
+ const atStart = context2.kind === "position";
136
+ if (atStart && (line.selectedAtStart !== true || line.selectedIndex !== -1 || line.startFen !== context2.fenAfter)) throw Error("Recorded starting-position scope mismatch.");
137
+ if (!atStart && line.selectedAtStart) throw Error("Recorded anchor kind mismatch.");
138
+ const chess = new Chess6(line.startFen);
139
+ const historyRoot = new Chess6(atStart ? context2.fenAfter : context2.historyStartFen).fen();
140
+ if (chess.fen() !== historyRoot) throw Error("Recorded main-line root mismatch.");
141
+ const rows = [];
142
+ const moves2 = line.moves.map((item, index) => {
143
+ if (!/^[a-h][1-8][a-h][1-8][qrbn]?$/.test(item.uci)) throw Error("Invalid recorded move.");
144
+ const before = chess.fen(), move = chess.move({ from: item.uci.slice(0, 2), to: item.uci.slice(2, 4), promotion: item.uci.slice(4) || void 0 });
145
+ if (move.san !== item.san) throw Error("Recorded SAN mismatch.");
146
+ if (index === line.selectedIndex && (before !== context2.fenBefore || chess.fen() !== context2.fenAfter || item.uci !== context2.moveUci || index !== context2.historyUci.length || line.moves.slice(0, index).some((m, i) => m.uci !== context2.historyUci[i]))) throw Error("Recorded question scope mismatch.");
147
+ const a = item.analysis;
148
+ if (validRecordedAnalysis(a, before, chess.fen(), item.uci)) {
149
+ const score = savedScorePresentation(a);
150
+ rows.push([
151
+ index + 1,
152
+ a.engine,
153
+ a.actualDepth,
154
+ a.requestedDepth,
155
+ a.classifierVersion,
156
+ a.classification,
157
+ score.beforeCp,
158
+ score.afterCp,
159
+ score.lossCp,
160
+ score.mateBefore,
161
+ score.mateAfter
162
+ ]);
163
+ }
164
+ return { uci: item.uci, san: move.san, moveNumber: Number(before.split(" ")[5]), color: move.color };
165
+ });
166
+ const continuation = atStart ? moves2.map((move) => move.uci) : line.selectedIndex >= 0 && line.selectedIndex < moves2.length ? moves2.slice(line.selectedIndex + 1).map((move) => move.uci) : [];
167
+ const contextHash = reasoningContextHash(context2);
168
+ const evidence = continuation.length ? [{
169
+ schemaVersion: REASONING_POC_VERSION,
170
+ id: `evidence:recorded-main-line:${contextHash}:${continuation.slice(0, 32).join("-")}`,
171
+ contextHash,
172
+ kind: "fact",
173
+ source: "loaded-game-main-line",
174
+ proofStrength: "observed",
175
+ licenses: ["chess.legality", "chess.identity"],
176
+ summary: "Legally replayed recorded main-line continuation; not an engine recommendation or proof of intent.",
177
+ data: { authority: "legal-exact", scope: "sequence-legality-and-identity", phase: "after" },
178
+ coverage: { complete: false, covered: [], unresolved: ["No optimality or human-intent claim."] },
179
+ replay: { fen: context2.fenAfter, movesUci: continuation.slice(0, 32) }
180
+ }] : [];
181
+ return {
182
+ contextHash,
183
+ evidence,
184
+ recordedAnalysis: {
185
+ source: "Current loaded game's stored per-move analysis snapshots",
186
+ authority: "attributed-existing-analysis",
187
+ scorePerspective: "mover-at-each-recorded-ply",
188
+ units: "centipawns; mate separate",
189
+ coverage: { analyzedPlies: rows.length, totalPlies: line.totalPlies, complete: !line.truncated && rows.length === line.totalPlies },
190
+ columns: ["ply", "engine", "reportedDepth", "recordedRequestedDepth", "classifierVersion", "classification", "beforeCp", "afterCp", "lossCp", "mateBefore", "mateAfter"],
191
+ rows,
192
+ limitations: ["reportedDepth is the stored classification depth, not a verified root-search depth; recordedRequestedDepth is the board setting recorded when classified.", "Matching stored edge analyses are included even when their engine, classifier version or dependency fingerprint is no longer current; missing or invalid plies have no analysis row.", "Scores are from the mover's perspective at each row's ply: positive favors that move's color; lossCp is a saved before/after search delta for that mover, not a controlled regret comparison. Mate-related/sentinel centipawn fields are null; use mateBefore/mateAfter. Best or Forced labels can coexist with search-score changes.", "Classification is a historical decision from the reported classifier version, not necessarily current policy or proof of its explanation. Saved scores may differ from fresh searches.", ...line.truncated ? ["Analysis is limited to the first 512 recorded plies."] : []]
193
+ },
194
+ recordedMainLine: {
195
+ source: "Current loaded game's recorded primary line (may contain user edits)",
196
+ startFen: line.startFen,
197
+ moves: moves2,
198
+ selectedIndex: line.selectedIndex,
199
+ selectedAtStart: atStart,
200
+ selectedOnMainLine: atStart || line.selectedIndex >= 0,
201
+ totalPlies: line.totalPlies,
202
+ truncated: line.truncated,
203
+ pgn: chess.pgn()
204
+ },
205
+ limitations: ["PGN is reconstructed from recorded moves; original headers, clocks and result metadata are not included.", "Recorded play is not engine evidence of best play, force, safety or human intent.", ...!atStart && line.selectedIndex < 0 ? ["The question is on a branch; this main line is not its continuation."] : [], ...line.truncated ? ["Only the first 512 plies are returned."] : []]
206
+ };
207
+ }
208
+
209
+ // src/chess-reasoning/recorded-position-tools.ts
210
+ import { Chess as Chess11 } from "chess.js";
211
+
212
+ // src/chess-reasoning/branch-expansion.ts
213
+ import { Chess as Chess7 } from "chess.js";
214
+
215
+ // src/chess-reasoning/poc-tools.ts
216
+ import { Chess as Chess10, SQUARES as SQUARES4 } from "chess.js";
217
+
218
+ // src/chess-reasoning/concept-registry.ts
219
+ var ENTITY_TYPES = {
220
+ IDEA: "idea",
221
+ PLAN: "plan",
222
+ ROLE: "role-assignment",
223
+ CONDITION: "condition",
224
+ TRANSFORMATION: "transformation",
225
+ OUTCOME: "outcome"
226
+ };
227
+ var PARTICIPANT_ROLES = {
228
+ ACTOR: "actor",
229
+ SUBJECT: "subject",
230
+ TARGET: "target",
231
+ GOAL: "goal",
232
+ RESOURCE: "resource",
233
+ DEFENDER: "defender",
234
+ DESTINATION: "destination"
235
+ };
236
+ var CONCEPT_KEYS = {
237
+ OFFER: "material.offer",
238
+ MATERIAL_CLAIM: "material.claim",
239
+ FORK: "tactic.fork",
240
+ TRAPPED_TARGET: "tactic.trapped-target",
241
+ PROMOTION: "tactic.promotion",
242
+ MATING_ATTACK: "attack.mating",
243
+ PERPETUAL_CHECK: "attack.perpetual-check",
244
+ POSITIONAL_CLAIM: "position.claim",
245
+ KING_ATTACK_PLAN: "plan.king-attack",
246
+ PIECE_ROLE: "role.piece-function",
247
+ CHANGED_CONSTRAINT: "condition.changed-constraint",
248
+ POSITIONAL_TRANSFORMATION: "position.transformation"
249
+ };
250
+ var COMMON_TERMINAL_STATES = ["converted", "refuted", "abandoned", "expired"];
251
+ function claimLifecycle(capturedBy) {
252
+ return {
253
+ initialState: "created",
254
+ retainedState: "retained",
255
+ terminalStates: [...COMMON_TERMINAL_STATES],
256
+ trackedParticipantRole: PARTICIPANT_ROLES.TARGET,
257
+ expireWhenTrackedUnavailable: true,
258
+ onTrackedCapture: {
259
+ capturedBy,
260
+ matchingState: "converted",
261
+ matchingAnnotation: "converted",
262
+ otherState: "refuted",
263
+ otherAnnotation: "refuted"
264
+ }
265
+ };
266
+ }
267
+ function createConceptRegistry(definitions) {
268
+ const registry = {};
269
+ for (const definition of definitions) {
270
+ if (!definition.key.trim()) throw new Error("Concept keys must not be empty");
271
+ if (registry[definition.key]) throw new Error(`Duplicate concept key: ${definition.key}`);
272
+ registry[definition.key] = Object.freeze({
273
+ ...definition,
274
+ lifecycle: definition.lifecycle ? Object.freeze({
275
+ ...definition.lifecycle,
276
+ terminalStates: Object.freeze([...definition.lifecycle.terminalStates]),
277
+ onTrackedCapture: definition.lifecycle.onTrackedCapture ? Object.freeze({ ...definition.lifecycle.onTrackedCapture }) : void 0
278
+ }) : void 0
279
+ });
280
+ }
281
+ return Object.freeze(registry);
282
+ }
283
+ var DEFAULT_CONCEPT_REGISTRY = createConceptRegistry([
284
+ {
285
+ key: CONCEPT_KEYS.OFFER,
286
+ label: "Material offer",
287
+ category: "tactical",
288
+ description: "A material liability the opponent may choose to accept.",
289
+ defaultEntityType: ENTITY_TYPES.IDEA,
290
+ acceptancePolicy: "material-offer-liability/1",
291
+ lifecycle: claimLifecycle("opponent")
292
+ },
293
+ {
294
+ key: CONCEPT_KEYS.MATERIAL_CLAIM,
295
+ label: "Material claim",
296
+ category: "tactical",
297
+ description: "An evidence-backed entitlement to win material.",
298
+ defaultEntityType: ENTITY_TYPES.IDEA,
299
+ lifecycle: claimLifecycle("owner")
300
+ },
301
+ {
302
+ key: CONCEPT_KEYS.FORK,
303
+ label: "Fork",
304
+ category: "tactical",
305
+ description: "One resource attacks multiple targets.",
306
+ defaultEntityType: ENTITY_TYPES.IDEA,
307
+ lifecycle: claimLifecycle("owner")
308
+ },
309
+ {
310
+ key: CONCEPT_KEYS.TRAPPED_TARGET,
311
+ label: "Trapped target",
312
+ category: "tactical",
313
+ description: "A target lacks an adequate escape or defensive resource.",
314
+ defaultEntityType: ENTITY_TYPES.IDEA,
315
+ lifecycle: claimLifecycle("owner")
316
+ },
317
+ {
318
+ key: CONCEPT_KEYS.PROMOTION,
319
+ label: "Promotion",
320
+ category: "tactical",
321
+ description: "A promotion event or promotion claim.",
322
+ defaultEntityType: ENTITY_TYPES.IDEA
323
+ },
324
+ {
325
+ key: CONCEPT_KEYS.MATING_ATTACK,
326
+ label: "Mating attack",
327
+ category: "tactical",
328
+ description: "A coordinated plan whose concrete target is mate.",
329
+ defaultEntityType: ENTITY_TYPES.PLAN
330
+ },
331
+ {
332
+ key: CONCEPT_KEYS.PERPETUAL_CHECK,
333
+ label: "Perpetual check",
334
+ category: "tactical",
335
+ description: "A claim to a repeatable checking sequence.",
336
+ defaultEntityType: ENTITY_TYPES.IDEA
337
+ },
338
+ {
339
+ key: CONCEPT_KEYS.POSITIONAL_CLAIM,
340
+ label: "Positional claim",
341
+ category: "positional",
342
+ description: "A measured, evidence-bounded positional interpretation.",
343
+ defaultEntityType: ENTITY_TYPES.IDEA
344
+ },
345
+ {
346
+ key: CONCEPT_KEYS.KING_ATTACK_PLAN,
347
+ label: "King attack plan",
348
+ category: "plan",
349
+ description: "A goal-directed sequence intended to attack the king.",
350
+ defaultEntityType: ENTITY_TYPES.PLAN
351
+ },
352
+ {
353
+ key: CONCEPT_KEYS.PIECE_ROLE,
354
+ label: "Piece role",
355
+ category: "role",
356
+ description: "A context-dependent function performed by a piece.",
357
+ defaultEntityType: ENTITY_TYPES.ROLE
358
+ },
359
+ {
360
+ key: CONCEPT_KEYS.CHANGED_CONSTRAINT,
361
+ label: "Changed constraint",
362
+ category: "condition",
363
+ description: "A condition whose importance changed after a move or sequence.",
364
+ defaultEntityType: ENTITY_TYPES.CONDITION
365
+ },
366
+ {
367
+ key: CONCEPT_KEYS.POSITIONAL_TRANSFORMATION,
368
+ label: "Positional transformation",
369
+ category: "transformation",
370
+ description: "A causal change in the meaning of a positional feature.",
371
+ defaultEntityType: ENTITY_TYPES.TRANSFORMATION
372
+ }
373
+ ]);
374
+
375
+ // src/chess-reasoning/poc-move-witnesses.ts
376
+ import { Chess as Chess8 } from "chess.js";
377
+
378
+ // src/chess-reasoning/poc-hypotheses.ts
379
+ var RECORD_HYPOTHESES_DESCRIPTOR = {
380
+ name: "record_hypotheses",
381
+ category: "graph",
382
+ description: "Record model-originated semantic hypotheses and causal relations in the provisional Hypothesis Ledger. Hypotheses may cite observations or be novel with zero source observations; novel concrete claims still need evidence before acceptance. parentHypothesisIds means refinement lineage only, never causal order: normally use [] and express enables/supports/explains order in relations. A true refinement may name an earlier ledger ID or same-batch localId and must preserve parent owner/concepts/anchors or include explicit refinementReason and removedAnchorReasons attributes.",
383
+ inputSchema: {
384
+ type: "object",
385
+ required: ["hypotheses", "relations"],
386
+ properties: {
387
+ hypotheses: {
388
+ type: "array",
389
+ minItems: 1,
390
+ maxItems: 16,
391
+ items: {
392
+ type: "object",
393
+ required: ["localId", "entityType", "concepts", "owner", "participants", "attributes", "proofStrength", "evidenceIds", "sourceObservationIds", "parentHypothesisIds", "anchorRequirements"],
394
+ properties: {
395
+ localId: { type: "string", maxLength: 160 },
396
+ entityType: { type: "string", maxLength: 160 },
397
+ concepts: { type: "array", minItems: 1, maxItems: 4, items: { type: "string", maxLength: 160 } },
398
+ owner: { type: ["string", "null"], enum: ["w", "b", null] },
399
+ participants: participantArraySchema(12),
400
+ attributes: { type: "object", maxProperties: 24, propertyNames: { type: "string", minLength: 1, maxLength: 80 }, additionalProperties: true },
401
+ proofStrength: { type: ["string", "null"], enum: ["observed", "supported", "forced", null] },
402
+ evidenceIds: { type: "array", maxItems: 12, items: { type: "string", maxLength: 200 } },
403
+ sourceObservationIds: { type: "array", maxItems: 12, items: { type: "string", maxLength: 200 } },
404
+ parentHypothesisIds: { type: "array", maxItems: 8, description: "Refinement lineage only, not causal order. Usually []. True refinements may use existing hypothesis IDs or same-batch localIds and must satisfy refinement compatibility.", items: { type: "string", maxLength: 200 } },
405
+ anchorRequirements: {
406
+ type: "array",
407
+ maxItems: 12,
408
+ items: {
409
+ type: "object",
410
+ required: ["participant", "disposition"],
411
+ properties: { participant: participantSchema(), disposition: { type: "string", enum: ["required"] } },
412
+ additionalProperties: false
413
+ }
414
+ }
415
+ },
416
+ additionalProperties: false
417
+ }
418
+ },
419
+ relations: {
420
+ type: "array",
421
+ maxItems: 24,
422
+ items: {
423
+ type: "object",
424
+ required: ["relationType", "from", "to", "attributes", "evidenceIds", "sourceObservationIds"],
425
+ properties: {
426
+ relationType: { type: "string", maxLength: 160 },
427
+ from: { type: "string", maxLength: 200 },
428
+ to: { type: "string", maxLength: 200 },
429
+ attributes: { type: "object", maxProperties: 24, propertyNames: { type: "string", minLength: 1, maxLength: 80 }, additionalProperties: true },
430
+ evidenceIds: { type: "array", minItems: 1, maxItems: 12, items: { type: "string", maxLength: 200 } },
431
+ sourceObservationIds: { type: "array", maxItems: 12, items: { type: "string", maxLength: 200 } }
432
+ },
433
+ additionalProperties: false
434
+ }
435
+ }
436
+ },
437
+ additionalProperties: false
438
+ }
439
+ };
440
+ function participantSchema() {
441
+ return {
442
+ type: "object",
443
+ required: ["role", "ref"],
444
+ properties: {
445
+ role: { type: "string", maxLength: 160 },
446
+ ref: {
447
+ type: "object",
448
+ required: ["domain", "id"],
449
+ properties: { domain: { type: "string", maxLength: 160 }, id: { type: "string", maxLength: 200 } },
450
+ additionalProperties: false
451
+ }
452
+ },
453
+ additionalProperties: false
454
+ };
455
+ }
456
+ function participantArraySchema(maxItems) {
457
+ return { type: "array", maxItems, items: participantSchema() };
458
+ }
459
+ function isRecord(value) {
460
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
461
+ }
462
+ var CONCEPT_ACCEPTANCE_VALIDATORS = Object.freeze({
463
+ "material-offer-liability/1": (hypothesis, records) => {
464
+ const contradictedCapture = records.find((record) => {
465
+ if (record.kind !== "fact" || record.data.kind !== "move.legal_recaptures_after") return false;
466
+ const data = isRecord(record.data.data) ? record.data.data : null;
467
+ return data?.targetPieceColor === hypothesis.owner && data.allCapturesLoseAfterImmediateSameSquareRecapture === true;
468
+ });
469
+ const contradictedData = contradictedCapture && isRecord(contradictedCapture.data.data) ? contradictedCapture.data.data : null;
470
+ const captureMoves = Array.isArray(contradictedData?.moves) ? contradictedData.moves.flatMap((move) => isRecord(move) && typeof move.uci === "string" ? [move.uci] : []) : [];
471
+ const strongerBoundedEvidence = captureMoves.length > 0 && records.some((record) => {
472
+ if (record.kind !== "probe" || record.proofStrength !== "supported" && record.proofStrength !== "forced") return false;
473
+ const roots = Array.isArray(record.data.rootMoves) ? record.data.rootMoves.filter((move) => typeof move === "string") : [];
474
+ return captureMoves.every((move) => roots.includes(move));
475
+ });
476
+ return contradictedCapture && !strongerBoundedEvidence ? [`Hypothesis ${hypothesis.id} calls the owner's moved piece a material offer even though cited exhaustive immediate-capture evidence shows every capture can be answered on the same square with a negative nominal balance delta for the capturing side (${contradictedCapture.id})`] : [];
477
+ }
478
+ });
479
+
480
+ // src/chess-reasoning/matched-comparison.ts
481
+ import { Chess as Chess9 } from "chess.js";
482
+
483
+ // src/chess-reasoning/recorded-position-tools.ts
484
+ var moves = { type: "array", maxItems: 32, items: { type: "string", maxLength: 5, pattern: "^[a-h][1-8][a-h][1-8][qrbn]?$" } };
485
+ var common = { ply: { type: "integer", minimum: 0, maximum: 512 }, depth: { type: "integer", minimum: 18, maximum: 18 }, minimumPvPlies: { type: "integer", minimum: 1, maximum: 32 } };
486
+ var RECORDED_POSITION_DESCRIPTORS = [
487
+ { name: "analyze_game_position", category: "probe", description: "analyze_game_position", inputSchema: { type: "object", additionalProperties: false, required: ["ply"], properties: { ...common, rootMoves: { ...moves, minItems: 1, maxItems: 6 }, multiPv: { type: "integer", minimum: 1, maximum: 3 } } } },
488
+ { name: "test_game_line", category: "probe", description: "test_game_line", inputSchema: { type: "object", additionalProperties: false, required: ["ply", "movesUci"], properties: { ...common, movesUci: { ...moves, minItems: 1 }, analyzeFinal: { type: "boolean" }, compareFinalMovesUci: { ...moves, minItems: 1, maxItems: 6 }, inspectPlies: { type: "array", maxItems: 8, items: { type: "integer", minimum: 1, maximum: 32 } }, inspectSquares: { type: "array", maxItems: 12, items: { type: "string", maxLength: 2, pattern: "^[a-h][1-8]$" } } } } }
489
+ ];
490
+ function recordedPositionContext(line, ply) {
491
+ if (!Number.isInteger(ply) || ply < 0 || ply > line.moves.length) throw Object.assign(Error(`ply must be between 0 and ${line.moves.length}; 0 is the initial position`), { code: "invalid-recorded-ply", field: "ply", expected: `integer 0..${line.moves.length}` });
492
+ const chess = new Chess11(line.startFen), prefix = line.moves.slice(0, ply);
493
+ let before = chess.fen();
494
+ for (const item of prefix) {
495
+ before = chess.fen();
496
+ const m = chess.move({ from: item.uci.slice(0, 2), to: item.uci.slice(2, 4), promotion: item.uci.slice(4) || void 0 });
497
+ if (m.san !== item.san) throw Error("recorded-SAN-mismatch");
498
+ }
499
+ const id = `recorded:${stableHash({ startFen: line.startFen, moves: line.moves.map((m) => m.uci) })}:${ply}`;
500
+ return ply === 0 ? { kind: "position", nodeId: id, historyStartFen: line.startFen, historyUci: [], fenBefore: chess.fen(), fenAfter: chess.fen(), moveUci: "", moveSan: "" } : { nodeId: id, historyStartFen: line.startFen, historyUci: prefix.slice(0, -1).map((m) => m.uci), fenBefore: before, fenAfter: chess.fen(), moveUci: prefix.at(-1).uci, moveSan: prefix.at(-1).san };
501
+ }
502
+
503
+ // src/chess-reasoning/initial-search-plan.ts
504
+ var normalize = (san) => san.replace(/[+#?!]+$/, "");
505
+ var uci = (m) => m.from + m.to + (m.promotion ?? "");
506
+ function planInitialSearches(input2) {
507
+ const { question: q, context: context2, mainLine } = input2;
508
+ const result = { version: "initial-search-plan/1", requests: [], limitations: [] };
509
+ const record = mainLine ? recordedMainLineResult(mainLine, context2) : void 0;
510
+ if (input2.classificationQuestion && !input2.omitSelectedContext && context2.kind !== "position") {
511
+ result.classificationReassessment = true;
512
+ result.requests.push({ tool: "explore_continuations", input: { phase: "before", depth: 18, multiPv: 3, minimumPvPlies: 10 }, reason: "Reassess the selected move classification using a depth-18 unrestricted before-position search. Preserve the original decision and refresh the canonical label afterwards." });
513
+ }
514
+ const names = [...q.matchAll(/(?<![A-Za-z0-9])(?:O-O(?:-O)?|[KQRBN][a-h]?[1-8]?x?[a-h][1-8](?:=[QRBN])?|[a-h]x?[a-h]?[1-8](?:=[QRBN])?)[+#]?(?![A-Za-z0-9])/g)].map((m) => normalize(m[0]));
515
+ const alternative = /\b(better|instead|alternative|compare|rather)\b|\bwhat (?:if|about)\b|\b(?:could|should)\b.*\bplay\b/i.test(q);
516
+ const negated = /\b(?:don't|do not|no need to|without)\b.*\b(?:compare|analy[sz]e|instead|alternative)\b/i.test(q);
517
+ if (names.length && names.length <= 6 && alternative && !negated) {
518
+ let fen, phase = "before", ply, played;
519
+ const numbered = [...q.matchAll(/\b(\d+)\s*(\.{1,3}|…)\s*(?=[KQRBNa-hO])/g)];
520
+ const unboundNumber = /\b\d+\b/.test(q.replace(/\b(\d+)\s*(\.{1,3}|…)\s*(?=[KQRBNa-hO])/g, ""));
521
+ if (numbered.length && !unboundNumber && record && mainLine) {
522
+ const roots = numbered.map((m) => record.recordedMainLine.moves.flatMap((move, i) => move.moveNumber === Number(m[1]) && move.color === (m[2] === "." ? "w" : "b") ? [i] : []));
523
+ if (roots.every((r) => r.length === 1 && r[0] === roots[0][0])) {
524
+ ply = roots[0][0];
525
+ fen = recordedPositionContext(mainLine, ply).fenAfter;
526
+ played = mainLine.moves[ply]?.uci;
527
+ }
528
+ } else if (!numbered.length && !/\b\d+\b/.test(q) && !input2.omitSelectedContext && !/\b(later|earlier|previous|opening|endgame|middlegame|move\s+\d+)\b/i.test(q)) {
529
+ phase = /\b(next|reply|respond)\b/i.test(q) ? "after" : "before";
530
+ fen = phase === "after" ? context2.fenAfter : context2.fenBefore;
531
+ played = phase === "before" && context2.kind !== "position" ? context2.moveUci : void 0;
532
+ const explicitRole = /\b(instead|alternative|rather|than|next|reply|respond)\b/i.test(q);
533
+ if (!explicitRole && context2.fenBefore !== context2.fenAfter) {
534
+ const other = new Chess12(context2.fenAfter).moves().map(normalize);
535
+ if (names.every((n) => other.includes(n))) fen = void 0;
536
+ }
537
+ }
538
+ if (fen) {
539
+ const legal = new Chess12(fen).moves({ verbose: true });
540
+ const resolved = names.map((n) => legal.filter((m) => normalize(m.san) === n));
541
+ if (resolved.every((ms) => ms.length === 1)) {
542
+ const roots = [.../* @__PURE__ */ new Set([...resolved.map((ms) => uci(ms[0])), ...played ? [played] : []])];
543
+ if (roots.length && roots.length <= 6 && (!played || roots.some((r) => r !== played))) {
544
+ result.requests.push({ tool: ply === void 0 ? "compare_moves" : "analyze_game_position", input: { ...ply === void 0 ? { phase, movesUci: roots } : { ply, rootMoves: roots }, depth: 18, minimumPvPlies: 10 }, reason: "Explicit named legal alternatives at one resolved root; compare with the recorded/selected move when applicable." });
545
+ return result;
546
+ }
547
+ }
548
+ }
549
+ result.limitations.push("Named moves were not unambiguously resolved for automatic search; the model may choose the root and query.");
550
+ }
551
+ if (input2.positionPreparation !== false && !input2.omitSelectedContext && !input2.reviewGame && (input2.answerScope === "position_analysis" || !input2.answerScope && context2.kind === "position") && !names.length) {
552
+ try {
553
+ const phase = context2.kind === "position" ? "before" : "after";
554
+ const fen = phase === "before" ? context2.fenBefore : context2.fenAfter;
555
+ if (!new Chess12(fen).isGameOver()) result.requests.push({
556
+ tool: "explore_continuations",
557
+ input: { phase, depth: 18, multiPv: 3, minimumPvPlies: 24 },
558
+ reason: "Initial current-position candidates and continuations. Reuse this evidence and investigate additional relevant plans with the available tools; these returned moves are not exhaustive."
559
+ });
560
+ } catch {
561
+ result.limitations.push("Current-position preparation unavailable: invalid position.");
562
+ }
563
+ return result;
564
+ }
565
+ if (!record || !mainLine || !input2.reviewGame || !input2.omitSelectedContext) return result;
566
+ if (names.length || /\b(?:endgame|middlegame|late|last|after|before)\b|\bmove\s+\d+/i.test(q)) {
567
+ result.limitations.push("Specific move or phase boundary requires model-directed investigation.");
568
+ return result;
569
+ }
570
+ const subject = input2.reviewSubject ?? "unspecified";
571
+ const relative = subject === "self" || subject === "opponent";
572
+ const playerSide = input2.playerPerspective?.side;
573
+ const side = subject === "white" || subject === "black" ? subject : relative && playerSide ? subject === "self" ? playerSide : playerSide === "white" ? "black" : "white" : void 0;
574
+ result.reviewScope = { subject, resolvedSide: side ?? (relative ? "unknown" : "both") };
575
+ if (relative && !side) {
576
+ result.limitations.push("Player side unknown; defer personal/opponent review preparation to the answering model.");
577
+ return result;
578
+ }
579
+ const opening = /\bopening\b/i.test(q);
580
+ if (opening && mainLine.startFen !== new Chess12().fen()) {
581
+ result.limitations.push("Opening boundary unknown for a custom starting position.");
582
+ return result;
583
+ }
584
+ if (opening) result.limitations.push("Preparation uses the first 12 full moves as an opening-review heuristic, not a claim that the opening ends there.");
585
+ const eligible = record.recordedAnalysis.rows.filter((row) => {
586
+ const move = record.recordedMainLine.moves[row[0] - 1];
587
+ return (!side || move.color === (side === "white" ? "w" : "b")) && (!opening || move.moveNumber <= 12);
588
+ });
589
+ const rank = (row) => row[8] ?? (row[9] !== null && row[10] !== null ? Math.max(0, Math.abs(row[10]) - Math.abs(row[9])) : 0);
590
+ const ordered = (rows) => rows.sort((a, b) => rank(b) - rank(a) || a[0] - b[0]);
591
+ const major = ordered(eligible.filter((row) => ["blunder", "mistake", "miss"].includes(row[5])));
592
+ const optional = major.length < 10 ? ordered(eligible.filter((row) => row[5] === "dubious")).slice(0, Math.min(5, 10 - major.length)) : [];
593
+ for (const row of [...major, ...optional]) {
594
+ const score = row[9] !== null || row[10] !== null ? `mate before ${row[9] ?? "not found"}, mate after ${row[10] ?? "not found"}` : row[8] !== null ? `saved search delta ${row[8]}cp` : "no comparable centipawn loss";
595
+ result.requests.push({ tool: "analyze_game_position", input: { ply: row[0] - 1, multiPv: 3, depth: 18, minimumPvPlies: 10 }, playedMove: mainLine.moves[row[0] - 1].uci, reason: `Review candidate at recorded ply ${row[0]}: saved ${row[5]}, ${score} at depth ${row[2]}. Discover strongest alternatives and ensure a matched comparison with the played move; classification is historical.` });
596
+ }
597
+ if (!result.requests.length) result.limitations.push("No matching saved Blunder, Mistake, Miss or Dubious moves; model may investigate other useful moments.");
598
+ return result;
599
+ }
600
+
601
+ // test/owner/position-preparation.test.mjs
602
+ var context = { kind: "position", nodeId: "root", historyStartFen: "rnbq1rk1/p1p1bpp1/1p3n1p/3p4/3P3B/2N1PN2/PP3PPP/R2QKB1R w KQ - 0 9", historyUci: [], moveUci: "", moveSan: "" };
603
+ context.fenBefore = context.fenAfter = context.historyStartFen;
604
+ var input = { context, question: "Assess the current position: what are the main strengths, weaknesses and plans for both sides?", answerScope: "position_analysis", omitSelectedContext: false };
605
+ test("KE-REASON-021: prepare same actual position tool before first answering call", () => {
606
+ const plan = planInitialSearches(input);
607
+ assert.equal(plan.requests.length, 1);
608
+ assert.equal(plan.requests[0].tool, "explore_continuations");
609
+ assert.deepEqual(plan.requests[0].input, { phase: "before", depth: 18, multiPv: 3, minimumPvPlies: 24 });
610
+ });
611
+ test("retrospective, omitted, general, terminal and explicit ablation do not search an unrelated board", () => {
612
+ for (const change of [{ omitSelectedContext: true }, { reviewGame: true }, { answerScope: "general" }, { positionPreparation: false }]) assert.equal(planInitialSearches({ ...input, ...change }).requests.length, 0);
613
+ const terminal = "7k/5Q2/6K1/8/8/8/8/8 b - - 0 1";
614
+ assert.ok(new Chess13(terminal).isGameOver());
615
+ assert.equal(planInitialSearches({ ...input, context: { ...context, fenBefore: terminal, fenAfter: terminal } }).requests.length, 0);
616
+ });
617
+ test("explicit current-node comparison takes precedence over broad preparation", () => {
618
+ const p = planInitialSearches({ ...input, question: "Compare Bd3 and Be2 instead." });
619
+ assert.equal(p.requests.length, 1);
620
+ assert.equal(p.requests[0].tool, "compare_moves");
621
+ });
622
+ test("retained selected-move context assessment searches the after position", () => {
623
+ const c = { ...context, kind: "move", moveUci: "e6d5", moveSan: "exd5" };
624
+ assert.equal(planInitialSearches({ ...input, context: c }).requests[0].input.phase, "after");
625
+ });