bantamkit 0.35.2__tar.gz → 0.35.4__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 (233) hide show
  1. {bantamkit-0.35.2 → bantamkit-0.35.4}/PKG-INFO +107 -5
  2. {bantamkit-0.35.2 → bantamkit-0.35.4}/README.md +104 -3
  3. bantamkit-0.35.4/_assets/tools/shiftwork_clock_in.json +37 -0
  4. bantamkit-0.35.4/_assets/tools/shiftwork_clock_out.json +150 -0
  5. bantamkit-0.35.4/_assets/tools/shiftwork_plan.json +25 -0
  6. {bantamkit-0.35.2 → bantamkit-0.35.4}/pyproject.toml +10 -2
  7. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/__init__.py +1 -1
  8. bantamkit-0.35.4/src/bantamkit/hookadapter.py +2084 -0
  9. bantamkit-0.35.4/src/bantamkit/hostinstall.py +722 -0
  10. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/mcpserver.py +328 -2
  11. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/dream.py +5 -5
  12. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/store.py +25 -9
  13. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/selfupdate.py +22 -2
  14. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/shiftwork.py +172 -61
  15. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/updatecheck.py +78 -16
  16. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/served-tool-surface.json +78 -11
  17. bantamkit-0.35.4/tests/test_hookadapter.py +1262 -0
  18. bantamkit-0.35.4/tests/test_hostinstall_hooks.py +1033 -0
  19. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_mcpserver.py +22 -0
  20. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory.py +1 -1
  21. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory_dream.py +3 -3
  22. bantamkit-0.35.4/tests/test_nativeexport.py +830 -0
  23. bantamkit-0.35.4/tests/test_readme_separation.py +331 -0
  24. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_selfupdate.py +36 -10
  25. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_shiftwork.py +330 -2
  26. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_tool_manifest.py +48 -1
  27. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_updatecheck.py +86 -4
  28. bantamkit-0.35.2/_assets/tools/shiftwork_clock_in.json +0 -25
  29. bantamkit-0.35.2/_assets/tools/shiftwork_clock_out.json +0 -95
  30. bantamkit-0.35.2/_assets/tools/shiftwork_plan.json +0 -25
  31. bantamkit-0.35.2/src/bantamkit/hostinstall.py +0 -296
  32. {bantamkit-0.35.2 → bantamkit-0.35.4}/.gitignore +0 -0
  33. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/contracts/default.yaml +0 -0
  34. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/manifest.yaml +0 -0
  35. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/HISTORY.md +0 -0
  36. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/README.md +0 -0
  37. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/docs/architecture.md +0 -0
  38. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/docs/runbook.md +0 -0
  39. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/issues/142-settlement-timeout.md +0 -0
  40. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/patches/0009-retry-budget.patch +0 -0
  41. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/__init__.py +0 -0
  42. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/config.py +0 -0
  43. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/errors.py +0 -0
  44. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/posting.py +0 -0
  45. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/registry.py +0 -0
  46. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/report.py +0 -0
  47. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/retry.py +0 -0
  48. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/settle.py +0 -0
  49. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/validate.py +0 -0
  50. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/tests/test_posting.py +0 -0
  51. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/tests/test_settle.py +0 -0
  52. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-error-contract.yaml +0 -0
  53. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-handler-map.yaml +0 -0
  54. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-patch-before-after.yaml +0 -0
  55. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-retry-attempts.yaml +0 -0
  56. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-settlement-config.yaml +0 -0
  57. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-symbol-home.yaml +0 -0
  58. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-trace-blame.yaml +0 -0
  59. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-unread-key.yaml +0 -0
  60. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-large-in-137.yaml +0 -0
  61. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-large-in-359.yaml +0 -0
  62. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-large-in-372.yaml +0 -0
  63. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-large-out-11764.yaml +0 -0
  64. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-large-out-4137.yaml +0 -0
  65. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-large-out-8022.yaml +0 -0
  66. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-small-137.yaml +0 -0
  67. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-small-261.yaml +0 -0
  68. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-small-388.yaml +0 -0
  69. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/fixtures/.gitkeep +0 -0
  70. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/fixtures/catalog.json +0 -0
  71. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/perturbations/task-completion.yaml +0 -0
  72. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/.gitkeep +0 -0
  73. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/extract-contact.yaml +0 -0
  74. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/extract-invoice.yaml +0 -0
  75. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/extract-order.yaml +0 -0
  76. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/extract-schedule.yaml +0 -0
  77. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/extract-versions.yaml +0 -0
  78. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/nav-prod-port.yaml +0 -0
  79. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/nav-release-bundle.yaml +0 -0
  80. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-audit-retention.yaml +0 -0
  81. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-cache-ttl.yaml +0 -0
  82. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-db-port.yaml +0 -0
  83. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-deploy.yaml +0 -0
  84. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-env-endpoint.yaml +0 -0
  85. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-oncall-rotation.yaml +0 -0
  86. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-oncall.yaml +0 -0
  87. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-org-quota.yaml +0 -0
  88. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-owner.yaml +0 -0
  89. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/shop-basket-total.yaml +0 -0
  90. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/shop-cheapest.yaml +0 -0
  91. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/shop-compare.yaml +0 -0
  92. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/shop-gadget-value.yaml +0 -0
  93. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/shop-stock-total.yaml +0 -0
  94. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/shop-total.yaml +0 -0
  95. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/pricing/default.json +0 -0
  96. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/profiles/default.yaml +0 -0
  97. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/profiles/patient.yaml +0 -0
  98. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/rubrics/.gitkeep +0 -0
  99. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/rubrics/code-quality.yaml +0 -0
  100. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/rubrics/grounded-completion.yaml +0 -0
  101. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/rubrics/task-completion.yaml +0 -0
  102. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/schemas/shiftwork-checkpoint.json +0 -0
  103. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/skills/.gitkeep +0 -0
  104. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/skills/file-graph.md +0 -0
  105. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/skills/memory.md +0 -0
  106. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/.gitkeep +0 -0
  107. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/bantamkit_read.json +0 -0
  108. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/bantamkit_status.json +0 -0
  109. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/build_identity.json +0 -0
  110. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/document_list.json +0 -0
  111. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/document_read.json +0 -0
  112. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/file_graph.json +0 -0
  113. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/memory_compact.json +0 -0
  114. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/memory_dream.json +0 -0
  115. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/memory_recall.json +0 -0
  116. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/memory_save.json +0 -0
  117. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/repo_map.json +0 -0
  118. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/shiftwork_status.json +0 -0
  119. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/skill_audit.json +0 -0
  120. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/token_ledger.json +0 -0
  121. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/validate_json.json +0 -0
  122. {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/work_plan.json +0 -0
  123. {bantamkit-0.35.2 → bantamkit-0.35.4}/hatch_build.py +0 -0
  124. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/agent.py +0 -0
  125. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/assets.py +0 -0
  126. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/budget.py +0 -0
  127. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/client.py +0 -0
  128. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/contract.py +0 -0
  129. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/criticreplay.py +0 -0
  130. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/critique.py +0 -0
  131. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/docmanifest.py +0 -0
  132. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/docread.py +0 -0
  133. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/evalrun.py +0 -0
  134. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/eventlog.py +0 -0
  135. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/filegraph.py +0 -0
  136. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/loopguard.py +0 -0
  137. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/mcpreport.py +0 -0
  138. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/__init__.py +0 -0
  139. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/__main__.py +0 -0
  140. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/component.py +0 -0
  141. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/divergence.py +0 -0
  142. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/layers.py +0 -0
  143. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/pdfread.py +0 -0
  144. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/pricing.py +0 -0
  145. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/profile.py +0 -0
  146. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/repomap.py +0 -0
  147. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/skillaudit.py +0 -0
  148. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/statusline.py +0 -0
  149. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/structured.py +0 -0
  150. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/textutil.py +0 -0
  151. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/tokenledger.py +0 -0
  152. {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/workplan.py +0 -0
  153. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/cli_exit_status_probe.py +0 -0
  154. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/conftest.py +0 -0
  155. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/bad-crc.docx +0 -0
  156. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/charref-4301-digits.html +0 -0
  157. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/charset-table.json +0 -0
  158. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/compression-method-9.docx +0 -0
  159. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/corrupt-deflate.docx +0 -0
  160. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/encrypted-member.docx +0 -0
  161. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/encrypted-mimetype.odt +0 -0
  162. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/eszett-cell-ref.xlsx +0 -0
  163. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/internal-dtd-entity.docx +0 -0
  164. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/rfc2231-charset.eml +0 -0
  165. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/rfc822-nested-twice.eml +0 -0
  166. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/unicode-digit-shared-string.xlsx +0 -0
  167. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/x-uuencode.eml +0 -0
  168. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/f8404ab-perturbation-baseline.json +0 -0
  169. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/platform-assumption-baseline.json +0 -0
  170. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/docread_fixtures.py +0 -0
  171. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/perturbation_baseline_harness.py +0 -0
  172. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/rbp16_effect_probe.py +0 -0
  173. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/rbp18_payload_probe.py +0 -0
  174. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_adapter.py +0 -0
  175. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_agent.py +0 -0
  176. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_amendguard.py +0 -0
  177. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_bantamkit_gitignore.py +0 -0
  178. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_bantamkit_read_tool.py +0 -0
  179. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_budget.py +0 -0
  180. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_build_identity.py +0 -0
  181. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_client.py +0 -0
  182. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_compaction_corpus_survey.py +0 -0
  183. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_conformance.py +0 -0
  184. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_conformance_harness_resilience.py +0 -0
  185. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_conformance_suite_table_gate.py +0 -0
  186. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_contract_fanout.py +0 -0
  187. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_criticreplay.py +0 -0
  188. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_critique.py +0 -0
  189. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_doc_commands_gate.py +0 -0
  190. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_docread.py +0 -0
  191. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_docread_ceilings.py +0 -0
  192. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_document_manifest_parity.py +0 -0
  193. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_document_setup.py +0 -0
  194. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_document_tasks.py +0 -0
  195. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_document_tools.py +0 -0
  196. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_encoding_gate.py +0 -0
  197. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_evalrun.py +0 -0
  198. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_eventlog.py +0 -0
  199. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_field_program_gates.py +0 -0
  200. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_field_programs.py +0 -0
  201. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_filegraph.py +0 -0
  202. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_hostinstall.py +0 -0
  203. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_install_shape.py +0 -0
  204. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_ladder_statistics.py +0 -0
  205. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_launcher_which.py +0 -0
  206. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_layers.py +0 -0
  207. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_loopguard.py +0 -0
  208. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_mcp_endpoint.py +0 -0
  209. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_mcpdrift.py +0 -0
  210. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_mcpreport.py +0 -0
  211. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory_compact_tool.py +0 -0
  212. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory_component.py +0 -0
  213. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory_divergence.py +0 -0
  214. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory_layers.py +0 -0
  215. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory_store_tripwire.py +0 -0
  216. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_mutmatrix.py +0 -0
  217. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_newline_gate.py +0 -0
  218. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_packaging.py +0 -0
  219. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_pdfread.py +0 -0
  220. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_pinharness_ledger.py +0 -0
  221. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_platform_assumption_gate.py +0 -0
  222. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_pricing.py +0 -0
  223. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_repo_map_tool.py +0 -0
  224. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_repomap.py +0 -0
  225. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_served_tool_count_records.py +0 -0
  226. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_skillaudit.py +0 -0
  227. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_status_surface.py +0 -0
  228. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_statusline.py +0 -0
  229. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_structured.py +0 -0
  230. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_thread_exception_gate.py +0 -0
  231. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_tokenledger.py +0 -0
  232. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_version_agreement.py +0 -0
  233. {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_workplan.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bantamkit
3
- Version: 0.35.2
3
+ Version: 0.35.4
4
4
  Summary: Memory MCP server for Claude Code, Cursor, VS Code Copilot and Claude Desktop, plus a Python library that lifts small-model agents. Install once, run offline.
5
5
  Project-URL: Homepage, https://github.com/Ink01101011/bantamkit
6
6
  Project-URL: Repository, https://github.com/Ink01101011/bantamkit
@@ -19,11 +19,12 @@ Requires-Dist: httpx>=0.27
19
19
  Requires-Dist: jsonschema>=4.21
20
20
  Requires-Dist: pyyaml>=6.0
21
21
  Provides-Extra: dev
22
+ Requires-Dist: build>=1.0; extra == 'dev'
22
23
  Requires-Dist: hatchling>=1.24; extra == 'dev'
23
24
  Requires-Dist: pytest>=8.0; extra == 'dev'
24
25
  Requires-Dist: ruff>=0.4; extra == 'dev'
25
26
  Provides-Extra: mcp
26
- Requires-Dist: mcp<3,>=2.0; extra == 'mcp'
27
+ Requires-Dist: mcp<2.1,>=2.0; extra == 'mcp'
27
28
  Description-Content-Type: text/markdown
28
29
 
29
30
  # bantamkit — memory MCP server for Claude Code, Cursor, VS Code Copilot and Claude Desktop (Python)
@@ -39,6 +40,10 @@ The same server in pure Node is on **npm** as
39
40
  disk and a conformance suite holds them to the same answers, so install whichever your host makes
40
41
  easy.
41
42
 
43
+ **This page is the PyPI package's.** Every command on it runs `bantamkit` from PyPI. The npm
44
+ package is named where the two differ, but its own install, update and CLI commands live on
45
+ [its page](https://www.npmjs.com/package/bantamkit-mcp); run them here and you get nothing.
46
+
42
47
  ## Contents
43
48
 
44
49
  | Topic | What you'll find |
@@ -60,6 +65,7 @@ easy.
60
65
  | [The asset pack](#the-asset-pack) | `--assets-root`, `BANTAMKIT_ASSETS` |
61
66
  | [The operator CLI: `python -m bantamkit.memory`](#the-operator-cli-python--m-bantamkitmemory) | status, lint, compact, archived, archive, restore |
62
67
  | [Where the Python and Node servers differ](#where-the-python-and-node-servers-differ) | One store; pdf/.doc/.rtf, CLI name, `build_id` |
68
+ | [Module API](#module-api) | `import bantamkit`: the library half, measured from the wheel |
63
69
  | [Development](#development) | Clone, test, lint, conformance |
64
70
  | [Documentation](#documentation) | The full docs on GitHub |
65
71
 
@@ -97,9 +103,9 @@ CPU architecture and Python minor version** (some wheels, such as `pydantic_core
97
103
  one platform only), copy `wheels/` across, and install from it:
98
104
 
99
105
  ```bash
100
- python -m pip download "bantamkit[mcp]==0.35.2" -d wheels
106
+ python -m pip download "bantamkit[mcp]==0.35.4" -d wheels
101
107
  python -m venv <env>
102
- <env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.35.2"
108
+ <env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.35.4"
103
109
  <env>/bin/bantamkit-mcp --install cursor
104
110
  ```
105
111
 
@@ -132,7 +138,10 @@ or re-run. The entry's `command` and `args` depend on the install route:
132
138
  |---|---|---|
133
139
  | Python venv, install once | `/absolute/path/to/env/bin/bantamkit-mcp` | `[]` |
134
140
  | pipx at every launch | `pipx` | `["run", "--spec", "bantamkit[mcp]", "bantamkit-mcp"]` |
135
- | npm, install once | see the [npm package](https://www.npmjs.com/package/bantamkit-mcp) | |
141
+
142
+ Both rows are PyPI installs. The npm package records a different `command` and `args`, written
143
+ on [its page](https://www.npmjs.com/package/bantamkit-mcp); the two shapes are not
144
+ interchangeable.
136
145
 
137
146
  To check a recorded command, run it in a terminal: with nothing on stdin it prints
138
147
  `usage: bantamkit-mcp …`.
@@ -338,6 +347,99 @@ a conformance case compares their answers. Three differences are deliberate, eac
338
347
  - **`build_id`** hashes the executing tree, so it differs by construction; `assets_digest` is
339
348
  identical, and that is the one that carries meaning.
340
349
 
350
+ ## Module API
351
+
352
+ The package is a server first, but it is importable too: `import bantamkit` is a supported call,
353
+ and the names behind it are part of what is published.
354
+
355
+ Everything in this section was measured against the **wheel**, not the source tree: a
356
+ `bantamkit-0.35.3-py3-none-any.whl` built with `pip wheel --no-deps --no-build-isolation`,
357
+ installed into a throwaway venv with `--no-index --no-deps`, and imported from a working
358
+ directory outside the checkout (2026-09-21). A name that only exists in `src/` is not API; this
359
+ is what an importer gets.
360
+
361
+ **There is no `exports` map in Python, so nothing is sealed.** The wheel carries **31** modules
362
+ and every one is deep-importable — `from bantamkit.mcpserver import main` resolves, and so does
363
+ `from bantamkit.memory import MemoryStore`. That is the opposite of the npm package, which
364
+ declares a single `.` entry point and refuses every deep import with
365
+ `ERR_PACKAGE_PATH_NOT_EXPORTED`. Only the names below are *intended* as API; the rest are
366
+ reachable because Python has no way to say otherwise.
367
+
368
+ **`import bantamkit` binds 45 names, of which 30 are values.** The other 15 are submodules bound
369
+ as a side effect of the package's own imports (`agent`, `assets`, `budget`, `client`, `contract`,
370
+ `critique`, `docmanifest`, `docread`, `evalrun`, `filegraph`, `loopguard`, `memory`, `pdfread`,
371
+ `profile`, `textutil`). There is no `__all__`, so `from bantamkit import *` takes all 45.
372
+
373
+ | Module behind it | What it is | Names |
374
+ | --- | --- | --- |
375
+ | `bantamkit.agent` | the tool-calling loop | `Agent`, `AgentResult`, `MaxTurnsExceeded`, `ToolDef` |
376
+ | `bantamkit.client` | the OpenAI-compatible transport and its wire types | `APIError`, `BantamError`, `Message`, `ModelClient`, `OpenAICompatible`, `Response`, `Tool`, `ToolCall`, `TransportError`, `Usage` |
377
+ | `bantamkit.critique` | the critique gate and its rubrics | `CritiqueExhausted`, `CritiqueGate`, `GroundedCritiqueGate`, `Rubric`, `load_rubric` |
378
+ | `bantamkit.evalrun` | the suite runner | `CONFIGS`, `format_report`, `run_suite` |
379
+ | `bantamkit.structured` | schema-constrained output | `StructuredOutputError`, `structured` |
380
+ | `bantamkit.contract` | JSON out of model prose, and evidence rendering | `extract_json`, `render_evidence` |
381
+ | `bantamkit.loopguard` | the repetition cut-off | `LoopGuard` |
382
+ | `bantamkit.filegraph` | the file-access graph | `FileAccessGraph` |
383
+ | `bantamkit.memory` | the memory store | `Memory`, `MemoryStore` |
384
+ | **9 modules** | | **30 values, no `__all__`** |
385
+
386
+ **This is not the npm package's export surface.** Both runtimes serve the same fourteen MCP
387
+ tools, but what each one exports *to an importer* is a different product: here it is the
388
+ agent/critique/eval library above; there it is the memory store, the asset pack, the event log,
389
+ the shift-work tools and a set of CPython-semantics shims — 139 values behind one entry point. Of
390
+ these 30 names exactly **three** are spelled the same on the npm side (`BantamError`, `Memory`,
391
+ `MemoryStore`), and a spelling is not a promise about behaviour. A parity claim about the MCP
392
+ tools is not a parity claim about these.
393
+
394
+ **A worked start.** Copy-paste examples:
395
+ [`examples/`](https://github.com/Ink01101011/bantamkit/tree/main/examples).
396
+
397
+ ```python
398
+ from bantamkit import Agent, CritiqueGate, Memory, OpenAICompatible, Tool, ToolDef
399
+
400
+ client = OpenAICompatible(base_url="http://localhost:11434/v1", model="qwen2.5:7b-instruct")
401
+
402
+ price_lookup = ToolDef(
403
+ tool=Tool(
404
+ name="price_lookup",
405
+ description="Get the unit price of an item",
406
+ parameters={
407
+ "type": "object",
408
+ "required": ["item"],
409
+ "properties": {"item": {"type": "string"}},
410
+ },
411
+ ),
412
+ handler=lambda item: f"{item} price: 25",
413
+ )
414
+
415
+ agent = Agent(client=client, tools=[price_lookup]).use(
416
+ Memory(store="./.bantam-memory"),
417
+ CritiqueGate("task-completion"),
418
+ )
419
+
420
+ result = agent.run("What does a widget cost? Remember it for next time.")
421
+ print(result.output, result.usage.total)
422
+ ```
423
+
424
+ Which options are worth attaching, measured over 528 runs per model:
425
+ [docs/usage.md → Recommended defaults](https://github.com/Ink01101011/bantamkit/blob/main/docs/usage.md#recommended-defaults).
426
+
427
+ **Rerun the numbers.** Against the published wheel, in a throwaway venv:
428
+
429
+ ```bash
430
+ python -m venv /tmp/bk && /tmp/bk/bin/pip install bantamkit
431
+ /tmp/bk/bin/python -c "import bantamkit; print(len([n for n in dir(bantamkit) if not n.startswith('_')]))"
432
+ ```
433
+
434
+ It prints `45`. The 30 values alone, without the submodules:
435
+
436
+ ```bash
437
+ /tmp/bk/bin/python -c "import bantamkit, types; print(sorted(n for n in dir(bantamkit) if not n.startswith('_') and not isinstance(getattr(bantamkit, n), types.ModuleType)))"
438
+ ```
439
+
440
+ Both numbers move whenever `src/bantamkit/__init__.py` does, which is why they are quoted with
441
+ the command that prints them rather than kept in prose.
442
+
341
443
  ## Development
342
444
 
343
445
  ```bash
@@ -11,6 +11,10 @@ The same server in pure Node is on **npm** as
11
11
  disk and a conformance suite holds them to the same answers, so install whichever your host makes
12
12
  easy.
13
13
 
14
+ **This page is the PyPI package's.** Every command on it runs `bantamkit` from PyPI. The npm
15
+ package is named where the two differ, but its own install, update and CLI commands live on
16
+ [its page](https://www.npmjs.com/package/bantamkit-mcp); run them here and you get nothing.
17
+
14
18
  ## Contents
15
19
 
16
20
  | Topic | What you'll find |
@@ -32,6 +36,7 @@ easy.
32
36
  | [The asset pack](#the-asset-pack) | `--assets-root`, `BANTAMKIT_ASSETS` |
33
37
  | [The operator CLI: `python -m bantamkit.memory`](#the-operator-cli-python--m-bantamkitmemory) | status, lint, compact, archived, archive, restore |
34
38
  | [Where the Python and Node servers differ](#where-the-python-and-node-servers-differ) | One store; pdf/.doc/.rtf, CLI name, `build_id` |
39
+ | [Module API](#module-api) | `import bantamkit`: the library half, measured from the wheel |
35
40
  | [Development](#development) | Clone, test, lint, conformance |
36
41
  | [Documentation](#documentation) | The full docs on GitHub |
37
42
 
@@ -69,9 +74,9 @@ CPU architecture and Python minor version** (some wheels, such as `pydantic_core
69
74
  one platform only), copy `wheels/` across, and install from it:
70
75
 
71
76
  ```bash
72
- python -m pip download "bantamkit[mcp]==0.35.2" -d wheels
77
+ python -m pip download "bantamkit[mcp]==0.35.4" -d wheels
73
78
  python -m venv <env>
74
- <env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.35.2"
79
+ <env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.35.4"
75
80
  <env>/bin/bantamkit-mcp --install cursor
76
81
  ```
77
82
 
@@ -104,7 +109,10 @@ or re-run. The entry's `command` and `args` depend on the install route:
104
109
  |---|---|---|
105
110
  | Python venv, install once | `/absolute/path/to/env/bin/bantamkit-mcp` | `[]` |
106
111
  | pipx at every launch | `pipx` | `["run", "--spec", "bantamkit[mcp]", "bantamkit-mcp"]` |
107
- | npm, install once | see the [npm package](https://www.npmjs.com/package/bantamkit-mcp) | |
112
+
113
+ Both rows are PyPI installs. The npm package records a different `command` and `args`, written
114
+ on [its page](https://www.npmjs.com/package/bantamkit-mcp); the two shapes are not
115
+ interchangeable.
108
116
 
109
117
  To check a recorded command, run it in a terminal: with nothing on stdin it prints
110
118
  `usage: bantamkit-mcp …`.
@@ -310,6 +318,99 @@ a conformance case compares their answers. Three differences are deliberate, eac
310
318
  - **`build_id`** hashes the executing tree, so it differs by construction; `assets_digest` is
311
319
  identical, and that is the one that carries meaning.
312
320
 
321
+ ## Module API
322
+
323
+ The package is a server first, but it is importable too: `import bantamkit` is a supported call,
324
+ and the names behind it are part of what is published.
325
+
326
+ Everything in this section was measured against the **wheel**, not the source tree: a
327
+ `bantamkit-0.35.3-py3-none-any.whl` built with `pip wheel --no-deps --no-build-isolation`,
328
+ installed into a throwaway venv with `--no-index --no-deps`, and imported from a working
329
+ directory outside the checkout (2026-09-21). A name that only exists in `src/` is not API; this
330
+ is what an importer gets.
331
+
332
+ **There is no `exports` map in Python, so nothing is sealed.** The wheel carries **31** modules
333
+ and every one is deep-importable — `from bantamkit.mcpserver import main` resolves, and so does
334
+ `from bantamkit.memory import MemoryStore`. That is the opposite of the npm package, which
335
+ declares a single `.` entry point and refuses every deep import with
336
+ `ERR_PACKAGE_PATH_NOT_EXPORTED`. Only the names below are *intended* as API; the rest are
337
+ reachable because Python has no way to say otherwise.
338
+
339
+ **`import bantamkit` binds 45 names, of which 30 are values.** The other 15 are submodules bound
340
+ as a side effect of the package's own imports (`agent`, `assets`, `budget`, `client`, `contract`,
341
+ `critique`, `docmanifest`, `docread`, `evalrun`, `filegraph`, `loopguard`, `memory`, `pdfread`,
342
+ `profile`, `textutil`). There is no `__all__`, so `from bantamkit import *` takes all 45.
343
+
344
+ | Module behind it | What it is | Names |
345
+ | --- | --- | --- |
346
+ | `bantamkit.agent` | the tool-calling loop | `Agent`, `AgentResult`, `MaxTurnsExceeded`, `ToolDef` |
347
+ | `bantamkit.client` | the OpenAI-compatible transport and its wire types | `APIError`, `BantamError`, `Message`, `ModelClient`, `OpenAICompatible`, `Response`, `Tool`, `ToolCall`, `TransportError`, `Usage` |
348
+ | `bantamkit.critique` | the critique gate and its rubrics | `CritiqueExhausted`, `CritiqueGate`, `GroundedCritiqueGate`, `Rubric`, `load_rubric` |
349
+ | `bantamkit.evalrun` | the suite runner | `CONFIGS`, `format_report`, `run_suite` |
350
+ | `bantamkit.structured` | schema-constrained output | `StructuredOutputError`, `structured` |
351
+ | `bantamkit.contract` | JSON out of model prose, and evidence rendering | `extract_json`, `render_evidence` |
352
+ | `bantamkit.loopguard` | the repetition cut-off | `LoopGuard` |
353
+ | `bantamkit.filegraph` | the file-access graph | `FileAccessGraph` |
354
+ | `bantamkit.memory` | the memory store | `Memory`, `MemoryStore` |
355
+ | **9 modules** | | **30 values, no `__all__`** |
356
+
357
+ **This is not the npm package's export surface.** Both runtimes serve the same fourteen MCP
358
+ tools, but what each one exports *to an importer* is a different product: here it is the
359
+ agent/critique/eval library above; there it is the memory store, the asset pack, the event log,
360
+ the shift-work tools and a set of CPython-semantics shims — 139 values behind one entry point. Of
361
+ these 30 names exactly **three** are spelled the same on the npm side (`BantamError`, `Memory`,
362
+ `MemoryStore`), and a spelling is not a promise about behaviour. A parity claim about the MCP
363
+ tools is not a parity claim about these.
364
+
365
+ **A worked start.** Copy-paste examples:
366
+ [`examples/`](https://github.com/Ink01101011/bantamkit/tree/main/examples).
367
+
368
+ ```python
369
+ from bantamkit import Agent, CritiqueGate, Memory, OpenAICompatible, Tool, ToolDef
370
+
371
+ client = OpenAICompatible(base_url="http://localhost:11434/v1", model="qwen2.5:7b-instruct")
372
+
373
+ price_lookup = ToolDef(
374
+ tool=Tool(
375
+ name="price_lookup",
376
+ description="Get the unit price of an item",
377
+ parameters={
378
+ "type": "object",
379
+ "required": ["item"],
380
+ "properties": {"item": {"type": "string"}},
381
+ },
382
+ ),
383
+ handler=lambda item: f"{item} price: 25",
384
+ )
385
+
386
+ agent = Agent(client=client, tools=[price_lookup]).use(
387
+ Memory(store="./.bantam-memory"),
388
+ CritiqueGate("task-completion"),
389
+ )
390
+
391
+ result = agent.run("What does a widget cost? Remember it for next time.")
392
+ print(result.output, result.usage.total)
393
+ ```
394
+
395
+ Which options are worth attaching, measured over 528 runs per model:
396
+ [docs/usage.md → Recommended defaults](https://github.com/Ink01101011/bantamkit/blob/main/docs/usage.md#recommended-defaults).
397
+
398
+ **Rerun the numbers.** Against the published wheel, in a throwaway venv:
399
+
400
+ ```bash
401
+ python -m venv /tmp/bk && /tmp/bk/bin/pip install bantamkit
402
+ /tmp/bk/bin/python -c "import bantamkit; print(len([n for n in dir(bantamkit) if not n.startswith('_')]))"
403
+ ```
404
+
405
+ It prints `45`. The 30 values alone, without the submodules:
406
+
407
+ ```bash
408
+ /tmp/bk/bin/python -c "import bantamkit, types; print(sorted(n for n in dir(bantamkit) if not n.startswith('_') and not isinstance(getattr(bantamkit, n), types.ModuleType)))"
409
+ ```
410
+
411
+ Both numbers move whenever `src/bantamkit/__init__.py` does, which is why they are quoted with
412
+ the command that prints them rather than kept in prose.
413
+
313
414
  ## Development
314
415
 
315
416
  ```bash
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "shiftwork_clock_in",
3
+ "description": "Shift-work clock-in: schema-validate the checkpoint file and return the brief for the unit at plan.cursor — {unit, role, invariants, handoff, do_not, files} — to hand to the spawned agent verbatim. The unit briefed is the one at plan.cursor, or, when unit_id is given, that unit — which must appear in shiftwork_plan's `ready`, the batch the dependency graph says may run now. A unit_id that is not ready, including one naming no unit, is refused with {\"result\": \"error\", \"reason\": \"unit <id> is not ready; ready is <a, b>\"}, and the refusals of the batch view itself (cycle, unknown dependency, unreadable checkpoint) pass through verbatim. Clock-in still never moves plan.cursor; clock_out does. Structured refusals, never exceptions: result=escalate when handoff.open_questions is non-empty, result=success when every unit is done or dropped, result=error when the checkpoint fails validation. Clock-in also WRITES: on result=brief, and only then, it appends one line {event: brief, ts, unit, role} to <checkpoint>.log.jsonl — best-effort: a log it cannot write costs the brief nothing (the brief still returns, no error, only the record is lost). clock_out reads those lines back to write `briefed` on every accounting line, so the ledger is no longer one line per clock-out; a brief line carries `event` and no `status`. See docs/shiftwork.md.",
4
+ "surfaces": [
5
+ "mcp"
6
+ ],
7
+ "parameters": {
8
+ "properties": {
9
+ "checkpoint": {
10
+ "title": "Checkpoint",
11
+ "type": "string"
12
+ },
13
+ "unit_id": {
14
+ "anyOf": [
15
+ {
16
+ "type": "string"
17
+ },
18
+ {
19
+ "type": "null"
20
+ }
21
+ ],
22
+ "default": null,
23
+ "title": "Unit Id"
24
+ }
25
+ },
26
+ "required": [
27
+ "checkpoint"
28
+ ],
29
+ "type": "object",
30
+ "title": "shiftwork_clock_inArguments"
31
+ },
32
+ "output_schema": {
33
+ "type": "object",
34
+ "additionalProperties": true,
35
+ "title": "shiftwork_clock_inDictOutput"
36
+ }
37
+ }
@@ -0,0 +1,150 @@
1
+ {
2
+ "name": "shiftwork_clock_out",
3
+ "description": "Shift-work clock-out: record a finished unit — set its status, advance plan.cursor, merge handoff_patch, push history_entry onto the 5-entry ring — validating the whole mutated document against the checkpoint schema BEFORE an atomic write (a failure writes nothing and returns result=error). `unit_id` must be `plan.cursor` — which needs no brief, clocking out with briefed=false — OR a unit briefed since its own last clock-out; any other id keeps its refusal (`unit X is not the cursor unit Y`). plan.cursor then advances to the head of the ready batch recomputed on the mutated document, falling back to plan.units order over the remaining non-terminal units when the graph cannot batch (cycle or unknown dependency), and to unit_id when none remain. `handoff_patch` and `history_entry` are both required arguments: `handoff_patch` is shallow-merged into `handoff` and takes only its four keys (pass `{}` to leave it unchanged); `history_entry` needs `unit` and `outcome`; `status` is one of the five unit statuses — a value outside these shapes is refused by the schema check, nothing written. Every success appends one accounting line (unit, role, status, ts, briefed, plus your accounting fields, e.g. tokens/duration_ms/model) to <checkpoint>.log.jsonl, beside the brief lines clock_in writes (a brief line carries `event` and no `status`). `accounting` is optional: null, the default, logs a line with no cost figures at all; a non-null line must fit the accounting shape below. `briefed` is written by the runtime, never taken from you: true when a brief was issued for this unit since its LAST clock-out (not ever), so a unit re-run after a blocked clock-out reads false. If job.roles names this unit's role, accounting.model must be one of that role's model identifiers, spelled exactly, or nothing is written — see the `model` property below.",
4
+ "surfaces": [
5
+ "mcp"
6
+ ],
7
+ "parameters": {
8
+ "properties": {
9
+ "checkpoint": {
10
+ "title": "Checkpoint",
11
+ "type": "string"
12
+ },
13
+ "unit_id": {
14
+ "title": "Unit Id",
15
+ "type": "string",
16
+ "description": "The unit being clocked out. Must be plan.cursor, or a unit briefed since its own last clock-out: clock_in briefs the cursor unit by default and, when its unit_id names one, any unit shiftwork_plan reports in `ready` — and that brief is what lets clock_out accept a unit the cursor is not on."
17
+ },
18
+ "status": {
19
+ "title": "Status",
20
+ "type": "string",
21
+ "enum": [
22
+ "todo",
23
+ "in_progress",
24
+ "done",
25
+ "blocked",
26
+ "dropped"
27
+ ],
28
+ "description": "The unit's new status; the same five values the checkpoint schema allows on plan.units[].status."
29
+ },
30
+ "handoff_patch": {
31
+ "title": "Handoff Patch",
32
+ "type": "object",
33
+ "additionalProperties": false,
34
+ "description": "Shallow-merged into `handoff`: only these four keys exist there, and a key outside them is refused by the schema check. Required; `{}` leaves `handoff` unchanged.",
35
+ "properties": {
36
+ "next_action": {
37
+ "type": "string",
38
+ "minLength": 1,
39
+ "description": "Imperative first move — zero re-derivation."
40
+ },
41
+ "open_questions": {
42
+ "type": "array",
43
+ "items": {
44
+ "type": "string",
45
+ "minLength": 1
46
+ },
47
+ "description": "The autonomy switch: empty = driver keeps cycling, non-empty = STOP and ask."
48
+ },
49
+ "do_not": {
50
+ "type": "array",
51
+ "items": {
52
+ "type": "string",
53
+ "minLength": 1
54
+ },
55
+ "description": "Negative space — near-mistakes past sessions made."
56
+ },
57
+ "notes": {
58
+ "type": "string",
59
+ "description": "Free-form prose for the next session, one string; the empty string clears it."
60
+ }
61
+ }
62
+ },
63
+ "history_entry": {
64
+ "title": "History Entry",
65
+ "type": "object",
66
+ "required": [
67
+ "unit",
68
+ "outcome"
69
+ ],
70
+ "additionalProperties": true,
71
+ "description": "Pushed onto the 5-entry `history` ring; `unit` and `outcome` are required, `notes` optional, other keys pass through.",
72
+ "properties": {
73
+ "unit": {
74
+ "type": "string",
75
+ "minLength": 1
76
+ },
77
+ "outcome": {
78
+ "type": "string",
79
+ "minLength": 1
80
+ },
81
+ "notes": {
82
+ "type": "string"
83
+ }
84
+ }
85
+ },
86
+ "accounting": {
87
+ "anyOf": [
88
+ {
89
+ "type": "object",
90
+ "description": "Per-unit cost. Written verbatim, beside ts/unit/role/status, as one line of <checkpoint>.log.jsonl - the ledger the N-sessions experiment reads. The keys named here have fixed meanings so a reader holding only the ledger knows what each number counts, in which unit, and which model produced it; any other key passes through unchanged (a refused key is friction, not safety). Lines written before this schema existed may spell these differently; the schema governs new writes only.",
91
+ "properties": {
92
+ "tokens": {
93
+ "type": "integer",
94
+ "minimum": 0,
95
+ "description": "Tokens the unit consumed as the harness's subagent counter reports them: every class it reports (input, output, cache creation) summed, EXCLUDING cache reads. In a non-null accounting line it is required — a line without it is refused before anything is written; only `accounting: null`, the default, is exempt, and that logs no cost at all. A rounded self-estimate is allowed only if `note` says it is one; a unit whose cost is unknown cannot be compared with any other."
96
+ },
97
+ "cache_read_tokens": {
98
+ "type": "integer",
99
+ "minimum": 0,
100
+ "description": "Tokens the unit's requests served from prompt cache, kept OUT of `tokens` because they dominate a real session's traffic and would swamp the work signal. Optional: omit it when the harness reports no such figure - a written 0 means the unit read nothing from cache."
101
+ },
102
+ "duration_ms": {
103
+ "type": "integer",
104
+ "minimum": 0,
105
+ "description": "Wall-clock from spawning the subagent to its final message, in whole milliseconds. In a non-null line it is required, and it is the only duration key with a defined meaning: older lines carry `duration`, `duration_min` or `duration_s`, which this schema neither reads nor renames."
106
+ },
107
+ "model": {
108
+ "type": "string",
109
+ "description": "The exact identifier of the model the subagent actually ran on (e.g. `claude-sonnet-5`) and nothing else - a caveat about how it was chosen belongs in `note`. Not required here: when the checkpoint's job.roles names this unit's role, clock_out already requires it and refuses a value off that role's list, spelled exactly; a checkpoint with no job.roles leaves it optional. This schema does not change that gate."
110
+ },
111
+ "tool_uses": {
112
+ "type": "integer",
113
+ "minimum": 0,
114
+ "description": "Tool calls the subagent made, as the harness counts them. Optional; it is the denominator that makes `tokens` comparable across units of different size (per-unit cost is linear in tool calls, not in unit length)."
115
+ },
116
+ "note": {
117
+ "type": "string",
118
+ "description": "Free text for what the fields above cannot say: that `tokens` is an estimate, that this is a retry or a second scope under the same unit id, what a harness counter excludes. Anything that is not a model identifier goes here, not in `model`."
119
+ }
120
+ },
121
+ "required": [
122
+ "tokens",
123
+ "duration_ms"
124
+ ],
125
+ "additionalProperties": true
126
+ },
127
+ {
128
+ "type": "null"
129
+ }
130
+ ],
131
+ "default": null,
132
+ "title": "Accounting"
133
+ }
134
+ },
135
+ "required": [
136
+ "checkpoint",
137
+ "unit_id",
138
+ "status",
139
+ "handoff_patch",
140
+ "history_entry"
141
+ ],
142
+ "type": "object",
143
+ "title": "shiftwork_clock_outArguments"
144
+ },
145
+ "output_schema": {
146
+ "type": "object",
147
+ "additionalProperties": true,
148
+ "title": "shiftwork_clock_outDictOutput"
149
+ }
150
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "shiftwork_plan",
3
+ "description": "Shift-work plan: read-only batch view of a checkpoint — which units its `depends_on` graph permits to run in parallel. Answers `{\"result\": \"plan\", \"batches\", \"ready\", \"sequence\", \"width\", \"cursor\"}`: `ready` is `batches[0]`, the units whose dependencies are all satisfied, and `width` is the largest batch length, the widest fan-out. A `ready` member beyond the cursor is clockable, but only in that order: shiftwork_clock_in briefs any unit in `ready` when `unit_id` names it, and shiftwork_clock_out then accepts that unit because it was briefed — an id that is neither the cursor nor briefed since its own last clock-out is still refused. Units with status `done` or `dropped` are satisfied — dropped from the graph, and edges pointing at them treated as already resolved; `todo`, `in_progress` and `blocked` stay in it. Every unit has priority 0, because the checkpoint schema has no priority field, so order inside a batch is `plan.units` order. Same refusal sentences as `work_plan` for a duplicate id, an unknown dependency or a cycle, and the same refusals `shiftwork_status` gives for a checkpoint it cannot read. It reports what the dependency graph permits; it does not move the cursor, which is echoed unchanged so the single-pointer contract and the batch view can be read side by side. An orchestrator stays responsible for what it actually dispatches: `depends_on` encodes logical order, not file contention. Never mutates.",
4
+ "surfaces": [
5
+ "mcp"
6
+ ],
7
+ "parameters": {
8
+ "properties": {
9
+ "checkpoint": {
10
+ "title": "Checkpoint",
11
+ "type": "string"
12
+ }
13
+ },
14
+ "required": [
15
+ "checkpoint"
16
+ ],
17
+ "type": "object",
18
+ "title": "shiftwork_planArguments"
19
+ },
20
+ "output_schema": {
21
+ "type": "object",
22
+ "additionalProperties": true,
23
+ "title": "shiftwork_planDictOutput"
24
+ }
25
+ }
@@ -68,8 +68,16 @@ dependencies = ["httpx>=0.27", "jsonschema>=4.21", "pyyaml>=6.0"]
68
68
  # installs the backend into an isolated build env, never into the target env, so
69
69
  # without this declaration the bar would silently skip in exactly the environment
70
70
  # CI runs (`pip install -e "runtime-py[dev,mcp]"`). Declared here so it runs.
71
- dev = ["pytest>=8.0", "ruff>=0.4", "hatchling>=1.24"]
72
- mcp = ["mcp>=2.0,<3"]
71
+ # `build` is here because `tools/release/publish.sh` hard-requires it (it refuses at
72
+ # preflight with "the repo venv cannot 'import build'") and nothing declared it, so every
73
+ # release hit the same refusal and fixed it by hand. Added 2026-09-21, J62-15.
74
+ dev = ["pytest>=8.0", "ruff>=0.4", "hatchling>=1.24", "build>=1.0"]
75
+ # Upper bound measured, not guessed: 2.0.0 and 2.0.1 wrap a tool crash as
76
+ # `Error executing tool <name>: <exc>`, which runtime-ts/src/mcp/server.ts mirrors.
77
+ # 2.1.0 added an UnexpectedToolError branch that drops the `: <exc>` suffix, so the
78
+ # crash text stops reaching the client and `--suite workplan` goes red on the
79
+ # reference while the port still carries it. Raise this only together with the port.
80
+ mcp = ["mcp>=2.0,<2.1"]
73
81
 
74
82
  [project.scripts]
75
83
  bantamkit-mcp = "bantamkit.mcpserver:main"
@@ -29,4 +29,4 @@ from bantamkit.structured import StructuredOutputError, extract_json, structured
29
29
  # file as its dynamic version source, so the wheel's metadata and the string the MCP
30
30
  # server advertises are the same committed bytes, and neither is a function of when
31
31
  # someone last ran `pip`.
32
- __version__ = "0.35.2"
32
+ __version__ = "0.35.4"