@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,529 @@
1
+ // test/owner/mechanism-encoding.test.mjs
2
+ import assert from "node:assert/strict";
3
+ import test from "node:test";
4
+ import { Chess as Chess3 } from "chess.js";
5
+
6
+ // src/chess-reasoning/mechanism-presentation.ts
7
+ var object = (v) => !!v && typeof v === "object" && !Array.isArray(v);
8
+ var COLUMNS = {
9
+ mover: ["pieceId", "pieceIdAfter", "fromSquare", "toSquare", "color", "pieceTypeBefore", "pieceTypeAfter", "attackersBefore", "attackersAfter"],
10
+ unmoved: ["pieceId", "square", "pieceType", "attackersBefore", "attackersAfter"],
11
+ rays: ["pieceId", "fromSquare", "color", "pieceType", "direction", "gainedSquares", "lostSquares"],
12
+ control: ["square", "color", "attackersBefore", "attackersAfter"]
13
+ };
14
+ var GROUPS = ["mover", "unmoved", "rays", "control"];
15
+ function exactKeys(value, columns) {
16
+ return object(value) && Object.keys(value).length === columns.length && columns.every((column) => Object.hasOwn(value, column));
17
+ }
18
+ function encodeRows(value, columns) {
19
+ return columns.map((column) => value[column]);
20
+ }
21
+ function decodeRow(row, columns) {
22
+ if (!Array.isArray(row) || row.length !== columns.length) return null;
23
+ return Object.fromEntries(columns.map((column, index) => [column, row[index]]));
24
+ }
25
+ function expandMechanismPresentation(value) {
26
+ if (!object(value) || value.encoding !== "move-mechanism/1") return value;
27
+ if (!object(value.columns) || !object(value.rows) || Object.keys(value.columns).length !== GROUPS.length || Object.keys(value.rows).length !== GROUPS.length) return value;
28
+ for (const group of GROUPS) {
29
+ if (JSON.stringify(value.columns[group]) !== JSON.stringify(COLUMNS[group])) return value;
30
+ }
31
+ const mover = decodeRow(value.rows.mover, COLUMNS.mover);
32
+ if (!mover || !Array.isArray(value.rows.unmoved) || !Array.isArray(value.rows.rays) || !Array.isArray(value.rows.control)) return value;
33
+ const unmoved = value.rows.unmoved.map((row) => decodeRow(row, COLUMNS.unmoved));
34
+ const rays = value.rows.rays.map((row) => decodeRow(row, COLUMNS.rays));
35
+ const control = value.rows.control.map((row) => decodeRow(row, COLUMNS.control));
36
+ if ([...unmoved, ...rays, ...control].some((row) => row === null)) return value;
37
+ const { encoding: _encoding, columns: _columns, rows: _rows, ...rest } = value;
38
+ void _encoding;
39
+ void _columns;
40
+ void _rows;
41
+ return {
42
+ ...rest,
43
+ mover,
44
+ attackedUnmovedFriendlyPieces: unmoved,
45
+ stationarySliderRays: rays,
46
+ controlDelta: control
47
+ };
48
+ }
49
+ function compactMechanism(value, targetSquares) {
50
+ if (!object(value) || !Array.isArray(value.controlDelta)) return value;
51
+ const targets = [...new Set(targetSquares)].filter((s) => /^[a-h][1-8]$/.test(s));
52
+ const controlDelta = value.controlDelta.filter((d) => object(d) && targets.includes(String(d.square)));
53
+ const rays = Array.isArray(value.stationarySliderRays) ? value.stationarySliderRays.map((ray2) => {
54
+ if (!object(ray2)) return ray2;
55
+ const { beforeSquares: _before, afterSquares: _after, ...changes } = ray2;
56
+ void _before;
57
+ void _after;
58
+ return changes;
59
+ }) : value.stationarySliderRays;
60
+ const projected = {
61
+ ...value,
62
+ stationarySliderRays: rays,
63
+ controlDelta,
64
+ presentation: {
65
+ controlSquares: targets,
66
+ omittedControlDeltaCount: value.controlDelta.length - controlDelta.length,
67
+ scope: "All changed stationary rays and mover/unmoved attack measurements retained. Control deltas shown only for controlSquares; an omitted square is not checked-negative in this view. Full ray extents and all control deltas are retrievable."
68
+ }
69
+ };
70
+ if (!exactKeys(value, ["mover", "attackedUnmovedFriendlyPieces", "stationarySliderRays", "controlDelta", "checksRun", "scope"]) || !exactKeys(projected.mover, COLUMNS.mover) || !Array.isArray(projected.attackedUnmovedFriendlyPieces) || !projected.attackedUnmovedFriendlyPieces.every((item) => exactKeys(item, COLUMNS.unmoved)) || !Array.isArray(rays) || !rays.every((item) => exactKeys(item, COLUMNS.rays)) || !controlDelta.every((item) => exactKeys(item, COLUMNS.control))) return projected;
71
+ return {
72
+ encoding: "move-mechanism/1",
73
+ columns: COLUMNS,
74
+ rows: {
75
+ mover: encodeRows(projected.mover, COLUMNS.mover),
76
+ unmoved: projected.attackedUnmovedFriendlyPieces.map((item) => encodeRows(item, COLUMNS.unmoved)),
77
+ rays: rays.map((item) => encodeRows(item, COLUMNS.rays)),
78
+ control: controlDelta.map((item) => encodeRows(item, COLUMNS.control))
79
+ },
80
+ checksRun: projected.checksRun,
81
+ scope: projected.scope,
82
+ presentation: projected.presentation
83
+ };
84
+ }
85
+
86
+ // src/chess-reasoning/move-mechanism-facts.ts
87
+ import { Chess as Chess2, SQUARES as SQUARES2 } from "chess.js";
88
+
89
+ // src/chess-reasoning/piece-identities.ts
90
+ import { Chess, SQUARES } from "chess.js";
91
+
92
+ // src/chess-reasoning/types.ts
93
+ var CHESS_REASONING_SCHEMA_VERSION = "0.2.0";
94
+
95
+ // src/chess-reasoning/piece-identities.ts
96
+ var PIECE_NAMES = {
97
+ p: "pawn",
98
+ n: "knight",
99
+ b: "bishop",
100
+ r: "rook",
101
+ q: "queen",
102
+ k: "king"
103
+ };
104
+ var COLOR_NAMES = { w: "white", b: "black" };
105
+ function pieceId(color, type, square, ordinal = 0) {
106
+ return `${COLOR_NAMES[color]}-${PIECE_NAMES[type]}:${square}:${ordinal}`;
107
+ }
108
+ function promotionId(color, type, square, ordinal) {
109
+ return `${COLOR_NAMES[color]}-${PIECE_NAMES[type]}:promotion:${square}:${ordinal}`;
110
+ }
111
+ function clonePieces(pieces) {
112
+ return Object.fromEntries(Object.entries(pieces).map(([id, piece]) => [id, { ...piece }]));
113
+ }
114
+ function createIdentityState(fen = new Chess().fen(), branchId = "main", ply = 0) {
115
+ const chess = new Chess(fen);
116
+ const pieces = {};
117
+ const squares = {};
118
+ const seen = /* @__PURE__ */ new Map();
119
+ for (const square of SQUARES) {
120
+ const piece = chess.get(square);
121
+ if (!piece) continue;
122
+ const key = `${piece.color}:${piece.type}:${square}`;
123
+ const ordinal = seen.get(key) || 0;
124
+ seen.set(key, ordinal + 1);
125
+ const id = pieceId(piece.color, piece.type, square, ordinal);
126
+ pieces[id] = {
127
+ id,
128
+ color: piece.color,
129
+ type: piece.type,
130
+ originSquare: square,
131
+ createdPly: ply,
132
+ promotedFrom: null,
133
+ capturedAtPly: null,
134
+ retiredAtPly: null
135
+ };
136
+ squares[square] = id;
137
+ }
138
+ return {
139
+ schemaVersion: CHESS_REASONING_SCHEMA_VERSION,
140
+ branchId,
141
+ fen: chess.fen(),
142
+ ply,
143
+ pieces,
144
+ squares,
145
+ promotionSequence: 0
146
+ };
147
+ }
148
+ function applyIdentityMove(state, moveInput) {
149
+ const chess = new Chess(state.fen);
150
+ const beforeFen = chess.fen();
151
+ const move = chess.move(moveInput);
152
+ const nextPly = state.ply + 1;
153
+ const pieces = clonePieces(state.pieces);
154
+ const squares = { ...state.squares };
155
+ const mover = squares[move.from];
156
+ if (!mover) throw new Error(`No stable piece identity at ${move.from}`);
157
+ let captured = null;
158
+ const capturedSquare = move.isEnPassant() ? `${move.to[0]}${move.from[1]}` : move.to;
159
+ if (move.isCapture() || move.isEnPassant()) {
160
+ captured = squares[capturedSquare] || null;
161
+ if (!captured) throw new Error(`No captured piece identity at ${capturedSquare}`);
162
+ pieces[captured] = { ...pieces[captured], capturedAtPly: nextPly };
163
+ delete squares[capturedSquare];
164
+ }
165
+ delete squares[move.from];
166
+ let rookMoved = null;
167
+ if (move.isKingsideCastle() || move.isQueensideCastle()) {
168
+ const rank = move.from[1];
169
+ const rookFrom = `${move.isKingsideCastle() ? "h" : "a"}${rank}`;
170
+ const rookTo = `${move.isKingsideCastle() ? "f" : "d"}${rank}`;
171
+ rookMoved = squares[rookFrom] || null;
172
+ if (!rookMoved) throw new Error(`No stable rook identity at ${rookFrom}`);
173
+ delete squares[rookFrom];
174
+ squares[rookTo] = rookMoved;
175
+ }
176
+ let promoted = null;
177
+ let promotionSequence = state.promotionSequence;
178
+ if (move.isPromotion()) {
179
+ promotionSequence += 1;
180
+ pieces[mover] = { ...pieces[mover], retiredAtPly: nextPly };
181
+ promoted = promotionId(move.color, move.promotion, move.to, promotionSequence);
182
+ pieces[promoted] = {
183
+ id: promoted,
184
+ color: move.color,
185
+ type: move.promotion,
186
+ originSquare: move.to,
187
+ createdPly: nextPly,
188
+ promotedFrom: mover,
189
+ capturedAtPly: null,
190
+ retiredAtPly: null
191
+ };
192
+ squares[move.to] = promoted;
193
+ } else {
194
+ squares[move.to] = mover;
195
+ }
196
+ const nextState = {
197
+ schemaVersion: CHESS_REASONING_SCHEMA_VERSION,
198
+ branchId: state.branchId,
199
+ fen: chess.fen(),
200
+ ply: nextPly,
201
+ pieces,
202
+ squares,
203
+ promotionSequence
204
+ };
205
+ return {
206
+ state: nextState,
207
+ delta: {
208
+ branchId: state.branchId,
209
+ ply: nextPly,
210
+ uci: `${move.from}${move.to}${move.promotion || ""}`,
211
+ san: move.san,
212
+ mover,
213
+ captured,
214
+ promoted,
215
+ rookMoved,
216
+ beforeFen,
217
+ afterFen: chess.fen()
218
+ }
219
+ };
220
+ }
221
+
222
+ // src/chess-reasoning/move-mechanism-facts.ts
223
+ var DIRECTIONS = [
224
+ ["N", 0, 1],
225
+ ["NE", 1, 1],
226
+ ["E", 1, 0],
227
+ ["SE", 1, -1],
228
+ ["S", 0, -1],
229
+ ["SW", -1, -1],
230
+ ["W", -1, 0],
231
+ ["NW", -1, 1]
232
+ ];
233
+ function enemy(color) {
234
+ return color === "w" ? "b" : "w";
235
+ }
236
+ function attackers(board, square, color) {
237
+ return board.attackers(square, color).sort((a, b) => SQUARES2.indexOf(a) - SQUARES2.indexOf(b));
238
+ }
239
+ function ray(board, origin, fileStep, rankStep) {
240
+ const squares = [];
241
+ const file = origin.charCodeAt(0) - 97;
242
+ const rank = Number(origin[1]) - 1;
243
+ for (let distance = 1; distance < 8; distance += 1) {
244
+ const f = file + fileStep * distance;
245
+ const r = rank + rankStep * distance;
246
+ if (f < 0 || f > 7 || r < 0 || r > 7) break;
247
+ const square = `${String.fromCharCode(97 + f)}${r + 1}`;
248
+ squares.push(square);
249
+ if (board.get(square)) break;
250
+ }
251
+ return squares;
252
+ }
253
+ function sliderDirections(type) {
254
+ if (type === "q") return DIRECTIONS;
255
+ return DIRECTIONS.filter(([, dx, dy]) => type === "r" ? !dx || !dy : !!dx && !!dy);
256
+ }
257
+ function moveMechanismFacts(before, after, from, to, beforeIds, afterIds) {
258
+ const moverBefore = before.get(from);
259
+ const moverAfter = after.get(to);
260
+ if (!moverBefore || !moverAfter || moverBefore.color !== moverAfter.color) {
261
+ throw new Error(`Move mechanism has no corresponding mover at ${from}-${to}`);
262
+ }
263
+ const beforeState = beforeIds || createIdentityState(before.fen());
264
+ if (beforeState.fen !== before.fen() || afterIds && afterIds.fen !== after.fen()) {
265
+ throw new Error("Move mechanism identity position does not match the board");
266
+ }
267
+ const actualMove = before.moves({ verbose: true }).find((move) => {
268
+ if (move.from !== from || move.to !== to) return false;
269
+ const replay = new Chess2(before.fen());
270
+ replay.move({ from, to, promotion: move.promotion });
271
+ return replay.fen() === after.fen();
272
+ });
273
+ if (!actualMove) throw new Error(`Move mechanism after-position is not a legal ${from}-${to} result`);
274
+ const afterState = afterIds || applyIdentityMove(beforeState, {
275
+ from,
276
+ to,
277
+ promotion: actualMove.promotion
278
+ }).state;
279
+ const pieceId2 = beforeState.squares[from];
280
+ const pieceIdAfter = afterState.squares[to];
281
+ if (!pieceId2 || !pieceIdAfter || (actualMove.promotion ? afterState.pieces[pieceIdAfter]?.promotedFrom !== pieceId2 : pieceIdAfter !== pieceId2)) {
282
+ throw new Error("Move mechanism mover identities do not match");
283
+ }
284
+ const attackedUnmovedFriendlyPieces = [];
285
+ const stationarySliderRays = [];
286
+ const color = moverBefore.color;
287
+ for (const square of SQUARES2) {
288
+ const piece = before.get(square);
289
+ const samePiece = after.get(square);
290
+ const id = beforeState.squares[square];
291
+ if (!piece || !samePiece || !id || afterState.squares[square] !== id || piece.color !== samePiece.color || piece.type !== samePiece.type) continue;
292
+ if (piece.color === color) {
293
+ const beforeAttackers = attackers(before, square, enemy(color));
294
+ const afterAttackers = attackers(after, square, enemy(color));
295
+ if (beforeAttackers.length || afterAttackers.length) {
296
+ attackedUnmovedFriendlyPieces.push({
297
+ pieceId: id,
298
+ square,
299
+ pieceType: piece.type,
300
+ attackersBefore: beforeAttackers,
301
+ attackersAfter: afterAttackers
302
+ });
303
+ }
304
+ }
305
+ if (piece.type !== "r" && piece.type !== "b" && piece.type !== "q") continue;
306
+ for (const [direction, dx, dy] of sliderDirections(piece.type)) {
307
+ const beforeSquares = ray(before, square, dx, dy);
308
+ const afterSquares = ray(after, square, dx, dy);
309
+ const beforeSet = new Set(beforeSquares);
310
+ const afterSet = new Set(afterSquares);
311
+ const gainedSquares = afterSquares.filter((target) => !beforeSet.has(target));
312
+ const lostSquares = beforeSquares.filter((target) => !afterSet.has(target));
313
+ if (gainedSquares.length || lostSquares.length) {
314
+ stationarySliderRays.push({
315
+ pieceId: id,
316
+ fromSquare: square,
317
+ color: piece.color,
318
+ pieceType: piece.type,
319
+ direction,
320
+ beforeSquares,
321
+ afterSquares,
322
+ gainedSquares,
323
+ lostSquares
324
+ });
325
+ }
326
+ }
327
+ }
328
+ const controlDelta = [];
329
+ for (const square of SQUARES2) {
330
+ for (const attackingColor of ["w", "b"]) {
331
+ const attackersBefore = attackers(before, square, attackingColor);
332
+ const attackersAfter = attackers(after, square, attackingColor);
333
+ if (attackersBefore.length !== attackersAfter.length || attackersBefore.some((origin, index) => origin !== attackersAfter[index])) {
334
+ controlDelta.push({ square, color: attackingColor, attackersBefore, attackersAfter });
335
+ }
336
+ }
337
+ }
338
+ return {
339
+ mover: {
340
+ pieceId: pieceId2,
341
+ pieceIdAfter,
342
+ fromSquare: from,
343
+ toSquare: to,
344
+ color,
345
+ pieceTypeBefore: moverBefore.type,
346
+ pieceTypeAfter: moverAfter.type,
347
+ attackersBefore: attackers(before, from, enemy(color)),
348
+ attackersAfter: attackers(after, to, enemy(color))
349
+ },
350
+ attackedUnmovedFriendlyPieces,
351
+ stationarySliderRays,
352
+ controlDelta,
353
+ checksRun: [
354
+ "mover-geometric-attackers-before-after",
355
+ "unmoved-friendly-piece-geometric-attackers-before-after",
356
+ "stationary-slider-visible-rays-before-after",
357
+ "all-square-both-color-geometric-control-delta"
358
+ ],
359
+ scope: "Complete board-local geometric measurements at this move. Attackers include pinned pieces; visible slider rays include the first occupied square. Empty lists mean measured none or no change. No claim of legal captures, safe retreat, exchange profit, forced purpose, or strategic importance."
360
+ };
361
+ }
362
+
363
+ // src/chess-reasoning/lossless-evidence-sharing.ts
364
+ var EVIDENCE_SHARING_VERSION = "evidence-sharing/1";
365
+ var EVIDENCE_SHARING_GUIDANCE_CHARS = 490;
366
+ var object2 = (x) => x !== null && typeof x === "object" && !Array.isArray(x);
367
+ function shareEvidence(value) {
368
+ if (object2(value) && value.encoding === EVIDENCE_SHARING_VERSION) return value;
369
+ const counts = /* @__PURE__ */ new Map();
370
+ const keys = /* @__PURE__ */ new WeakMap();
371
+ let collision = false;
372
+ const count = (x) => {
373
+ if (!x || typeof x !== "object") return;
374
+ if (Object.hasOwn(x, "$shared")) collision = true;
375
+ const key = JSON.stringify(x);
376
+ keys.set(x, key);
377
+ if (key.length >= 96) counts.set(key, (counts.get(key) ?? 0) + 1);
378
+ for (const child of Object.values(x)) count(child);
379
+ };
380
+ count(value);
381
+ if (collision) return value;
382
+ const values = {}, ids = /* @__PURE__ */ new Map();
383
+ const children = (x) => Array.isArray(x) ? x.map(visit) : object2(x) ? Object.fromEntries(Object.entries(x).map(([k, v]) => [k, visit(v)])) : x;
384
+ const visit = (x) => {
385
+ if (!x || typeof x !== "object") return x;
386
+ const key = keys.get(x);
387
+ if ((counts.get(key) ?? 0) < 2) return children(x);
388
+ let id = ids.get(key);
389
+ if (!id) {
390
+ id = `s${ids.size}`;
391
+ ids.set(key, id);
392
+ values[id] = children(x);
393
+ }
394
+ return { $shared: id };
395
+ };
396
+ let content = children(value);
397
+ const stringCounts = /* @__PURE__ */ new Map();
398
+ const objectDefinitions = Object.entries(values);
399
+ const countStrings = (x) => {
400
+ if (typeof x === "string") {
401
+ stringCounts.set(x, (stringCounts.get(x) ?? 0) + 1);
402
+ return;
403
+ }
404
+ if (Array.isArray(x)) {
405
+ x.forEach(countStrings);
406
+ return;
407
+ }
408
+ if (object2(x) && !Object.hasOwn(x, "$shared")) Object.values(x).forEach(countStrings);
409
+ };
410
+ countStrings(content);
411
+ for (const [, definition] of objectDefinitions) countStrings(definition);
412
+ const stringIds = /* @__PURE__ */ new Map();
413
+ const shareStrings = (x) => {
414
+ if (typeof x === "string") {
415
+ const count2 = stringCounts.get(x) ?? 0;
416
+ let id = stringIds.get(x);
417
+ if (!id && count2 >= 2) {
418
+ const nextId = `s${ids.size + stringIds.size}`;
419
+ const literalLength = JSON.stringify(x).length;
420
+ const pointerLength = JSON.stringify({ $shared: nextId }).length;
421
+ const definitionLength = JSON.stringify(nextId).length + 1 + literalLength + 1;
422
+ if (count2 * literalLength > count2 * pointerLength + definitionLength) {
423
+ id = nextId;
424
+ stringIds.set(x, id);
425
+ values[id] = x;
426
+ }
427
+ }
428
+ return id ? { $shared: id } : x;
429
+ }
430
+ if (Array.isArray(x)) return x.map(shareStrings);
431
+ if (object2(x) && !Object.hasOwn(x, "$shared")) return Object.fromEntries(Object.entries(x).map(([k, v]) => [k, shareStrings(v)]));
432
+ return x;
433
+ };
434
+ content = shareStrings(content);
435
+ for (const [id, definition] of objectDefinitions) values[id] = shareStrings(definition);
436
+ const result = { encoding: EVIDENCE_SHARING_VERSION, values, content };
437
+ return (ids.size || stringIds.size) && JSON.stringify(result).length + EVIDENCE_SHARING_GUIDANCE_CHARS + 128 < JSON.stringify(value).length ? result : value;
438
+ }
439
+
440
+ // test/owner/mechanism-encoding.test.mjs
441
+ function measured(fen, uci) {
442
+ const before = new Chess3(fen);
443
+ const after = new Chess3(fen);
444
+ after.move({ from: uci.slice(0, 2), to: uci.slice(2, 4), promotion: uci.slice(4) || void 0 });
445
+ return moveMechanismFacts(before, after, uci.slice(0, 2), uci.slice(2, 4));
446
+ }
447
+ function oldProjection(value, targets) {
448
+ const controlSquares = [...new Set(targets)].filter((s) => /^[a-h][1-8]$/.test(s));
449
+ return {
450
+ ...value,
451
+ stationarySliderRays: value.stationarySliderRays.map((ray2) => {
452
+ const copy = { ...ray2 };
453
+ delete copy.beforeSquares;
454
+ delete copy.afterSquares;
455
+ return copy;
456
+ }),
457
+ controlDelta: value.controlDelta.filter((change) => controlSquares.includes(change.square)),
458
+ presentation: {
459
+ controlSquares,
460
+ omittedControlDeltaCount: value.controlDelta.length - value.controlDelta.filter((change) => controlSquares.includes(change.square)).length,
461
+ scope: "All changed stationary rays and mover/unmoved attack measurements retained. Control deltas shown only for controlSquares; an omitted square is not checked-negative in this view. Full ray extents and all control deltas are retrievable."
462
+ }
463
+ };
464
+ }
465
+ test("KE-REASON-016/021: row encoding round trips every currently projected field and omission marker", () => {
466
+ const examples = [
467
+ [measured("1k1r3r/2p5/p2p1p2/2P2B2/b3PB1p/5P2/3R2PP/2KR4 w - - 1 25", "d2b2"), ["d1", "b2", "d5"]],
468
+ [measured("r1bqkb1r/p1pp1pp1/1p3n1p/8/2BQP3/2N5/PPP2PPP/R1B1K2R w KQkq - 0 8", "e4e5"), ["e5", "g4", "f4", "e5"]],
469
+ [measured("8/4P3/1R2B3/6Bk/7P/8/8/2K5 w - - 3 50", "e6f7"), ["g4", "f7", "e8"]]
470
+ ];
471
+ for (const [full, targets] of examples) {
472
+ const compact = compactMechanism(full, targets);
473
+ assert.equal(compact.encoding, "move-mechanism/1");
474
+ assert.deepEqual(expandMechanismPresentation(compact), oldProjection(full, targets));
475
+ assert.deepEqual(compact.presentation.controlSquares, [...new Set(targets)]);
476
+ assert.ok(compact.columns.rays.includes("gainedSquares"));
477
+ assert.ok(compact.columns.control.includes("attackersAfter"));
478
+ assert.equal(expandMechanismPresentation(full), full);
479
+ assert.equal(compactMechanism(compact, targets), compact);
480
+ }
481
+ });
482
+ test("KE-REASON-016/021: unknown canonical fields fail open without information loss", () => {
483
+ const full = measured("r1bqkb1r/p1pp1pp1/1p3n1p/8/2BQP3/2N5/PPP2PPP/R1B1K2R w KQkq - 0 8", "e4e5");
484
+ for (const modified of [
485
+ { ...full, futureMeasurement: { value: 42 } },
486
+ { ...full, mover: { ...full.mover, futureIdentity: "some-id" } },
487
+ { ...full, stationarySliderRays: full.stationarySliderRays.map((ray2, index) => index ? ray2 : { ...ray2, futureRay: "retained" }) }
488
+ ]) {
489
+ const projected = compactMechanism(modified, ["g4"]);
490
+ assert.equal(projected.encoding, void 0);
491
+ assert.deepEqual(projected, oldProjection(modified, ["g4"]));
492
+ }
493
+ const encoded = compactMechanism(full, ["g4"]);
494
+ assert.equal(expandMechanismPresentation({ ...encoded, columns: { ...encoded.columns, rays: ["unknown"] } }).encoding, "move-mechanism/1");
495
+ assert.equal(expandMechanismPresentation({ ...encoded, rows: { ...encoded.rows, futureRows: [42] } }).encoding, "move-mechanism/1");
496
+ });
497
+ test("KE-REASON-016/021: row tables reduce repeated geometry bytes across a mixed search packet", () => {
498
+ const moves = [
499
+ "e2e4",
500
+ "e7e5",
501
+ "g1f3",
502
+ "b8c6",
503
+ "f1c4",
504
+ "h7h6",
505
+ "d2d4",
506
+ "e5d4",
507
+ "f3d4",
508
+ "c6d4",
509
+ "d1d4",
510
+ "g8f6",
511
+ "b1c3",
512
+ "b7b6",
513
+ "c3d5",
514
+ "f8c5"
515
+ ];
516
+ const board = new Chess3();
517
+ const baseline = [], encoded = [];
518
+ for (let index = 0; index < moves.length; index++) {
519
+ const uci = moves[index], before = new Chess3(board.fen());
520
+ board.move({ from: uci.slice(0, 2), to: uci.slice(2, 4) });
521
+ const fact = moveMechanismFacts(before, board, uci.slice(0, 2), uci.slice(2, 4));
522
+ const targets = [uci.slice(2, 4), moves[index + 1]?.slice(2, 4)].filter(Boolean);
523
+ baseline.push({ ply: index + 1, mechanism: oldProjection(fact, targets) });
524
+ encoded.push({ ply: index + 1, mechanism: compactMechanism(fact, targets) });
525
+ }
526
+ const originalBytes = JSON.stringify(shareEvidence(baseline)).length;
527
+ const encodedBytes = JSON.stringify(shareEvidence(encoded)).length;
528
+ assert.ok(encodedBytes < originalBytes * 0.75, `${originalBytes} -> ${encodedBytes}`);
529
+ });