kanso 0.1.0__tar.gz

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 (494) hide show
  1. kanso-0.1.0/.github/workflows/ci.yml +49 -0
  2. kanso-0.1.0/.github/workflows/publish.yml +36 -0
  3. kanso-0.1.0/.gitignore +24 -0
  4. kanso-0.1.0/.python-version +1 -0
  5. kanso-0.1.0/AGENTS.md +203 -0
  6. kanso-0.1.0/CHANGELOG.md +44 -0
  7. kanso-0.1.0/CLAUDE.md +1 -0
  8. kanso-0.1.0/LICENSE +202 -0
  9. kanso-0.1.0/PKG-INFO +307 -0
  10. kanso-0.1.0/README.md +282 -0
  11. kanso-0.1.0/docs/adapters.md +418 -0
  12. kanso-0.1.0/docs/backlog.md +46 -0
  13. kanso-0.1.0/docs/cli.md +254 -0
  14. kanso-0.1.0/docs/concepts.md +490 -0
  15. kanso-0.1.0/docs/constructs.md +281 -0
  16. kanso-0.1.0/docs/extensions.md +561 -0
  17. kanso-0.1.0/docs/maintainers.md +225 -0
  18. kanso-0.1.0/docs/workspace.md +737 -0
  19. kanso-0.1.0/pyproject.toml +91 -0
  20. kanso-0.1.0/skills/kanso-release/SKILL.md +27 -0
  21. kanso-0.1.0/src/kanso/__init__.py +11 -0
  22. kanso-0.1.0/src/kanso/certify/__init__.py +1 -0
  23. kanso-0.1.0/src/kanso/certify/certificate.py +202 -0
  24. kanso-0.1.0/src/kanso/certify/plan.py +491 -0
  25. kanso-0.1.0/src/kanso/certify/run.py +819 -0
  26. kanso-0.1.0/src/kanso/classify/__init__.py +42 -0
  27. kanso-0.1.0/src/kanso/classify/classify.py +464 -0
  28. kanso-0.1.0/src/kanso/classify/construct.py +630 -0
  29. kanso-0.1.0/src/kanso/classify/constructs/__init__.py +6 -0
  30. kanso-0.1.0/src/kanso/classify/constructs/allocation.py +19 -0
  31. kanso-0.1.0/src/kanso/classify/constructs/allocation.yaml +8 -0
  32. kanso-0.1.0/src/kanso/classify/constructs/alpha.py +20 -0
  33. kanso-0.1.0/src/kanso/classify/constructs/alpha.yaml +8 -0
  34. kanso-0.1.0/src/kanso/classify/constructs/execution.py +18 -0
  35. kanso-0.1.0/src/kanso/classify/constructs/execution.yaml +8 -0
  36. kanso-0.1.0/src/kanso/classify/constructs/exit.py +19 -0
  37. kanso-0.1.0/src/kanso/classify/constructs/exit.yaml +7 -0
  38. kanso-0.1.0/src/kanso/classify/constructs/filter.py +21 -0
  39. kanso-0.1.0/src/kanso/classify/constructs/filter.yaml +9 -0
  40. kanso-0.1.0/src/kanso/classify/constructs/overlay.py +25 -0
  41. kanso-0.1.0/src/kanso/classify/constructs/overlay.yaml +8 -0
  42. kanso-0.1.0/src/kanso/classify/constructs/sleeve.py +18 -0
  43. kanso-0.1.0/src/kanso/classify/constructs/sleeve.yaml +8 -0
  44. kanso-0.1.0/src/kanso/classify/features.py +251 -0
  45. kanso-0.1.0/src/kanso/cli/__init__.py +12 -0
  46. kanso-0.1.0/src/kanso/cli/align.py +73 -0
  47. kanso-0.1.0/src/kanso/cli/cert.py +209 -0
  48. kanso-0.1.0/src/kanso/cli/classify.py +95 -0
  49. kanso-0.1.0/src/kanso/cli/context.py +50 -0
  50. kanso-0.1.0/src/kanso/cli/data.py +370 -0
  51. kanso-0.1.0/src/kanso/cli/doctor.py +641 -0
  52. kanso-0.1.0/src/kanso/cli/ext.py +254 -0
  53. kanso-0.1.0/src/kanso/cli/hyp.py +180 -0
  54. kanso-0.1.0/src/kanso/cli/inbox.py +88 -0
  55. kanso-0.1.0/src/kanso/cli/main.py +291 -0
  56. kanso-0.1.0/src/kanso/cli/models.py +88 -0
  57. kanso-0.1.0/src/kanso/cli/monitor.py +98 -0
  58. kanso-0.1.0/src/kanso/cli/portfolio.py +368 -0
  59. kanso-0.1.0/src/kanso/cli/render.py +98 -0
  60. kanso-0.1.0/src/kanso/cli/replay.py +258 -0
  61. kanso-0.1.0/src/kanso/cli/research.py +413 -0
  62. kanso-0.1.0/src/kanso/cli/status.py +226 -0
  63. kanso-0.1.0/src/kanso/cli/strat.py +255 -0
  64. kanso-0.1.0/src/kanso/config.py +198 -0
  65. kanso-0.1.0/src/kanso/creds.py +147 -0
  66. kanso-0.1.0/src/kanso/criteria/__init__.py +91 -0
  67. kanso-0.1.0/src/kanso/criteria/context.py +143 -0
  68. kanso-0.1.0/src/kanso/criteria/gates/__init__.py +513 -0
  69. kanso-0.1.0/src/kanso/criteria/gates/daily_loss_kill.py +61 -0
  70. kanso-0.1.0/src/kanso/criteria/gates/fill_quality_drift.py +107 -0
  71. kanso-0.1.0/src/kanso/criteria/gates/live_drift.py +90 -0
  72. kanso-0.1.0/src/kanso/criteria/gates/paper_forward.py +133 -0
  73. kanso-0.1.0/src/kanso/criteria/gates/param_plateau.py +145 -0
  74. kanso-0.1.0/src/kanso/criteria/gates/parity_replay.py +62 -0
  75. kanso-0.1.0/src/kanso/criteria/integrity.py +249 -0
  76. kanso-0.1.0/src/kanso/criteria/library/book_correlation.yaml +8 -0
  77. kanso-0.1.0/src/kanso/criteria/library/bootstrap.yaml +8 -0
  78. kanso-0.1.0/src/kanso/criteria/library/capacity_vs_adv.yaml +8 -0
  79. kanso-0.1.0/src/kanso/criteria/library/cost_stress.yaml +8 -0
  80. kanso-0.1.0/src/kanso/criteria/library/daily_loss_kill.yaml +8 -0
  81. kanso-0.1.0/src/kanso/criteria/library/deflated_sharpe.yaml +8 -0
  82. kanso-0.1.0/src/kanso/criteria/library/embargoed_window.yaml +8 -0
  83. kanso-0.1.0/src/kanso/criteria/library/fill_quality_drift.yaml +8 -0
  84. kanso-0.1.0/src/kanso/criteria/library/live_drift.yaml +8 -0
  85. kanso-0.1.0/src/kanso/criteria/library/marginal_net_edge_bps.yaml +10 -0
  86. kanso-0.1.0/src/kanso/criteria/library/marginal_wf_sharpe.yaml +10 -0
  87. kanso-0.1.0/src/kanso/criteria/library/max_drawdown.yaml +8 -0
  88. kanso-0.1.0/src/kanso/criteria/library/min_trades.yaml +8 -0
  89. kanso-0.1.0/src/kanso/criteria/library/net_edge_bps.yaml +10 -0
  90. kanso-0.1.0/src/kanso/criteria/library/paper_forward.yaml +8 -0
  91. kanso-0.1.0/src/kanso/criteria/library/param_plateau.yaml +8 -0
  92. kanso-0.1.0/src/kanso/criteria/library/parity_replay.yaml +8 -0
  93. kanso-0.1.0/src/kanso/criteria/library/publication_lag.yaml +8 -0
  94. kanso-0.1.0/src/kanso/criteria/library/strategy_integrity.yaml +8 -0
  95. kanso-0.1.0/src/kanso/criteria/library/walk_forward_consistency.yaml +8 -0
  96. kanso-0.1.0/src/kanso/criteria/library/wf_sharpe_net.yaml +10 -0
  97. kanso-0.1.0/src/kanso/criteria/library.py +291 -0
  98. kanso-0.1.0/src/kanso/criteria/objectives.py +206 -0
  99. kanso-0.1.0/src/kanso/criteria/quantities.py +126 -0
  100. kanso-0.1.0/src/kanso/criteria/run.py +148 -0
  101. kanso-0.1.0/src/kanso/data/__init__.py +29 -0
  102. kanso-0.1.0/src/kanso/data/adapters/__init__.py +15 -0
  103. kanso-0.1.0/src/kanso/data/adapters/massive/__init__.py +295 -0
  104. kanso-0.1.0/src/kanso/data/adapters/massive/client.py +468 -0
  105. kanso-0.1.0/src/kanso/data/adapters/massive/conventions.py +553 -0
  106. kanso-0.1.0/src/kanso/data/adapters/massive/corporate_actions.py +384 -0
  107. kanso-0.1.0/src/kanso/data/adapters/massive/entitlement.py +1172 -0
  108. kanso-0.1.0/src/kanso/data/adapters/massive/errors.py +170 -0
  109. kanso-0.1.0/src/kanso/data/adapters/massive/filings.py +472 -0
  110. kanso-0.1.0/src/kanso/data/adapters/massive/financials.py +391 -0
  111. kanso-0.1.0/src/kanso/data/adapters/massive/loaders/__init__.py +71 -0
  112. kanso-0.1.0/src/kanso/data/adapters/massive/loaders/bars.py +772 -0
  113. kanso-0.1.0/src/kanso/data/adapters/massive/loaders/bulk.py +821 -0
  114. kanso-0.1.0/src/kanso/data/adapters/massive/loaders/quotes.py +107 -0
  115. kanso-0.1.0/src/kanso/data/adapters/massive/loaders/trades.py +136 -0
  116. kanso-0.1.0/src/kanso/data/adapters/massive/objectstore.py +729 -0
  117. kanso-0.1.0/src/kanso/data/adapters/massive/reference.py +594 -0
  118. kanso-0.1.0/src/kanso/data/adapters/massive/survey.py +299 -0
  119. kanso-0.1.0/src/kanso/data/catalog.py +409 -0
  120. kanso-0.1.0/src/kanso/data/commands.py +1012 -0
  121. kanso-0.1.0/src/kanso/data/conventions.py +136 -0
  122. kanso-0.1.0/src/kanso/data/instruments.py +850 -0
  123. kanso-0.1.0/src/kanso/data/loader.py +368 -0
  124. kanso-0.1.0/src/kanso/data/loaders/__init__.py +27 -0
  125. kanso-0.1.0/src/kanso/data/loaders/csv_parquet.py +556 -0
  126. kanso-0.1.0/src/kanso/data/loaders/points.py +209 -0
  127. kanso-0.1.0/src/kanso/data/loaders/synthetic.py +453 -0
  128. kanso-0.1.0/src/kanso/data/manifest.py +355 -0
  129. kanso-0.1.0/src/kanso/data/publication.py +280 -0
  130. kanso-0.1.0/src/kanso/data/registry.py +267 -0
  131. kanso-0.1.0/src/kanso/data/snapshot.py +254 -0
  132. kanso-0.1.0/src/kanso/data/types/__init__.py +188 -0
  133. kanso-0.1.0/src/kanso/data/types/corporate_action.py +81 -0
  134. kanso-0.1.0/src/kanso/env/__init__.py +27 -0
  135. kanso-0.1.0/src/kanso/env/envelope.py +269 -0
  136. kanso-0.1.0/src/kanso/env/host.py +349 -0
  137. kanso-0.1.0/src/kanso/env/wheel.py +178 -0
  138. kanso-0.1.0/src/kanso/errors.py +57 -0
  139. kanso-0.1.0/src/kanso/ext.py +179 -0
  140. kanso-0.1.0/src/kanso/hyp/__init__.py +59 -0
  141. kanso-0.1.0/src/kanso/hyp/registry.py +306 -0
  142. kanso-0.1.0/src/kanso/hyp/scaffold.py +139 -0
  143. kanso-0.1.0/src/kanso/hyp/validate.py +339 -0
  144. kanso-0.1.0/src/kanso/inbox/__init__.py +283 -0
  145. kanso-0.1.0/src/kanso/inbox/webhook.py +130 -0
  146. kanso-0.1.0/src/kanso/models/__init__.py +68 -0
  147. kanso-0.1.0/src/kanso/models/anthropic.py +133 -0
  148. kanso-0.1.0/src/kanso/models/call.py +114 -0
  149. kanso-0.1.0/src/kanso/models/jsonschema.py +138 -0
  150. kanso-0.1.0/src/kanso/models/ledger.py +132 -0
  151. kanso-0.1.0/src/kanso/models/mock.py +107 -0
  152. kanso-0.1.0/src/kanso/models/openai_compat.py +131 -0
  153. kanso-0.1.0/src/kanso/models/register.py +113 -0
  154. kanso-0.1.0/src/kanso/models/router.py +284 -0
  155. kanso-0.1.0/src/kanso/models/tasks.py +242 -0
  156. kanso-0.1.0/src/kanso/models/wire.py +135 -0
  157. kanso-0.1.0/src/kanso/monitor/__init__.py +55 -0
  158. kanso-0.1.0/src/kanso/monitor/realised.py +132 -0
  159. kanso-0.1.0/src/kanso/monitor/run.py +483 -0
  160. kanso-0.1.0/src/kanso/monitor/stage.py +64 -0
  161. kanso-0.1.0/src/kanso/nautilus/__init__.py +1 -0
  162. kanso-0.1.0/src/kanso/nautilus/adapters/__init__.py +141 -0
  163. kanso-0.1.0/src/kanso/nautilus/adapters/alpaca/__init__.py +213 -0
  164. kanso-0.1.0/src/kanso/nautilus/adapters/alpaca/config.py +507 -0
  165. kanso-0.1.0/src/kanso/nautilus/adapters/alpaca/data.py +878 -0
  166. kanso-0.1.0/src/kanso/nautilus/adapters/alpaca/execution.py +1203 -0
  167. kanso-0.1.0/src/kanso/nautilus/adapters/alpaca/factory.py +181 -0
  168. kanso-0.1.0/src/kanso/nautilus/adapters/alpaca/parsing.py +861 -0
  169. kanso-0.1.0/src/kanso/nautilus/adapters/alpaca/provider.py +169 -0
  170. kanso-0.1.0/src/kanso/nautilus/adapters/alpaca/tradability.py +548 -0
  171. kanso-0.1.0/src/kanso/nautilus/adapters/alpaca/venue.py +122 -0
  172. kanso-0.1.0/src/kanso/nautilus/backtest.py +1028 -0
  173. kanso-0.1.0/src/kanso/nautilus/facts.py +1477 -0
  174. kanso-0.1.0/src/kanso/nautilus/hooks.py +237 -0
  175. kanso-0.1.0/src/kanso/nautilus/node.py +714 -0
  176. kanso-0.1.0/src/kanso/nautilus/replay_client.py +238 -0
  177. kanso-0.1.0/src/kanso/nautilus/sandbox.py +377 -0
  178. kanso-0.1.0/src/kanso/nautilus/session.py +330 -0
  179. kanso-0.1.0/src/kanso/nautilus/strategy.py +781 -0
  180. kanso-0.1.0/src/kanso/nautilus/venue.py +119 -0
  181. kanso-0.1.0/src/kanso/portfolio/__init__.py +104 -0
  182. kanso-0.1.0/src/kanso/portfolio/capital.py +46 -0
  183. kanso-0.1.0/src/kanso/portfolio/clients.py +272 -0
  184. kanso-0.1.0/src/kanso/portfolio/deploy.py +519 -0
  185. kanso-0.1.0/src/kanso/portfolio/files.py +142 -0
  186. kanso-0.1.0/src/kanso/portfolio/lifecycle.py +129 -0
  187. kanso-0.1.0/src/kanso/portfolio/promote.py +361 -0
  188. kanso-0.1.0/src/kanso/portfolio/records.py +381 -0
  189. kanso-0.1.0/src/kanso/portfolio/show.py +210 -0
  190. kanso-0.1.0/src/kanso/replay/__init__.py +38 -0
  191. kanso-0.1.0/src/kanso/replay/parity.py +203 -0
  192. kanso-0.1.0/src/kanso/replay/record.py +343 -0
  193. kanso-0.1.0/src/kanso/replay/run.py +191 -0
  194. kanso-0.1.0/src/kanso/replay/target.py +269 -0
  195. kanso-0.1.0/src/kanso/research/__init__.py +69 -0
  196. kanso-0.1.0/src/kanso/research/__main__.py +18 -0
  197. kanso-0.1.0/src/kanso/research/align.py +415 -0
  198. kanso-0.1.0/src/kanso/research/daemon.py +547 -0
  199. kanso-0.1.0/src/kanso/research/diff.py +193 -0
  200. kanso-0.1.0/src/kanso/research/driver.py +333 -0
  201. kanso-0.1.0/src/kanso/research/keep.py +82 -0
  202. kanso-0.1.0/src/kanso/research/lanes.py +107 -0
  203. kanso-0.1.0/src/kanso/research/loop.py +891 -0
  204. kanso-0.1.0/src/kanso/research/records.py +291 -0
  205. kanso-0.1.0/src/kanso/research/results.py +50 -0
  206. kanso-0.1.0/src/kanso/research/scheduler.py +254 -0
  207. kanso-0.1.0/src/kanso/schemas/__init__.py +220 -0
  208. kanso-0.1.0/src/kanso/schemas/base.py +120 -0
  209. kanso-0.1.0/src/kanso/schemas/catalogue.py +190 -0
  210. kanso-0.1.0/src/kanso/schemas/certification.py +218 -0
  211. kanso-0.1.0/src/kanso/schemas/duration.py +66 -0
  212. kanso-0.1.0/src/kanso/schemas/envelope.py +58 -0
  213. kanso-0.1.0/src/kanso/schemas/hypothesis.py +239 -0
  214. kanso-0.1.0/src/kanso/schemas/instruments.py +128 -0
  215. kanso-0.1.0/src/kanso/schemas/models.py +141 -0
  216. kanso-0.1.0/src/kanso/schemas/portfolio.py +97 -0
  217. kanso-0.1.0/src/kanso/schemas/run.py +145 -0
  218. kanso-0.1.0/src/kanso/schemas/strategy.py +136 -0
  219. kanso-0.1.0/src/kanso/schemas/venue.py +249 -0
  220. kanso-0.1.0/src/kanso/schemas/yamlio.py +86 -0
  221. kanso-0.1.0/src/kanso/skills/kanso-align/SKILL.md +18 -0
  222. kanso-0.1.0/src/kanso/skills/kanso-certify/SKILL.md +24 -0
  223. kanso-0.1.0/src/kanso/skills/kanso-classify/SKILL.md +21 -0
  224. kanso-0.1.0/src/kanso/skills/kanso-data/SKILL.md +48 -0
  225. kanso-0.1.0/src/kanso/skills/kanso-env/SKILL.md +20 -0
  226. kanso-0.1.0/src/kanso/skills/kanso-hypothesis/SKILL.md +30 -0
  227. kanso-0.1.0/src/kanso/skills/kanso-models/SKILL.md +20 -0
  228. kanso-0.1.0/src/kanso/skills/kanso-promote/SKILL.md +25 -0
  229. kanso-0.1.0/src/kanso/skills/kanso-replay/SKILL.md +21 -0
  230. kanso-0.1.0/src/kanso/skills/kanso-research/SKILL.md +25 -0
  231. kanso-0.1.0/src/kanso/skills/kanso-upstream/SKILL.md +30 -0
  232. kanso-0.1.0/src/kanso/skills_sync.py +84 -0
  233. kanso-0.1.0/src/kanso/state/__init__.py +31 -0
  234. kanso-0.1.0/src/kanso/state/migrations/0001_init.sql +223 -0
  235. kanso-0.1.0/src/kanso/state/migrations/0002_queue.sql +14 -0
  236. kanso-0.1.0/src/kanso/state/store.py +435 -0
  237. kanso-0.1.0/src/kanso/strategy/__init__.py +71 -0
  238. kanso-0.1.0/src/kanso/strategy/composition.py +372 -0
  239. kanso-0.1.0/src/kanso/strategy/files.py +151 -0
  240. kanso-0.1.0/src/kanso/strategy/impl.py +484 -0
  241. kanso-0.1.0/src/kanso/templates/AGENTS.md +20 -0
  242. kanso-0.1.0/src/kanso/templates/CLAUDE.md +1 -0
  243. kanso-0.1.0/src/kanso/templates/demo/hypothesis.yaml +29 -0
  244. kanso-0.1.0/src/kanso/templates/demo/instruments.yaml +17 -0
  245. kanso-0.1.0/src/kanso/templates/demo/loader.yaml +10 -0
  246. kanso-0.1.0/src/kanso/templates/demo/models.yaml +20 -0
  247. kanso-0.1.0/src/kanso/templates/demo/responses.yaml +102 -0
  248. kanso-0.1.0/src/kanso/templates/envelope.yaml +24 -0
  249. kanso-0.1.0/src/kanso/templates/gitignore +13 -0
  250. kanso-0.1.0/src/kanso/templates/hypothesis.yaml +28 -0
  251. kanso-0.1.0/src/kanso/templates/inbox.md +9 -0
  252. kanso-0.1.0/src/kanso/templates/instruments.yaml +15 -0
  253. kanso-0.1.0/src/kanso/templates/kanso.toml +40 -0
  254. kanso-0.1.0/src/kanso/templates/models.yaml +43 -0
  255. kanso-0.1.0/src/kanso/templates/portfolio.yaml +29 -0
  256. kanso-0.1.0/src/kanso/templates/program.md +26 -0
  257. kanso-0.1.0/src/kanso/templates/strategy_modifier.py +29 -0
  258. kanso-0.1.0/src/kanso/templates/strategy_sleeve.py +31 -0
  259. kanso-0.1.0/src/kanso/workspace.py +286 -0
  260. kanso-0.1.0/tests/__init__.py +0 -0
  261. kanso-0.1.0/tests/certify/__init__.py +0 -0
  262. kanso-0.1.0/tests/certify/conftest.py +14 -0
  263. kanso-0.1.0/tests/certify/test_plan.py +824 -0
  264. kanso-0.1.0/tests/certify/test_run.py +867 -0
  265. kanso-0.1.0/tests/classify/__init__.py +0 -0
  266. kanso-0.1.0/tests/classify/conftest.py +150 -0
  267. kanso-0.1.0/tests/classify/test_catalogue.py +174 -0
  268. kanso-0.1.0/tests/classify/test_classify.py +575 -0
  269. kanso-0.1.0/tests/classify/test_classify_features.py +398 -0
  270. kanso-0.1.0/tests/classify/test_compose.py +89 -0
  271. kanso-0.1.0/tests/classify/test_harness.py +190 -0
  272. kanso-0.1.0/tests/classify/test_host_run.py +69 -0
  273. kanso-0.1.0/tests/cli/__init__.py +0 -0
  274. kanso-0.1.0/tests/cli/conftest.py +581 -0
  275. kanso-0.1.0/tests/cli/massive_store.py +134 -0
  276. kanso-0.1.0/tests/cli/massive_wire.py +272 -0
  277. kanso-0.1.0/tests/cli/mocked.py +244 -0
  278. kanso-0.1.0/tests/cli/test_align.py +96 -0
  279. kanso-0.1.0/tests/cli/test_app.py +165 -0
  280. kanso-0.1.0/tests/cli/test_cert.py +391 -0
  281. kanso-0.1.0/tests/cli/test_classify.py +116 -0
  282. kanso-0.1.0/tests/cli/test_data_adapters.py +624 -0
  283. kanso-0.1.0/tests/cli/test_data_backfill.py +216 -0
  284. kanso-0.1.0/tests/cli/test_data_instruments.py +223 -0
  285. kanso-0.1.0/tests/cli/test_data_load.py +271 -0
  286. kanso-0.1.0/tests/cli/test_data_massive.py +291 -0
  287. kanso-0.1.0/tests/cli/test_data_show.py +90 -0
  288. kanso-0.1.0/tests/cli/test_data_spans.py +160 -0
  289. kanso-0.1.0/tests/cli/test_data_sync.py +309 -0
  290. kanso-0.1.0/tests/cli/test_demo.py +145 -0
  291. kanso-0.1.0/tests/cli/test_doctor.py +764 -0
  292. kanso-0.1.0/tests/cli/test_e2e.py +217 -0
  293. kanso-0.1.0/tests/cli/test_env.py +57 -0
  294. kanso-0.1.0/tests/cli/test_execution_clients.py +431 -0
  295. kanso-0.1.0/tests/cli/test_ext.py +564 -0
  296. kanso-0.1.0/tests/cli/test_hyp.py +209 -0
  297. kanso-0.1.0/tests/cli/test_inbox.py +131 -0
  298. kanso-0.1.0/tests/cli/test_init.py +158 -0
  299. kanso-0.1.0/tests/cli/test_migrate.py +60 -0
  300. kanso-0.1.0/tests/cli/test_models.py +87 -0
  301. kanso-0.1.0/tests/cli/test_monitor.py +81 -0
  302. kanso-0.1.0/tests/cli/test_no_git.py +114 -0
  303. kanso-0.1.0/tests/cli/test_portfolio.py +362 -0
  304. kanso-0.1.0/tests/cli/test_render.py +16 -0
  305. kanso-0.1.0/tests/cli/test_replay.py +195 -0
  306. kanso-0.1.0/tests/cli/test_research.py +446 -0
  307. kanso-0.1.0/tests/cli/test_research_daemon.py +167 -0
  308. kanso-0.1.0/tests/cli/test_research_run.py +129 -0
  309. kanso-0.1.0/tests/cli/test_skills.py +66 -0
  310. kanso-0.1.0/tests/cli/test_status.py +168 -0
  311. kanso-0.1.0/tests/cli/test_strat.py +155 -0
  312. kanso-0.1.0/tests/config/__init__.py +0 -0
  313. kanso-0.1.0/tests/config/test_config.py +221 -0
  314. kanso-0.1.0/tests/config/test_creds.py +278 -0
  315. kanso-0.1.0/tests/config/test_ext.py +229 -0
  316. kanso-0.1.0/tests/conftest.py +22 -0
  317. kanso-0.1.0/tests/criteria/__init__.py +0 -0
  318. kanso-0.1.0/tests/criteria/builders.py +140 -0
  319. kanso-0.1.0/tests/criteria/conftest.py +31 -0
  320. kanso-0.1.0/tests/criteria/test_fill_quality_drift.py +221 -0
  321. kanso-0.1.0/tests/criteria/test_gates.py +533 -0
  322. kanso-0.1.0/tests/criteria/test_integrity.py +237 -0
  323. kanso-0.1.0/tests/criteria/test_library.py +346 -0
  324. kanso-0.1.0/tests/criteria/test_objectives.py +179 -0
  325. kanso-0.1.0/tests/criteria/test_param_plateau.py +308 -0
  326. kanso-0.1.0/tests/criteria/test_parity_replay.py +215 -0
  327. kanso-0.1.0/tests/criteria/test_pending_required.py +93 -0
  328. kanso-0.1.0/tests/criteria/test_quantities.py +110 -0
  329. kanso-0.1.0/tests/criteria/test_run.py +129 -0
  330. kanso-0.1.0/tests/data/__init__.py +0 -0
  331. kanso-0.1.0/tests/data/adapters/__init__.py +1 -0
  332. kanso-0.1.0/tests/data/adapters/massive/__init__.py +195 -0
  333. kanso-0.1.0/tests/data/adapters/massive/test_client.py +632 -0
  334. kanso-0.1.0/tests/data/adapters/massive/test_entitlement.py +1193 -0
  335. kanso-0.1.0/tests/data/adapters/massive/test_fundamentals.py +1118 -0
  336. kanso-0.1.0/tests/data/adapters/massive/test_loaders.py +1109 -0
  337. kanso-0.1.0/tests/data/adapters/massive/test_objectstore.py +1811 -0
  338. kanso-0.1.0/tests/data/adapters/massive/test_reference.py +984 -0
  339. kanso-0.1.0/tests/data/adapters/massive/test_survey.py +246 -0
  340. kanso-0.1.0/tests/data/adapters/test_isolation.py +92 -0
  341. kanso-0.1.0/tests/data/catalog/__init__.py +1 -0
  342. kanso-0.1.0/tests/data/catalog/conftest.py +142 -0
  343. kanso-0.1.0/tests/data/catalog/test_catalog.py +396 -0
  344. kanso-0.1.0/tests/data/catalog/test_manifest.py +213 -0
  345. kanso-0.1.0/tests/data/catalog/test_one_checksum.py +71 -0
  346. kanso-0.1.0/tests/data/catalog/test_publication.py +149 -0
  347. kanso-0.1.0/tests/data/catalog/test_snapshot.py +258 -0
  348. kanso-0.1.0/tests/data/instruments/__init__.py +1 -0
  349. kanso-0.1.0/tests/data/instruments/conftest.py +149 -0
  350. kanso-0.1.0/tests/data/instruments/test_build.py +188 -0
  351. kanso-0.1.0/tests/data/instruments/test_checksum.py +76 -0
  352. kanso-0.1.0/tests/data/instruments/test_conventions.py +113 -0
  353. kanso-0.1.0/tests/data/instruments/test_resolve.py +411 -0
  354. kanso-0.1.0/tests/data/loaders/__init__.py +0 -0
  355. kanso-0.1.0/tests/data/loaders/conftest.py +81 -0
  356. kanso-0.1.0/tests/data/loaders/test_catalog_roundtrip.py +136 -0
  357. kanso-0.1.0/tests/data/loaders/test_csv_parquet.py +454 -0
  358. kanso-0.1.0/tests/data/loaders/test_custom_files.py +118 -0
  359. kanso-0.1.0/tests/data/loaders/test_loader.py +189 -0
  360. kanso-0.1.0/tests/data/loaders/test_points.py +64 -0
  361. kanso-0.1.0/tests/data/loaders/test_synthetic.py +331 -0
  362. kanso-0.1.0/tests/data/loaders/test_types.py +149 -0
  363. kanso-0.1.0/tests/env/__init__.py +0 -0
  364. kanso-0.1.0/tests/env/conftest.py +152 -0
  365. kanso-0.1.0/tests/env/test_envelope.py +361 -0
  366. kanso-0.1.0/tests/env/test_host.py +314 -0
  367. kanso-0.1.0/tests/env/test_plan.py +174 -0
  368. kanso-0.1.0/tests/env/test_wheel.py +206 -0
  369. kanso-0.1.0/tests/hyp/__init__.py +0 -0
  370. kanso-0.1.0/tests/hyp/conftest.py +194 -0
  371. kanso-0.1.0/tests/hyp/test_registry.py +368 -0
  372. kanso-0.1.0/tests/hyp/test_scaffold.py +118 -0
  373. kanso-0.1.0/tests/hyp/test_validate.py +589 -0
  374. kanso-0.1.0/tests/inbox/__init__.py +0 -0
  375. kanso-0.1.0/tests/inbox/conftest.py +35 -0
  376. kanso-0.1.0/tests/inbox/test_ack.py +80 -0
  377. kanso-0.1.0/tests/inbox/test_append_only.py +94 -0
  378. kanso-0.1.0/tests/inbox/test_escalate.py +211 -0
  379. kanso-0.1.0/tests/inbox/test_webhook.py +252 -0
  380. kanso-0.1.0/tests/models/__init__.py +0 -0
  381. kanso-0.1.0/tests/models/conftest.py +177 -0
  382. kanso-0.1.0/tests/models/test_anthropic.py +252 -0
  383. kanso-0.1.0/tests/models/test_check.py +152 -0
  384. kanso-0.1.0/tests/models/test_isolation.py +89 -0
  385. kanso-0.1.0/tests/models/test_jsonschema.py +130 -0
  386. kanso-0.1.0/tests/models/test_ledger.py +119 -0
  387. kanso-0.1.0/tests/models/test_mock.py +145 -0
  388. kanso-0.1.0/tests/models/test_openai_compat.py +184 -0
  389. kanso-0.1.0/tests/models/test_register.py +91 -0
  390. kanso-0.1.0/tests/models/test_router.py +424 -0
  391. kanso-0.1.0/tests/models/test_tasks.py +121 -0
  392. kanso-0.1.0/tests/models/test_wire.py +32 -0
  393. kanso-0.1.0/tests/monitor/__init__.py +1 -0
  394. kanso-0.1.0/tests/monitor/builders.py +415 -0
  395. kanso-0.1.0/tests/monitor/conftest.py +29 -0
  396. kanso-0.1.0/tests/monitor/test_live_gates.py +246 -0
  397. kanso-0.1.0/tests/monitor/test_paper_forward.py +165 -0
  398. kanso-0.1.0/tests/monitor/test_realised.py +125 -0
  399. kanso-0.1.0/tests/monitor/test_run.py +575 -0
  400. kanso-0.1.0/tests/nautilus/__init__.py +1 -0
  401. kanso-0.1.0/tests/nautilus/adapters/__init__.py +1 -0
  402. kanso-0.1.0/tests/nautilus/adapters/alpaca/__init__.py +292 -0
  403. kanso-0.1.0/tests/nautilus/adapters/alpaca/test_config.py +651 -0
  404. kanso-0.1.0/tests/nautilus/adapters/alpaca/test_data.py +1340 -0
  405. kanso-0.1.0/tests/nautilus/adapters/alpaca/test_execution.py +1919 -0
  406. kanso-0.1.0/tests/nautilus/adapters/alpaca/test_parsing.py +885 -0
  407. kanso-0.1.0/tests/nautilus/adapters/alpaca/test_tradability.py +682 -0
  408. kanso-0.1.0/tests/nautilus/adapters/test_isolation.py +129 -0
  409. kanso-0.1.0/tests/nautilus/backtest/__init__.py +1 -0
  410. kanso-0.1.0/tests/nautilus/backtest/conftest.py +459 -0
  411. kanso-0.1.0/tests/nautilus/backtest/test_determinism.py +59 -0
  412. kanso-0.1.0/tests/nautilus/backtest/test_extraction.py +363 -0
  413. kanso-0.1.0/tests/nautilus/backtest/test_subprocess.py +188 -0
  414. kanso-0.1.0/tests/nautilus/backtest/test_venue.py +97 -0
  415. kanso-0.1.0/tests/nautilus/backtest/test_window.py +111 -0
  416. kanso-0.1.0/tests/nautilus/strategy/__init__.py +0 -0
  417. kanso-0.1.0/tests/nautilus/strategy/conftest.py +166 -0
  418. kanso-0.1.0/tests/nautilus/strategy/test_config.py +162 -0
  419. kanso-0.1.0/tests/nautilus/strategy/test_hooks.py +187 -0
  420. kanso-0.1.0/tests/nautilus/strategy/test_modifiers.py +499 -0
  421. kanso-0.1.0/tests/nautilus/strategy/test_sleeve.py +548 -0
  422. kanso-0.1.0/tests/nautilus/strategy/test_templates.py +86 -0
  423. kanso-0.1.0/tests/nautilus/test_engine_behaviour.py +92 -0
  424. kanso-0.1.0/tests/nautilus/test_facts.py +98 -0
  425. kanso-0.1.0/tests/portfolio/__init__.py +0 -0
  426. kanso-0.1.0/tests/portfolio/conftest.py +123 -0
  427. kanso-0.1.0/tests/portfolio/test_deploy.py +269 -0
  428. kanso-0.1.0/tests/portfolio/test_lifecycle.py +125 -0
  429. kanso-0.1.0/tests/portfolio/test_node.py +216 -0
  430. kanso-0.1.0/tests/portfolio/test_promote.py +271 -0
  431. kanso-0.1.0/tests/portfolio/test_records.py +253 -0
  432. kanso-0.1.0/tests/portfolio/test_refusals.py +215 -0
  433. kanso-0.1.0/tests/portfolio/test_retire.py +115 -0
  434. kanso-0.1.0/tests/portfolio/test_sandbox.py +489 -0
  435. kanso-0.1.0/tests/portfolio/test_stage_run.py +199 -0
  436. kanso-0.1.0/tests/replay/__init__.py +1 -0
  437. kanso-0.1.0/tests/replay/conftest.py +547 -0
  438. kanso-0.1.0/tests/replay/test_client.py +202 -0
  439. kanso-0.1.0/tests/replay/test_parity.py +241 -0
  440. kanso-0.1.0/tests/replay/test_record.py +222 -0
  441. kanso-0.1.0/tests/replay/test_run.py +325 -0
  442. kanso-0.1.0/tests/replay/test_session.py +261 -0
  443. kanso-0.1.0/tests/replay/test_target.py +300 -0
  444. kanso-0.1.0/tests/research/__init__.py +0 -0
  445. kanso-0.1.0/tests/research/conftest.py +364 -0
  446. kanso-0.1.0/tests/research/mocked.py +218 -0
  447. kanso-0.1.0/tests/research/test_align.py +142 -0
  448. kanso-0.1.0/tests/research/test_attached.py +189 -0
  449. kanso-0.1.0/tests/research/test_daemon.py +434 -0
  450. kanso-0.1.0/tests/research/test_driver.py +264 -0
  451. kanso-0.1.0/tests/research/test_driver_align.py +230 -0
  452. kanso-0.1.0/tests/research/test_driver_diff.py +151 -0
  453. kanso-0.1.0/tests/research/test_keep.py +67 -0
  454. kanso-0.1.0/tests/research/test_lanes.py +65 -0
  455. kanso-0.1.0/tests/research/test_loop.py +472 -0
  456. kanso-0.1.0/tests/research/test_records.py +71 -0
  457. kanso-0.1.0/tests/research/test_results.py +56 -0
  458. kanso-0.1.0/tests/research/test_scheduler.py +271 -0
  459. kanso-0.1.0/tests/schemas/__init__.py +0 -0
  460. kanso-0.1.0/tests/schemas/conftest.py +13 -0
  461. kanso-0.1.0/tests/schemas/strategies.py +601 -0
  462. kanso-0.1.0/tests/schemas/test_base.py +42 -0
  463. kanso-0.1.0/tests/schemas/test_catalogue.py +182 -0
  464. kanso-0.1.0/tests/schemas/test_certification.py +154 -0
  465. kanso-0.1.0/tests/schemas/test_duration.py +78 -0
  466. kanso-0.1.0/tests/schemas/test_envelope.py +70 -0
  467. kanso-0.1.0/tests/schemas/test_hypothesis.py +225 -0
  468. kanso-0.1.0/tests/schemas/test_instruments.py +125 -0
  469. kanso-0.1.0/tests/schemas/test_models.py +108 -0
  470. kanso-0.1.0/tests/schemas/test_portfolio.py +100 -0
  471. kanso-0.1.0/tests/schemas/test_roundtrip.py +102 -0
  472. kanso-0.1.0/tests/schemas/test_run.py +126 -0
  473. kanso-0.1.0/tests/schemas/test_strategy.py +101 -0
  474. kanso-0.1.0/tests/schemas/test_templates.py +51 -0
  475. kanso-0.1.0/tests/schemas/test_venue.py +145 -0
  476. kanso-0.1.0/tests/schemas/test_yamlio.py +78 -0
  477. kanso-0.1.0/tests/state/__init__.py +0 -0
  478. kanso-0.1.0/tests/state/conftest.py +20 -0
  479. kanso-0.1.0/tests/state/test_state_blobs.py +109 -0
  480. kanso-0.1.0/tests/state/test_state_concurrency.py +78 -0
  481. kanso-0.1.0/tests/state/test_state_events.py +55 -0
  482. kanso-0.1.0/tests/state/test_state_migrations.py +287 -0
  483. kanso-0.1.0/tests/strategy/__init__.py +1 -0
  484. kanso-0.1.0/tests/strategy/conftest.py +304 -0
  485. kanso-0.1.0/tests/strategy/test_compose.py +227 -0
  486. kanso-0.1.0/tests/strategy/test_expectation.py +220 -0
  487. kanso-0.1.0/tests/strategy/test_impl.py +334 -0
  488. kanso-0.1.0/tests/workspace/__init__.py +0 -0
  489. kanso-0.1.0/tests/workspace/conftest.py +43 -0
  490. kanso-0.1.0/tests/workspace/test_find.py +109 -0
  491. kanso-0.1.0/tests/workspace/test_init.py +230 -0
  492. kanso-0.1.0/tests/workspace/test_no_git.py +74 -0
  493. kanso-0.1.0/tests/workspace/test_skills_sync.py +123 -0
  494. kanso-0.1.0/uv.lock +1225 -0
@@ -0,0 +1,49 @@
1
+ name: ci
2
+
3
+ # Every milestone is gated on this workflow, so it lands in the first commit.
4
+ # It runs the offline suite only: no credential is available to it and none is added,
5
+ # which is what proves the core works with every vendor credential unset.
6
+
7
+ on:
8
+ push:
9
+ branches: ["main", "feat/**", "fix/**", "docs/**", "chore/**"]
10
+ pull_request:
11
+ branches: ["main"]
12
+
13
+ concurrency:
14
+ group: ci-${{ github.ref }}
15
+ cancel-in-progress: true
16
+
17
+ jobs:
18
+ test:
19
+ name: ${{ matrix.os }} · py${{ matrix.python }}
20
+ runs-on: ${{ matrix.os }}
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ # macOS 26+ arm64 and Linux x86_64 are the supported hosts; the pinned engine
25
+ # publishes no wheel for an older macOS.
26
+ os: [macos-26, ubuntu-24.04]
27
+ python: ["3.12", "3.13"]
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+
31
+ - name: Install uv
32
+ uses: astral-sh/setup-uv@v5
33
+ with:
34
+ enable-cache: true
35
+
36
+ - name: Sync
37
+ run: uv sync --locked --python ${{ matrix.python }}
38
+
39
+ - name: Format
40
+ run: uv run ruff format --check
41
+
42
+ - name: Lint
43
+ run: uv run ruff check
44
+
45
+ - name: Types
46
+ run: uv run mypy src
47
+
48
+ - name: Tests
49
+ run: uv run pytest --cov-fail-under=85
@@ -0,0 +1,36 @@
1
+ name: publish
2
+
3
+ # Trusted publishing: the job requests an OIDC token and stores no credential.
4
+ # The index-side registration must name this repository, this workflow filename
5
+ # and the `pypi` environment exactly; a mismatch fails as an authentication error.
6
+
7
+ on:
8
+ push:
9
+ tags: ["v*.*.*"]
10
+
11
+ jobs:
12
+ publish:
13
+ runs-on: ubuntu-24.04
14
+ environment: pypi
15
+ permissions:
16
+ id-token: write
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Install uv
21
+ uses: astral-sh/setup-uv@v5
22
+
23
+ - name: Tag matches the package version
24
+ run: |
25
+ set -euo pipefail
26
+ tag="${GITHUB_REF_NAME#v}"
27
+ proj=$(uv run python -c "import tomllib,pathlib;print(tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['version'])")
28
+ pkg=$(uv run python -c "import kanso;print(kanso.__version__)")
29
+ echo "tag=$tag project=$proj package=$pkg"
30
+ test "$tag" = "$proj" && test "$tag" = "$pkg"
31
+
32
+ - name: Build
33
+ run: uv build
34
+
35
+ - name: Publish
36
+ uses: pypa/gh-action-pypi-publish@release/v1
kanso-0.1.0/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ # Build and packaging
2
+ dist/
3
+ build/
4
+ *.egg-info/
5
+
6
+ # Credentials — resolved from here at the moment of use, never committed
7
+ .env
8
+ .env.*
9
+
10
+ # Python
11
+ __pycache__/
12
+ *.py[cod]
13
+ .venv/
14
+
15
+ # Tooling caches
16
+ .pytest_cache/
17
+ .mypy_cache/
18
+ .ruff_cache/
19
+ .coverage
20
+ .coverage.*
21
+ htmlcov/
22
+
23
+ # macOS
24
+ .DS_Store
@@ -0,0 +1 @@
1
+ 3.12
kanso-0.1.0/AGENTS.md ADDED
@@ -0,0 +1,203 @@
1
+ # kanso — instructions for changing this package
2
+
3
+ This repository is the `kanso` framework: a released Python package, versioned by semver.
4
+ It is its own reference. `docs/` states what every part of it guarantees and refuses, the
5
+ tests state it again in a form that fails when it stops being true, and the two are changed
6
+ together or not at all. There is no design document, no decision log and no build plan; if
7
+ something is true of kanso and is written down nowhere, that is a gap in `docs/` or in the
8
+ suite, and the fix is to close it rather than to write a note.
9
+
10
+ `docs/maintainers.md` is the other side of this file: repositories, the development loop,
11
+ promoting an extension upstream, releases, and running the daemon as a service. Maintainer
12
+ skills live in `skills/` — link that directory into your tool's skills path.
13
+
14
+ ## The standing invariants
15
+
16
+ These are the properties the rest of the package is built on. Each one would be easy to
17
+ lose in a change that looks local, so each is enforced somewhere you can read.
18
+
19
+ **kanso never invokes git.** No `git` subprocess, in a workspace or anywhere else — no
20
+ `init`, commit, branch, tag, worktree, reset or object write, by itself or on an operator's
21
+ behalf. Committing a workspace is the operator's business; versioning the file research
22
+ mutates is kanso's own, content-addressed in the state store. `tests/workspace/test_no_git.py`
23
+ and `tests/cli/test_no_git.py` spy on every process launch and fail the moment one is git.
24
+
25
+ **The core knows no vendor and no broker.** Every outside party lives in exactly one
26
+ package — `data/adapters/<vendor>/` for data and reference, `nautilus/adapters/<broker>/`
27
+ for execution and live feeds — and nothing outside it names a vendor, an endpoint, a vendor
28
+ field or a vendor symbology. Mapping to engine types and kanso schemas happens at the
29
+ adapter boundary. Provider specifics stay inside `models/` the same way. The isolation
30
+ tests (`tests/data/adapters/`, `tests/nautilus/adapters/`, `tests/models/`) are a source
31
+ scan and an import-graph check, and they read the names from the adapter directories rather
32
+ than from a list, so a new adapter is scanned without anyone remembering to add it.
33
+
34
+ **An adapter is enabled by its credentials, never by installation.** There are no extras.
35
+ The full suite, `kanso doctor` and the demo are green with every vendor and broker
36
+ credential unset, and CI has no credential at all, which is what proves it. A test that
37
+ genuinely needs a real key carries the `live` marker, is deselected by default and never
38
+ runs in CI.
39
+
40
+ **Availability, not observation.** Every catalog point's `ts_init` is the instant its
41
+ information became public and `ts_event` is its economic reference time; `ts_init >=
42
+ ts_event` always, and the engine orders by `ts_init`. Never derive `ts_init` from
43
+ `ts_event` or from ingest time. A delayed dataset whose `ts_init` does not come from a
44
+ declared publication rule is refused at write (`data/publication.py`).
45
+
46
+ **Costs are applied once, by the runner, in the extraction.** Commission, slippage and half
47
+ the spread each side are deducted per fill in `nautilus/backtest.py` and nowhere else. One
48
+ application means one number: a card, a certification gate, a composition expectation and a
49
+ realised paper objective all read the same arithmetic, and a cost model can be re-applied to
50
+ recorded fills without re-running anything. The simulated venue charges nothing to keep it
51
+ that way — and it charges nothing because kanso's resolved instruments leave their maker and
52
+ taker rates at zero, not because the venue is configured fee-free, so an instrument that
53
+ arrives with a non-zero rate double-counts silently.
54
+
55
+ **The embargo is code.** A backtest request may name only a window the hypothesis declares,
56
+ and the card path accepts only the research window. A card runs in a child process with no
57
+ path to any catalog — the parent reads the window and serialises the points across, and the
58
+ child re-checks them against the window it was asked for. Never add a route by which
59
+ research could reach the certification window, and never replace the refusal with an
60
+ instruction to a model.
61
+
62
+ **Only `strategy.py` is mutable by the research loop.** Everything fixed lives in the
63
+ package. A proposal that names another file, does not apply, or changes nothing is a wrong
64
+ answer that takes the retry ladder; it never becomes a card.
65
+
66
+ **Real capital moves only on a named, recorded approval.** `promote --live --as NAME` is the
67
+ only path, `--as` has no default and no environment fallback, and the approval is recorded
68
+ against the exact version before anything moves. Paper promotion and demotion are automatic;
69
+ this one is not, and no convenience is worth making it so.
70
+
71
+ **One strategy class, one data model, one evaluation path.** Backtest, replay, paper and
72
+ live run the same generated implementation, and a version pins the engine version it was
73
+ certified under. `kanso replay parity` compares the two code paths element by element and
74
+ exists to be run at a tolerance of zero.
75
+
76
+ **A run optimises exactly one scalar.** Constraints are gates, never terms in an objective.
77
+
78
+ **Agents decide, the framework evaluates.** Which gates, which thresholds, which constraints
79
+ and which construct are chosen at runtime by a model from catalogues that declare
80
+ capabilities and ranges. There are no default plans, no default thresholds and no non-LLM
81
+ fallback for a decision an agent is supposed to make: with no model configured the step
82
+ exits 2. The framework's own opinions are structural invariants and the construct taxonomy,
83
+ and nothing else.
84
+
85
+ **Runtime dependencies are exhaustive.** `nautilus_trader`, `pydantic`, `typer`, `pyyaml`,
86
+ `httpx`, `numpy`, and the standard library. `pyarrow`, `pandas` and `msgspec` are reachable
87
+ only as the engine's own transitive dependencies and only where its API hands them to you.
88
+ `httpx` serves `models/` only. Adding a runtime dependency is a deliberate change to
89
+ `pyproject.toml` argued in the commit body; an adapter that would need one is not
90
+ admissible.
91
+
92
+ **Pure Python.** kanso ships no compiled artefact of its own. The only Rust it executes is
93
+ NautilusTrader's, through `nautilus_trader.core.nautilus_pyo3` — adapter network I/O uses
94
+ its `HttpClient` and `WebSocketClient` with `Quota` rate limits.
95
+
96
+ **Secrets live only in environment variables**, resolved by standard name from the
97
+ workspace `.env` and then the ambient environment, sent in a request header and never in a
98
+ URL path or query string, because URLs reach logs, manifests and `doctor --report`. No
99
+ credential appears in anything kanso writes.
100
+
101
+ **No notes, learnings, summaries or progress reports** — not in this repository, not in a
102
+ workspace. The tests, the diff, the cards, the certificates and the state store are the
103
+ record.
104
+
105
+ ## Toolchain
106
+
107
+ `uv` for everything.
108
+
109
+ ```bash
110
+ uv sync
111
+ uv run pytest --cov-fail-under=85 # the gate CI runs; drop the flag for a partial run
112
+ uv run ruff format
113
+ uv run ruff check
114
+ uv run mypy src
115
+ ```
116
+
117
+ Python ≥3.12; `nautilus_trader>=1.231.0,<1.232`, one requirement for every supported host
118
+ (macOS 26+ arm64, Linux x86_64). Tests use `pytest`, `pytest-cov` and `hypothesis`, make no
119
+ network call and are deterministic; the `synthetic` loader and the `mock` model protocol are
120
+ the fixtures.
121
+
122
+ ## Conventions
123
+
124
+ - Every CLI command takes `--json` and prints exactly one object under it, exits with the
125
+ codes `docs/cli.md` lists, and has at least one integration test.
126
+ - Every schema is a pydantic v2 model in `schemas/` with one property test.
127
+ - Docstrings state the contract a module implements in words, and record the
128
+ NautilusTrader facts it relies on with the engine version. They never point at a document
129
+ outside this repository.
130
+ - `from __future__ import annotations` everywhere. No `print()` outside `cli/`. Raise
131
+ `kanso.errors.{PreconditionError, ValidationError, ApprovalError}` — each carries the
132
+ message and, wherever there is one to give, a remedy that is a command the reader can run.
133
+ - A new state table ships as a new file in `src/kanso/state/migrations/`, never as an edit
134
+ to an existing one, with the `schema_version` bump beside it.
135
+ - Conventional commits (`feat:`, `fix:`, `test:`, `docs:`, `chore:`) on a branch named for
136
+ the change. Semver per `docs/maintainers.md`.
137
+
138
+ ## Two rules paid for in defects
139
+
140
+ Both were learned the expensive way during the build and are cheap to keep.
141
+
142
+ **A fixture is a claim about the world, and is worth what its evidence is worth.** Eight
143
+ defects in the first data adapter reached a suite of 3,492 tests at 100% line coverage,
144
+ because every fixture recorded what its author expected the vendor to do rather than what
145
+ the vendor was measured doing: an option key asked of the wrong reference endpoint, a
146
+ listing requested under a version prefix that answers 404, a page four times wider than the
147
+ endpoint serves, a signed `Host` forwarded to a transport that sets its own, an empty page
148
+ read as an entitlement refusal — which tells an operator to buy what they already own. Every
149
+ one was invisible offline and obvious in one live call. So: record the measured response,
150
+ say where it came from, and drive an adapter against its real source before calling the work
151
+ done. Coverage tells you which lines ran, never whether the fixture resembles the source.
152
+
153
+ **A test that recomputes a timestamp the product already took is asserting that no clock
154
+ moved between them.** Five did, and one failed CI at 00:13 UTC when a definition was
155
+ resolved either side of midnight and the two checksums differed. Pin the input, freeze the
156
+ clock, or accept either instant the call spanned — never leave it to the hour the suite
157
+ happens to run at.
158
+
159
+ ## Definition of done
160
+
161
+ 1. `uv run ruff format --check`, `uv run ruff check` and `uv run mypy src` clean.
162
+ 2. `uv run pytest` green. The enforced floor is 85% of lines in `src/kanso`; the tree is at
163
+ 100%, and a change that lowers it has shipped lines nothing runs.
164
+ 3. `kanso doctor` green in a fresh workspace, and the demo sequence in `README.md` runs end
165
+ to end with every `KANSO_*` and vendor variable unset.
166
+ 4. `docs/` changed in the same commit as any operator-visible behaviour — a command, a
167
+ workspace file, a refusal, a skill — and the tests with it. The PR body says why.
168
+ 5. CI green on macOS arm64 and Linux x86_64, on both Python versions, before it merges.
169
+
170
+ ## Working style
171
+
172
+ - Small commits, each green. Prefer deleting code to adding it. If a component can be a
173
+ function, it is not a class.
174
+ - When the engine's API is unclear, read the installed source rather than guessing:
175
+ `uv run python -c "import nautilus_trader, inspect; ..."`. Check
176
+ `src/kanso/nautilus/facts.py` first — it asserts what this build relies on, and
177
+ `kanso doctor` re-checks every claim against the installed engine and names the ones that
178
+ no longer hold.
179
+ - **A fixture is a claim about an outside party, and it is worth what its evidence is
180
+ worth.** Eight defects reached a green suite at 100% line coverage during the build
181
+ because the fixtures encoded what an author expected instead of what the vendor did.
182
+ Coverage says which lines ran, never whether the fixture resembles the source. Drive an
183
+ adapter against the real thing before trusting it, and record the measured response.
184
+ - Prose fails the same way. Every command a document shows must have been run, and if the
185
+ code and the explanation disagree, the code is what happened.
186
+
187
+ ## Where things are
188
+
189
+ | directory | what it holds |
190
+ |---|---|
191
+ | `cli/` | every command, its `--json` object and its exit codes |
192
+ | `schemas/` | a pydantic model for every file kanso reads or writes |
193
+ | `state/` | the store and its migrations |
194
+ | `data/` | the catalog, manifests, snapshots, loaders, instruments, `adapters/<vendor>/` |
195
+ | `nautilus/` | the strategy base, the runner, the venue, the node, replay, `facts.py`, `adapters/<broker>/` |
196
+ | `classify/` | the construct catalogue and the classifier |
197
+ | `criteria/` | objectives and gates, with the declared toolbox in `library/` |
198
+ | `hyp/`, `research/` | registration, the loop, the driver, the daemon, alignment |
199
+ | `certify/`, `strategy/` | the planner, certificates, composition and versions |
200
+ | `portfolio/`, `monitor/`, `replay/` | stages, deployment, promotion, surveillance, the two code paths |
201
+ | `models/` | the register, the router, the two wire protocols and the mock |
202
+ | `inbox/` | the five escalation kinds and the append-only file |
203
+ | `skills/`, `templates/` | what ships into an operator's workspace |
@@ -0,0 +1,44 @@
1
+ # Changelog
2
+
3
+ One line per user-visible change, newest release first. The format is the one
4
+ `docs/maintainers.md` §4 and the `kanso-release` skill require; versions are semver.
5
+
6
+ ## Unreleased
7
+
8
+ - `kanso doctor` grades a state database written by a later kanso as a failure rather than reporting it up to date, so it no longer disagrees with every other command about whether a workspace is usable.
9
+
10
+ - `kanso data sync` extends only the **newest** dataset of each series, so a series with a chunked backfill behind it can be continued at all; `--dataset` still names one directly, newest of its series or not.
11
+ - `kanso data instruments resolve` builds the `[data] reference` adapter only once an id is actually left unresolved, so a wholly manual universe resolves with that adapter's credential unset.
12
+ - A baseline that did not run reports the remedy of the failure that ended it — rows the catalog no longer holds send an operator to `kanso data load` — where every cause alike used to say `fix hypotheses/<id>/strategy.py`.
13
+ - `kanso hyp validate` and `kanso hyp add` refuse a construct parameter the construct does not declare, or a value outside its declared set (exit 3); the refusal used to arrive inside a run's first card.
14
+ - `kanso hyp validate` and `kanso hyp add` refuse `portfolio` as a hypothesis id (exit 3): it is how a construct attached to the book names its host.
15
+ - `kanso portfolio deploy` and `kanso replay run --strategy` hash every file under `strategies/<id>/impl/<version>/` against the `strategy_sha` its manifest records, and refuse an edited, truncated or deleted source by name (exit 3), naming the certified copy to restore it from.
16
+ - `kanso portfolio show` reads `portfolio.yaml` against the record: a stage entry no deployment wrote prints as `not deployed · in portfolio.yaml only`, carries `"recorded": false` under `--json`, and counts towards neither the stage's allocation nor its P&L nor whether its node is up.
17
+ - `kanso cert plan` warns when the paper window the plan implies is under a tenth of the certification window the hypothesis declares, and pins the plan either way; `warnings` under `--json`.
18
+ - A `kanso_ext` module declaring `gates` or `objectives` in `PROVIDES` is refused where it is declared: no registry reads either kind, and a criterion is written in the package.
19
+ - `kanso doctor`'s shadow check reads one registry per kind a declaration may carry — the packaged constructs, the custom data types and the framework's own `sandbox` execution client included — where it read three kinds out of seven.
20
+ - `[adapters.alpaca] poll_interval_s` sets the live feed's sweep cadence, `1` to `3600` seconds and still 15 by default, refused out of range when the table is read; it was a constructor argument no workspace could reach.
21
+
22
+ ## v0.1.0 — 2026-09-06
23
+
24
+ First release.
25
+
26
+ - `kanso init [--demo]`: a workspace is a plain directory; `--demo` runs end to end with no credential of any kind.
27
+ - `kanso doctor [--report] [--check-adapters]`: thirteen checks over the workspace, the install, the engine, the credentials, the adapters, the execution clients and the lanes.
28
+ - Data: `data load`, `show`, `snapshot`, `backfill`, `sync`, `instruments resolve|show`, `adapters [--check]`; one catalog, manifests recording the span a source *served*, immutable snapshots.
29
+ - Availability: every point carries `ts_init` (public) and `ts_event` (economic), `ts_init >= ts_event`; a delayed dataset with no declared publication rule is refused at write.
30
+ - Hypotheses: `hyp new|validate|add|show|retire` and `classify`; a hypothesis is pinned by the sha256 of its bytes and its progress lives in `state.db`.
31
+ - Constructs: seven in the catalogue, four runnable — `sleeve`, `filter`, `overlay` on a sleeve, `exit`; `alpha`, `execution` and portfolio-hosted `allocation` classify and refuse at `research begin` naming their seam.
32
+ - Research: `research begin|card|run|end|show`, the keep rule with its noise floor and complexity clause, `align check`, and the daemon (`research start|stop|status|queue`).
33
+ - The embargo is code: a card runs in a child process with no path to any catalog, and the `strategy_integrity` syntax-tree check runs before the backtest.
34
+ - Certification: `cert plan|run|show`; no default plan and no non-LLM fallback, gates chosen at runtime inside the toolbox's declared ranges, certificates immutable and pinned to plan, snapshot and engine version.
35
+ - Strategies and the portfolio: `strat compose|show|retire`, `portfolio show|clients|deploy`, `promote --live --as NAME`, `demote`, `monitor run`; one generated `impl/<version>/` loaded by backtest, replay and node alike.
36
+ - Real capital moves only on a named, recorded approval; `deploy` refuses six things with exit 2 and two with exit 4.
37
+ - Replay: `replay run|parity|show`, comparing the live and research code paths element by element at a tolerance meant to be zero.
38
+ - Models: `models check`, a register routed by task class and tier, every call ledgered including a retry's failed attempts.
39
+ - Operating: `status`, `inbox [ack]`, `migrate`, `skills sync`, `env detect`, `ext show`.
40
+ - Adapters: one first-party data vendor and one first-party broker, both enabled by their credentials and never by installation; the core knows neither.
41
+ - Extensions: `kanso_ext/` provides loaders, constructs, custom data types, data adapters and execution clients; a packaged id always wins.
42
+ - Eleven operator skills and the workspace templates ship inside the wheel.
43
+ - Python ≥3.12 on macOS 26+ arm64 and Linux x86_64; `nautilus_trader>=1.231.0,<1.232`; no compiled artefact of kanso's own.
44
+ - A state database this kanso cannot correctly write is refused in both directions, by the command layer and by the daemon entry point a service unit starts: behind the package names the migration to run, ahead of it names how far, and neither is silently written to.
kanso-0.1.0/CLAUDE.md ADDED
@@ -0,0 +1 @@
1
+ @AGENTS.md
kanso-0.1.0/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.