bantamkit 0.27.0__tar.gz → 0.28.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 (192) hide show
  1. {bantamkit-0.27.0 → bantamkit-0.28.0}/PKG-INFO +1 -1
  2. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/__init__.py +1 -1
  3. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/mcpserver.py +39 -2
  4. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_build_identity.py +40 -0
  5. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_mcpserver.py +50 -1
  6. {bantamkit-0.27.0 → bantamkit-0.28.0}/.gitignore +0 -0
  7. {bantamkit-0.27.0 → bantamkit-0.28.0}/README.md +0 -0
  8. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/contracts/default.yaml +0 -0
  9. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/manifest.yaml +0 -0
  10. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/HISTORY.md +0 -0
  11. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/README.md +0 -0
  12. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/docs/architecture.md +0 -0
  13. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/docs/runbook.md +0 -0
  14. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/issues/142-settlement-timeout.md +0 -0
  15. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/patches/0009-retry-budget.patch +0 -0
  16. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/src/ledger/__init__.py +0 -0
  17. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/src/ledger/config.py +0 -0
  18. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/src/ledger/errors.py +0 -0
  19. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/src/ledger/posting.py +0 -0
  20. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/src/ledger/registry.py +0 -0
  21. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/src/ledger/report.py +0 -0
  22. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/src/ledger/retry.py +0 -0
  23. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/src/ledger/settle.py +0 -0
  24. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/src/ledger/validate.py +0 -0
  25. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/tests/test_posting.py +0 -0
  26. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/repo/tests/test_settle.py +0 -0
  27. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/tasks/dt-error-contract.yaml +0 -0
  28. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/tasks/dt-handler-map.yaml +0 -0
  29. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/tasks/dt-patch-before-after.yaml +0 -0
  30. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/tasks/dt-retry-attempts.yaml +0 -0
  31. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/tasks/dt-settlement-config.yaml +0 -0
  32. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/tasks/dt-symbol-home.yaml +0 -0
  33. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/tasks/dt-trace-blame.yaml +0 -0
  34. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/devteam/tasks/dt-unread-key.yaml +0 -0
  35. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/document/tasks/doc-large-in-137.yaml +0 -0
  36. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/document/tasks/doc-large-in-359.yaml +0 -0
  37. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/document/tasks/doc-large-in-372.yaml +0 -0
  38. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/document/tasks/doc-large-out-11764.yaml +0 -0
  39. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/document/tasks/doc-large-out-4137.yaml +0 -0
  40. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/document/tasks/doc-large-out-8022.yaml +0 -0
  41. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/document/tasks/doc-small-137.yaml +0 -0
  42. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/document/tasks/doc-small-261.yaml +0 -0
  43. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/document/tasks/doc-small-388.yaml +0 -0
  44. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/fixtures/.gitkeep +0 -0
  45. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/fixtures/catalog.json +0 -0
  46. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/perturbations/task-completion.yaml +0 -0
  47. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/.gitkeep +0 -0
  48. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/extract-contact.yaml +0 -0
  49. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/extract-invoice.yaml +0 -0
  50. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/extract-order.yaml +0 -0
  51. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/extract-schedule.yaml +0 -0
  52. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/extract-versions.yaml +0 -0
  53. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/nav-prod-port.yaml +0 -0
  54. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/nav-release-bundle.yaml +0 -0
  55. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/recall-audit-retention.yaml +0 -0
  56. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/recall-cache-ttl.yaml +0 -0
  57. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/recall-db-port.yaml +0 -0
  58. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/recall-deploy.yaml +0 -0
  59. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/recall-env-endpoint.yaml +0 -0
  60. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/recall-oncall-rotation.yaml +0 -0
  61. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/recall-oncall.yaml +0 -0
  62. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/recall-org-quota.yaml +0 -0
  63. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/recall-owner.yaml +0 -0
  64. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/shop-basket-total.yaml +0 -0
  65. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/shop-cheapest.yaml +0 -0
  66. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/shop-compare.yaml +0 -0
  67. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/shop-gadget-value.yaml +0 -0
  68. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/shop-stock-total.yaml +0 -0
  69. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/evals/tasks/shop-total.yaml +0 -0
  70. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/profiles/default.yaml +0 -0
  71. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/profiles/patient.yaml +0 -0
  72. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/rubrics/.gitkeep +0 -0
  73. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/rubrics/code-quality.yaml +0 -0
  74. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/rubrics/grounded-completion.yaml +0 -0
  75. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/rubrics/task-completion.yaml +0 -0
  76. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/schemas/shiftwork-checkpoint.json +0 -0
  77. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/skills/.gitkeep +0 -0
  78. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/skills/file-graph.md +0 -0
  79. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/skills/memory.md +0 -0
  80. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/.gitkeep +0 -0
  81. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/bantamkit_read.json +0 -0
  82. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/bantamkit_status.json +0 -0
  83. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/build_identity.json +0 -0
  84. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/document_list.json +0 -0
  85. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/document_read.json +0 -0
  86. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/file_graph.json +0 -0
  87. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/memory_compact.json +0 -0
  88. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/memory_recall.json +0 -0
  89. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/memory_save.json +0 -0
  90. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/shiftwork_clock_in.json +0 -0
  91. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/shiftwork_clock_out.json +0 -0
  92. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/shiftwork_status.json +0 -0
  93. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/skill_audit.json +0 -0
  94. {bantamkit-0.27.0 → bantamkit-0.28.0}/_assets/tools/validate_json.json +0 -0
  95. {bantamkit-0.27.0 → bantamkit-0.28.0}/hatch_build.py +0 -0
  96. {bantamkit-0.27.0 → bantamkit-0.28.0}/pyproject.toml +0 -0
  97. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/agent.py +0 -0
  98. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/assets.py +0 -0
  99. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/budget.py +0 -0
  100. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/client.py +0 -0
  101. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/contract.py +0 -0
  102. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/criticreplay.py +0 -0
  103. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/critique.py +0 -0
  104. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/docread.py +0 -0
  105. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/evalrun.py +0 -0
  106. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/eventlog.py +0 -0
  107. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/filegraph.py +0 -0
  108. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/loopguard.py +0 -0
  109. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/mcpreport.py +0 -0
  110. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/memory/__init__.py +0 -0
  111. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/memory/__main__.py +0 -0
  112. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/memory/component.py +0 -0
  113. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/memory/divergence.py +0 -0
  114. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/memory/layers.py +0 -0
  115. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/memory/store.py +0 -0
  116. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/pdfread.py +0 -0
  117. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/profile.py +0 -0
  118. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/shiftwork.py +0 -0
  119. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/skillaudit.py +0 -0
  120. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/statusline.py +0 -0
  121. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/structured.py +0 -0
  122. {bantamkit-0.27.0 → bantamkit-0.28.0}/src/bantamkit/textutil.py +0 -0
  123. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/cli_exit_status_probe.py +0 -0
  124. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/conftest.py +0 -0
  125. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/docread/bad-crc.docx +0 -0
  126. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/docread/charref-4301-digits.html +0 -0
  127. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/docread/charset-table.json +0 -0
  128. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/docread/compression-method-9.docx +0 -0
  129. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/docread/corrupt-deflate.docx +0 -0
  130. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/docread/encrypted-member.docx +0 -0
  131. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/docread/encrypted-mimetype.odt +0 -0
  132. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/docread/eszett-cell-ref.xlsx +0 -0
  133. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/docread/internal-dtd-entity.docx +0 -0
  134. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/docread/rfc2231-charset.eml +0 -0
  135. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/docread/rfc822-nested-twice.eml +0 -0
  136. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/docread/unicode-digit-shared-string.xlsx +0 -0
  137. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/docread/x-uuencode.eml +0 -0
  138. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/f8404ab-perturbation-baseline.json +0 -0
  139. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/data/served-tool-surface.json +0 -0
  140. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/docread_fixtures.py +0 -0
  141. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/perturbation_baseline_harness.py +0 -0
  142. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/rbp16_effect_probe.py +0 -0
  143. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/rbp18_payload_probe.py +0 -0
  144. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_adapter.py +0 -0
  145. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_agent.py +0 -0
  146. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_amendguard.py +0 -0
  147. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_bantamkit_read_tool.py +0 -0
  148. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_budget.py +0 -0
  149. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_client.py +0 -0
  150. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_compaction_corpus_survey.py +0 -0
  151. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_conformance.py +0 -0
  152. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_contract_fanout.py +0 -0
  153. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_criticreplay.py +0 -0
  154. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_critique.py +0 -0
  155. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_doc_commands_gate.py +0 -0
  156. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_docread.py +0 -0
  157. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_document_setup.py +0 -0
  158. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_document_tasks.py +0 -0
  159. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_document_tools.py +0 -0
  160. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_encoding_gate.py +0 -0
  161. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_evalrun.py +0 -0
  162. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_eventlog.py +0 -0
  163. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_field_program_gates.py +0 -0
  164. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_field_programs.py +0 -0
  165. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_filegraph.py +0 -0
  166. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_ladder_statistics.py +0 -0
  167. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_launcher_which.py +0 -0
  168. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_layers.py +0 -0
  169. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_loopguard.py +0 -0
  170. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_mcp_endpoint.py +0 -0
  171. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_mcpdrift.py +0 -0
  172. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_mcpreport.py +0 -0
  173. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_memory.py +0 -0
  174. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_memory_compact_tool.py +0 -0
  175. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_memory_component.py +0 -0
  176. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_memory_divergence.py +0 -0
  177. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_memory_layers.py +0 -0
  178. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_memory_store_tripwire.py +0 -0
  179. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_mutmatrix.py +0 -0
  180. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_newline_gate.py +0 -0
  181. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_packaging.py +0 -0
  182. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_pdfread.py +0 -0
  183. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_pinharness_ledger.py +0 -0
  184. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_served_tool_count_records.py +0 -0
  185. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_shiftwork.py +0 -0
  186. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_skillaudit.py +0 -0
  187. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_status_surface.py +0 -0
  188. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_statusline.py +0 -0
  189. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_structured.py +0 -0
  190. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_thread_exception_gate.py +0 -0
  191. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_tool_manifest.py +0 -0
  192. {bantamkit-0.27.0 → bantamkit-0.28.0}/tests/test_version_agreement.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: bantamkit
3
- Version: 0.27.0
3
+ Version: 0.28.0
4
4
  Summary: bantamweight tooling — harness primitives that lift small-model agents
5
5
  License-Expression: MIT
6
6
  Requires-Python: >=3.11
@@ -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.27.0"
32
+ __version__ = "0.28.0"
@@ -145,6 +145,29 @@ def _code_fingerprint() -> tuple[str, int, Path]:
145
145
  raise _Undetermined(f"unreadable source under {root}: {exc}") from None
146
146
 
147
147
 
148
+ def _pack_files(root: Path) -> list[Path]:
149
+ """The pack as SHIPPED: every file except the bytecode caches an interpreter left in it.
150
+
151
+ ONE spelling of the rule, because there are TWO walks over this directory — the digest
152
+ behind `build_identity` and the count `--assets-root` prints — and a rule spelled twice
153
+ is a rule that gets fixed once. That is not hypothetical: the first version of this fix
154
+ excluded `__pycache__` from the digest alone, and a `pip install` then had one process
155
+ contradicting itself, `build_identity` answering 87 files while `--assets-root` printed
156
+ 98 for the pack it had just loaded.
157
+
158
+ Bytecode is derived. `_code_fingerprint` has said so since it was written; this is the
159
+ same sentence applied to the pack, which carries eleven `.py` fixture files of its own.
160
+
161
+ The membership test is over the path RELATIVE to `root`, so a pack that happens to live
162
+ somewhere under a directory named `__pycache__` is walked rather than emptied.
163
+ """
164
+ return sorted(
165
+ p
166
+ for p in root.rglob("*")
167
+ if p.is_file() and "__pycache__" not in p.relative_to(root).parts
168
+ )
169
+
170
+
148
171
  def _assets_fingerprint() -> tuple[str, int, Path]:
149
172
  """Fingerprint the asset pack this build would load.
150
173
 
@@ -153,12 +176,26 @@ def _assets_fingerprint() -> tuple[str, int, Path]:
153
176
  different pack whether or not today's code opens it. `contracts/default.yaml` is the
154
177
  reason — `RB-P84` measured it as the one asset that differed between two live builds
155
178
  while no resource template exposed it, so it was invisible on every probed surface.
179
+
180
+ EXCEPT bytecode caches, and that exception is the whole point of this field. The pack
181
+ ships `.py` fixture files, so `pip install` byte-compiles them into `__pycache__` on the
182
+ way in and the digest of an INSTALLED pack stopped matching the digest of the identical
183
+ npm pack — measured on the published 0.27.0 artifacts, `sha256:fa8372f6…` over 98 files
184
+ against `sha256:d47dcf4b…` over 87, and deleting `__pycache__` from the wheel's pack
185
+ reproduced the npm digest byte for byte. `cross_runtime` tells the caller to compare
186
+ `assets_digest` across runtimes; without this rule that instruction returned a false
187
+ "different" on every real install. It was worse than cross-runtime: the digest was not
188
+ stable for ONE install either, because it changed the first time anything imported a
189
+ fixture. The pack is what was SHIPPED, never what an interpreter later wrote beside it.
190
+
191
+ The rule lives in `_pack_files`, which `--assets-root` shares, and is spelled the same
192
+ way in `runtime-ts`.
156
193
  """
157
194
  try:
158
195
  root = assets_root()
159
196
  except AssetNotFound as exc:
160
197
  raise _Undetermined(f"assets_root() could not resolve a pack: {exc}") from None
161
- files = sorted(p for p in root.rglob("*") if p.is_file())
198
+ files = _pack_files(root)
162
199
  if not files:
163
200
  raise _Undetermined(f"asset pack at {root} contains no files")
164
201
  try:
@@ -1301,7 +1338,7 @@ def _print_assets_root() -> None:
1301
1338
  matches too.
1302
1339
  """
1303
1340
  root = assets_root()
1304
- files = sum(1 for path in root.rglob("*") if path.is_file())
1341
+ files = len(_pack_files(root))
1305
1342
  sys.stdout.buffer.write(f"{root}\n{files} files\n".encode())
1306
1343
  sys.stdout.buffer.flush()
1307
1344
 
@@ -458,3 +458,43 @@ def test_one_build_in_two_install_shapes_is_one_build(pristine, tmp_path):
458
458
  assert wheel["code_digest"] == pristine["code_digest"]
459
459
  assert wheel["assets_digest"] == pristine["assets_digest"]
460
460
  assert wheel["build_id"] == pristine["build_id"]
461
+
462
+
463
+ def test_pip_byte_compiling_the_packs_fixtures_is_not_a_different_pack(pristine, tmp_path):
464
+ """The same defect as the test above, one field over, found on the PUBLISHED artifacts.
465
+
466
+ `_code_fingerprint` has excluded `__pycache__` since it was written, for the reason
467
+ stated there: bytecode is derived, and a build must not fingerprint differently before
468
+ and after its first import. `_assets_fingerprint` did not, and the asset pack carries
469
+ eleven `.py` fixture files — so `pip install` byte-compiles them on the way in and the
470
+ installed pack gained eleven files the npm pack never has.
471
+
472
+ Measured on the published 0.27.0 artifacts, before this exclusion existed: the wheel
473
+ answered `sha256:fa8372f6…` over 98 files where the npm tarball answered
474
+ `sha256:d47dcf4b…` over 87, and deleting `__pycache__` from the wheel's pack reproduced
475
+ the npm digest byte for byte. `cross_runtime` was at that moment telling every caller
476
+ that `assets_digest` is the field to compare across runtimes, so the one instruction the
477
+ tool gives about itself returned a false "different" on every real install.
478
+
479
+ It was not only a cross-runtime defect. The digest was unstable for ONE install: it
480
+ changed the first time anything imported a fixture. This test pins that half, which is
481
+ the half a differential gate cannot see — pointed at one polluted pack, both runtimes
482
+ move together and agree with each other while both are wrong.
483
+
484
+ Note `_wheel_shaped` already copies with `ignore_patterns("__pycache__")`. The fixture
485
+ knew; the shipped walk did not.
486
+ """
487
+ pkgroot = _wheel_shaped(tmp_path, "compiled")
488
+ clean = _identity_of(pkgroot, tmp_path)
489
+
490
+ cache = pkgroot / "bantamkit" / "assets" / "evals" / "devteam" / "repo" / "src" / "ledger"
491
+ cache = cache / "__pycache__"
492
+ cache.mkdir(parents=True)
493
+ for stem in ("config", "errors", "posting"):
494
+ (cache / f"{stem}.cpython-312.pyc").write_bytes(b"not real bytecode\n")
495
+
496
+ compiled = _identity_of(pkgroot, tmp_path)
497
+
498
+ assert compiled["assets_files"] == clean["assets_files"] == pristine["assets_files"]
499
+ assert compiled["assets_digest"] == clean["assets_digest"] == pristine["assets_digest"]
500
+ assert compiled["build_id"] == clean["build_id"] == pristine["build_id"]
@@ -3,6 +3,7 @@
3
3
  import asyncio
4
4
  import json
5
5
  import os
6
+ import shutil
6
7
  import tomllib
7
8
  from pathlib import Path
8
9
 
@@ -18,6 +19,7 @@ from bantamkit.assets import load_skill, load_tool # noqa: E402
18
19
  # The checkout under test, so a subprocess can be pointed at IT rather than at whatever
19
20
  # `bantamkit` is installed in the interpreter that spawns it.
20
21
  SRC = Path(__file__).resolve().parents[1] / "src"
22
+ REPO_ASSETS = Path(__file__).resolve().parents[2] / "assets"
21
23
  from bantamkit.mcpserver import ( # noqa: E402
22
24
  _build_memory,
23
25
  _parse_args,
@@ -636,7 +638,15 @@ def test_assets_root_flag_prints_the_root_and_a_file_count_on_stdout(tmp_path):
636
638
  from bantamkit.assets import assets_root
637
639
 
638
640
  root = assets_root()
639
- expected = sum(len(names) for _dirpath, _dirnames, names in os.walk(root))
641
+ # `os.walk` and not the implementation's `rglob`, so a fix that counted directories as
642
+ # well as files stays red — but with the SAME `__pycache__` rule the implementation
643
+ # applies, or this expectation becomes a landmine that fires the first time anything
644
+ # imports the eleven `.py` fixtures the pack ships.
645
+ expected = sum(
646
+ len(names)
647
+ for dirpath, _dirnames, names in os.walk(root)
648
+ if "__pycache__" not in Path(dirpath).relative_to(root).parts
649
+ )
640
650
  done = _run_cli(["--assets-root"], tmp_path)
641
651
 
642
652
  assert done.returncode == 0
@@ -645,6 +655,45 @@ def test_assets_root_flag_prints_the_root_and_a_file_count_on_stdout(tmp_path):
645
655
  assert done.stdout.count(b"\n") == 2
646
656
 
647
657
 
658
+ def test_assets_root_and_build_identity_count_the_same_pack_the_same_way(tmp_path):
659
+ """One process must not contradict itself about the pack it just loaded.
660
+
661
+ There are two walks over the asset pack — the digest behind `build_identity` and this
662
+ count — and the first version of the `__pycache__` exclusion filtered only the digest.
663
+ On a real `pip install` that left `build_identity` answering 87 files while
664
+ `--assets-root` printed 98 for the same directory, which is a worse failure than either
665
+ number being wrong: a caller comparing them has no way to decide which surface lied.
666
+
667
+ The pack here carries a `__pycache__` because that is what `pip` leaves behind — the
668
+ pack ships eleven `.py` fixtures and installing the wheel byte-compiles them.
669
+ """
670
+ import subprocess
671
+ import sys
672
+
673
+ pack = tmp_path / "pack"
674
+ shutil.copytree(REPO_ASSETS, pack, ignore=shutil.ignore_patterns("__pycache__"))
675
+ shipped = sum(1 for p in pack.rglob("*") if p.is_file())
676
+
677
+ cache = pack / "evals" / "devteam" / "repo" / "src" / "ledger" / "__pycache__"
678
+ cache.mkdir(parents=True)
679
+ for stem in ("config", "errors", "posting"):
680
+ (cache / f"{stem}.cpython-312.pyc").write_bytes(b"not real bytecode\n")
681
+ assert sum(1 for p in pack.rglob("*") if p.is_file()) == shipped + 3
682
+
683
+ env = dict(os.environ)
684
+ env["PYTHONPATH"] = str(SRC)
685
+ env["BANTAMKIT_ASSETS"] = str(pack)
686
+ done = subprocess.run(
687
+ [sys.executable, "-m", "bantamkit.mcpserver", "--assets-root"],
688
+ capture_output=True,
689
+ cwd=str(tmp_path),
690
+ env=env,
691
+ )
692
+
693
+ assert done.returncode == 0
694
+ assert done.stdout == f"{pack}\n{shipped} files\n".encode()
695
+
696
+
648
697
  def test_assets_root_flag_returns_before_a_store_or_a_transport_exists(monkeypatch, capsysbinary):
649
698
  """The Node arm returns ahead of `new RawStdioTransport()`; so does this one.
650
699
 
File without changes
File without changes
File without changes
File without changes
File without changes