bantamkit 0.37.2__tar.gz → 0.38.1__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 (318) hide show
  1. {bantamkit-0.37.2 → bantamkit-0.38.1}/PKG-INFO +5 -5
  2. {bantamkit-0.37.2 → bantamkit-0.38.1}/README.md +3 -3
  3. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/schemas/shiftwork-checkpoint.json +175 -2
  4. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/bantamkit_status.json +8 -2
  5. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/shiftwork_clock_in.json +21 -3
  6. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/shiftwork_clock_out.json +192 -6
  7. bantamkit-0.38.1/_assets/tools/shiftwork_draft.json +226 -0
  8. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/shiftwork_plan.json +26 -1
  9. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/work_plan.json +23 -2
  10. {bantamkit-0.37.2 → bantamkit-0.38.1}/pyproject.toml +9 -6
  11. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/__init__.py +1 -1
  12. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/eventlog.py +2 -2
  13. bantamkit-0.38.1/src/bantamkit/experiment.py +75 -0
  14. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/hookadapter.py +3 -2
  15. bantamkit-0.38.1/src/bantamkit/jobbudget.py +135 -0
  16. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/mcpserver.py +101 -8
  17. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/mcpstdio.py +50 -2
  18. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/memory/__main__.py +1 -1
  19. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/shiftwork.py +1141 -24
  20. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/skillinstall.py +49 -13
  21. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/skillmine.py +28 -6
  22. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/storage/tiers.py +50 -8
  23. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/touch/log.py +22 -3
  24. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/workplan.py +103 -9
  25. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/served-tool-surface.json +529 -15
  26. bantamkit-0.38.1/tests/test_agreements.py +105 -0
  27. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_conformance_suite_table_gate.py +1 -0
  28. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_eventlog.py +1 -1
  29. bantamkit-0.38.1/tests/test_experimentation.py +234 -0
  30. bantamkit-0.38.1/tests/test_follow_ups.py +147 -0
  31. bantamkit-0.38.1/tests/test_investigation.py +217 -0
  32. bantamkit-0.38.1/tests/test_jobbudget.py +215 -0
  33. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_mcpserver.py +8 -5
  34. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory_compact_tool.py +3 -2
  35. bantamkit-0.38.1/tests/test_never_block.py +149 -0
  36. bantamkit-0.38.1/tests/test_reviews.py +135 -0
  37. bantamkit-0.38.1/tests/test_sdk_wire_text.py +175 -0
  38. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_served_tool_count_records.py +11 -11
  39. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_shiftwork.py +18 -4
  40. bantamkit-0.38.1/tests/test_shiftwork_draft.py +235 -0
  41. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_skillaudit.py +1 -1
  42. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_status_surface.py +33 -1
  43. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_storage_tiers.py +70 -1
  44. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_tokenledger.py +1 -0
  45. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_tool_annotations.py +2 -2
  46. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_tool_manifest.py +1 -0
  47. bantamkit-0.38.1/tests/test_touches.py +195 -0
  48. bantamkit-0.38.1/tests/test_unit_agent_id.py +359 -0
  49. bantamkit-0.38.1/tests/test_unit_results.py +133 -0
  50. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_unknown_arguments.py +1 -1
  51. {bantamkit-0.37.2 → bantamkit-0.38.1}/.gitignore +0 -0
  52. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/contracts/default.yaml +0 -0
  53. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/manifest.yaml +0 -0
  54. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/HISTORY.md +0 -0
  55. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/README.md +0 -0
  56. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/docs/architecture.md +0 -0
  57. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/docs/runbook.md +0 -0
  58. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/issues/142-settlement-timeout.md +0 -0
  59. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/patches/0009-retry-budget.patch +0 -0
  60. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/src/ledger/__init__.py +0 -0
  61. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/src/ledger/config.py +0 -0
  62. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/src/ledger/errors.py +0 -0
  63. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/src/ledger/posting.py +0 -0
  64. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/src/ledger/registry.py +0 -0
  65. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/src/ledger/report.py +0 -0
  66. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/src/ledger/retry.py +0 -0
  67. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/src/ledger/settle.py +0 -0
  68. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/src/ledger/validate.py +0 -0
  69. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/tests/test_posting.py +0 -0
  70. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/repo/tests/test_settle.py +0 -0
  71. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/tasks/dt-error-contract.yaml +0 -0
  72. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/tasks/dt-handler-map.yaml +0 -0
  73. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/tasks/dt-patch-before-after.yaml +0 -0
  74. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/tasks/dt-retry-attempts.yaml +0 -0
  75. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/tasks/dt-settlement-config.yaml +0 -0
  76. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/tasks/dt-symbol-home.yaml +0 -0
  77. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/tasks/dt-trace-blame.yaml +0 -0
  78. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/devteam/tasks/dt-unread-key.yaml +0 -0
  79. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/document/tasks/doc-large-in-137.yaml +0 -0
  80. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/document/tasks/doc-large-in-359.yaml +0 -0
  81. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/document/tasks/doc-large-in-372.yaml +0 -0
  82. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/document/tasks/doc-large-out-11764.yaml +0 -0
  83. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/document/tasks/doc-large-out-4137.yaml +0 -0
  84. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/document/tasks/doc-large-out-8022.yaml +0 -0
  85. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/document/tasks/doc-small-137.yaml +0 -0
  86. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/document/tasks/doc-small-261.yaml +0 -0
  87. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/document/tasks/doc-small-388.yaml +0 -0
  88. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/fixtures/.gitkeep +0 -0
  89. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/fixtures/catalog.json +0 -0
  90. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/perturbations/task-completion.yaml +0 -0
  91. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/.gitkeep +0 -0
  92. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/extract-contact.yaml +0 -0
  93. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/extract-invoice.yaml +0 -0
  94. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/extract-order.yaml +0 -0
  95. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/extract-schedule.yaml +0 -0
  96. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/extract-versions.yaml +0 -0
  97. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/nav-prod-port.yaml +0 -0
  98. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/nav-release-bundle.yaml +0 -0
  99. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/recall-audit-retention.yaml +0 -0
  100. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/recall-cache-ttl.yaml +0 -0
  101. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/recall-db-port.yaml +0 -0
  102. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/recall-deploy.yaml +0 -0
  103. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/recall-env-endpoint.yaml +0 -0
  104. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/recall-oncall-rotation.yaml +0 -0
  105. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/recall-oncall.yaml +0 -0
  106. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/recall-org-quota.yaml +0 -0
  107. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/recall-owner.yaml +0 -0
  108. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/shop-basket-total.yaml +0 -0
  109. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/shop-cheapest.yaml +0 -0
  110. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/shop-compare.yaml +0 -0
  111. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/shop-gadget-value.yaml +0 -0
  112. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/shop-stock-total.yaml +0 -0
  113. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/evals/tasks/shop-total.yaml +0 -0
  114. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/pricing/default.json +0 -0
  115. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/profiles/default.yaml +0 -0
  116. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/profiles/patient.yaml +0 -0
  117. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/rubrics/.gitkeep +0 -0
  118. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/rubrics/code-quality.yaml +0 -0
  119. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/rubrics/grounded-completion.yaml +0 -0
  120. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/rubrics/task-completion.yaml +0 -0
  121. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/skills/.gitkeep +0 -0
  122. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/skills/file-graph.md +0 -0
  123. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/skills/memory-queries.md +0 -0
  124. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/skills/memory.md +0 -0
  125. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/.gitkeep +0 -0
  126. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/bantamkit_read.json +0 -0
  127. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/build_identity.json +0 -0
  128. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/document_list.json +0 -0
  129. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/document_read.json +0 -0
  130. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/file_graph.json +0 -0
  131. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/memory_compact.json +0 -0
  132. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/memory_dream.json +0 -0
  133. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/memory_queries.json +0 -0
  134. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/memory_recall.json +0 -0
  135. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/memory_save.json +0 -0
  136. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/repo_map.json +0 -0
  137. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/shiftwork_status.json +0 -0
  138. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/skill_audit.json +0 -0
  139. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/token_ledger.json +0 -0
  140. {bantamkit-0.37.2 → bantamkit-0.38.1}/_assets/tools/validate_json.json +0 -0
  141. {bantamkit-0.37.2 → bantamkit-0.38.1}/hatch_build.py +0 -0
  142. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/agent.py +0 -0
  143. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/assets.py +0 -0
  144. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/budget.py +0 -0
  145. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/client.py +0 -0
  146. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/contract.py +0 -0
  147. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/criticreplay.py +0 -0
  148. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/critique.py +0 -0
  149. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/docmanifest.py +0 -0
  150. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/docread.py +0 -0
  151. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/evalrun.py +0 -0
  152. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/filegraph.py +0 -0
  153. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/hostinstall.py +0 -0
  154. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/loopguard.py +0 -0
  155. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/mcpreport.py +0 -0
  156. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/memory/__init__.py +0 -0
  157. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/memory/component.py +0 -0
  158. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/memory/divergence.py +0 -0
  159. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/memory/dream.py +0 -0
  160. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/memory/layers.py +0 -0
  161. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/memory/native.py +0 -0
  162. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/memory/queries.py +0 -0
  163. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/memory/retrieval.py +0 -0
  164. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/memory/skills.py +0 -0
  165. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/memory/store.py +0 -0
  166. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/memory/usage.py +0 -0
  167. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/pdfread.py +0 -0
  168. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/pricing.py +0 -0
  169. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/profile.py +0 -0
  170. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/repomap.py +0 -0
  171. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/selfupdate.py +0 -0
  172. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/skillaudit.py +0 -0
  173. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/skilldraft.py +0 -0
  174. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/skillfile.py +0 -0
  175. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/skillhost.py +0 -0
  176. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/skillpromote.py +0 -0
  177. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/skillpropose.py +0 -0
  178. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/skillreport.py +0 -0
  179. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/statusline.py +0 -0
  180. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/storage/__init__.py +0 -0
  181. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/storage/coldindex.py +0 -0
  182. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/storage/hotindex.py +0 -0
  183. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/storage/lock.py +0 -0
  184. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/storage/logsegment.py +0 -0
  185. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/storage/retention.py +0 -0
  186. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/structured.py +0 -0
  187. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/textutil.py +0 -0
  188. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/tokenledger.py +0 -0
  189. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/touch/__init__.py +0 -0
  190. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/touch/bashturn.py +0 -0
  191. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/touch/context.py +0 -0
  192. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/touch/graph.py +0 -0
  193. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/touch/recallfile.py +0 -0
  194. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/touch/refs.py +0 -0
  195. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/touch/repo.py +0 -0
  196. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/touch/summary.py +0 -0
  197. {bantamkit-0.37.2 → bantamkit-0.38.1}/src/bantamkit/updatecheck.py +0 -0
  198. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/cli_exit_status_probe.py +0 -0
  199. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/conftest.py +0 -0
  200. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/docread/bad-crc.docx +0 -0
  201. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/docread/charref-4301-digits.html +0 -0
  202. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/docread/charset-table.json +0 -0
  203. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/docread/compression-method-9.docx +0 -0
  204. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/docread/corrupt-deflate.docx +0 -0
  205. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/docread/encrypted-member.docx +0 -0
  206. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/docread/encrypted-mimetype.odt +0 -0
  207. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/docread/eszett-cell-ref.xlsx +0 -0
  208. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/docread/internal-dtd-entity.docx +0 -0
  209. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/docread/rfc2231-charset.eml +0 -0
  210. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/docread/rfc822-nested-twice.eml +0 -0
  211. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/docread/unicode-digit-shared-string.xlsx +0 -0
  212. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/docread/x-uuencode.eml +0 -0
  213. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/f8404ab-perturbation-baseline.json +0 -0
  214. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/data/platform-assumption-baseline.json +0 -0
  215. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/docread_fixtures.py +0 -0
  216. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/perturbation_baseline_harness.py +0 -0
  217. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/rbp16_effect_probe.py +0 -0
  218. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/rbp18_payload_probe.py +0 -0
  219. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_adapter.py +0 -0
  220. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_agent.py +0 -0
  221. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_amendguard.py +0 -0
  222. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_assets.py +0 -0
  223. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_bantamkit_gitignore.py +0 -0
  224. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_bantamkit_read_tool.py +0 -0
  225. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_budget.py +0 -0
  226. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_build_identity.py +0 -0
  227. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_cli_oneshot.py +0 -0
  228. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_client.py +0 -0
  229. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_compaction_corpus_survey.py +0 -0
  230. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_conformance.py +0 -0
  231. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_conformance_harness_resilience.py +0 -0
  232. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_contract_fanout.py +0 -0
  233. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_contract_patterns.py +0 -0
  234. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_contract_refs.py +0 -0
  235. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_criticreplay.py +0 -0
  236. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_critique.py +0 -0
  237. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_doc_commands_gate.py +0 -0
  238. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_docread.py +0 -0
  239. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_docread_ceilings.py +0 -0
  240. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_document_manifest_parity.py +0 -0
  241. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_document_setup.py +0 -0
  242. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_document_tasks.py +0 -0
  243. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_document_tools.py +0 -0
  244. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_encoding_gate.py +0 -0
  245. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_evalrun.py +0 -0
  246. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_field_program_gates.py +0 -0
  247. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_field_programs.py +0 -0
  248. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_filegraph.py +0 -0
  249. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_hookadapter.py +0 -0
  250. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_hostinstall.py +0 -0
  251. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_hostinstall_hooks.py +0 -0
  252. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_install_shape.py +0 -0
  253. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_ladder_statistics.py +0 -0
  254. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_launcher_which.py +0 -0
  255. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_layers.py +0 -0
  256. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_loopguard.py +0 -0
  257. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_mcp_endpoint.py +0 -0
  258. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_mcp_request_guard.py +0 -0
  259. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_mcpdrift.py +0 -0
  260. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_mcpreport.py +0 -0
  261. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_mcpstdio_frames.py +0 -0
  262. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory.py +0 -0
  263. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory_component.py +0 -0
  264. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory_divergence.py +0 -0
  265. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory_dream.py +0 -0
  266. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory_layers.py +0 -0
  267. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory_lifecycle.py +0 -0
  268. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory_native.py +0 -0
  269. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory_queries.py +0 -0
  270. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory_retrieval.py +0 -0
  271. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory_skills.py +0 -0
  272. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory_store_tripwire.py +0 -0
  273. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory_strings.py +0 -0
  274. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_memory_usage.py +0 -0
  275. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_mutmatrix.py +0 -0
  276. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_nativeexport.py +0 -0
  277. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_newline_gate.py +0 -0
  278. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_packaging.py +0 -0
  279. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_pdfread.py +0 -0
  280. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_pinharness_ledger.py +0 -0
  281. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_platform_assumption_gate.py +0 -0
  282. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_pricing.py +0 -0
  283. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_readme_separation.py +0 -0
  284. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_repo_map_tool.py +0 -0
  285. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_repomap.py +0 -0
  286. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_selfupdate.py +0 -0
  287. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_skillaudit_roots.py +0 -0
  288. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_skilldraft.py +0 -0
  289. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_skillfile.py +0 -0
  290. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_skillhost.py +0 -0
  291. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_skillimprove.py +0 -0
  292. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_skillimprove_signals.py +0 -0
  293. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_skillinstall.py +0 -0
  294. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_skillmine.py +0 -0
  295. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_skillmine_daily.py +0 -0
  296. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_skillpromote.py +0 -0
  297. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_skillpropose.py +0 -0
  298. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_skillreport.py +0 -0
  299. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_statusline.py +0 -0
  300. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_storage_bar.py +0 -0
  301. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_storage_coldindex.py +0 -0
  302. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_storage_hotindex.py +0 -0
  303. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_storage_log.py +0 -0
  304. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_storage_log_consumers.py +0 -0
  305. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_storage_recall_index.py +0 -0
  306. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_storage_retention.py +0 -0
  307. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_structured.py +0 -0
  308. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_thread_exception_gate.py +0 -0
  309. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_touch_bashturn.py +0 -0
  310. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_touch_context.py +0 -0
  311. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_touch_graph.py +0 -0
  312. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_touch_log.py +0 -0
  313. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_touch_recall_file.py +0 -0
  314. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_touch_refs.py +0 -0
  315. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_touch_summary.py +0 -0
  316. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_updatecheck.py +0 -0
  317. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_version_agreement.py +0 -0
  318. {bantamkit-0.37.2 → bantamkit-0.38.1}/tests/test_workplan.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bantamkit
3
- Version: 0.37.2
3
+ Version: 0.38.1
4
4
  Summary: Persistent memory for coding agents: an MCP server for Claude Code, Claude Desktop, Cursor and VS Code Copilot, 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
@@ -26,7 +26,7 @@ Requires-Dist: hatchling>=1.24; extra == 'dev'
26
26
  Requires-Dist: pytest>=8.0; extra == 'dev'
27
27
  Requires-Dist: ruff>=0.4; extra == 'dev'
28
28
  Provides-Extra: mcp
29
- Requires-Dist: mcp<2.1,>=2.0; extra == 'mcp'
29
+ Requires-Dist: mcp<2.4,>=2.3; extra == 'mcp'
30
30
  Description-Content-Type: text/markdown
31
31
 
32
32
  # bantamkit — memory MCP server for Claude Code, Cursor, VS Code Copilot and Claude Desktop (Python)
@@ -144,9 +144,9 @@ CPU architecture and Python minor version** (some wheels, such as `pydantic_core
144
144
  one platform only), copy `wheels/` across, and install from it:
145
145
 
146
146
  ```bash
147
- python -m pip download "bantamkit[mcp]==0.37.2" -d wheels
147
+ python -m pip download "bantamkit[mcp]==0.38.1" -d wheels
148
148
  python -m venv <env>
149
- <env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.37.2"
149
+ <env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.38.1"
150
150
  <env>/bin/bantamkit-mcp --install cursor
151
151
  ```
152
152
 
@@ -328,7 +328,7 @@ you**; a new version with an old `build_id` means an old process.
328
328
 
329
329
  ## 🧰 What it serves
330
330
 
331
- It serves 15 tools, three prompts (`bantamkit_status`, `skill_audit` and `skill_propose`) and two resource templates
331
+ It serves 16 tools, three prompts (`bantamkit_status`, `skill_audit` and `skill_propose`) and two resource templates
332
332
  (`bantamkit://skills/{name}`, `bantamkit://rubrics/{name}`):
333
333
 
334
334
  | Tool | What it does |
@@ -113,9 +113,9 @@ CPU architecture and Python minor version** (some wheels, such as `pydantic_core
113
113
  one platform only), copy `wheels/` across, and install from it:
114
114
 
115
115
  ```bash
116
- python -m pip download "bantamkit[mcp]==0.37.2" -d wheels
116
+ python -m pip download "bantamkit[mcp]==0.38.1" -d wheels
117
117
  python -m venv <env>
118
- <env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.37.2"
118
+ <env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.38.1"
119
119
  <env>/bin/bantamkit-mcp --install cursor
120
120
  ```
121
121
 
@@ -297,7 +297,7 @@ you**; a new version with an old `build_id` means an old process.
297
297
 
298
298
  ## 🧰 What it serves
299
299
 
300
- It serves 15 tools, three prompts (`bantamkit_status`, `skill_audit` and `skill_propose`) and two resource templates
300
+ It serves 16 tools, three prompts (`bantamkit_status`, `skill_audit` and `skill_propose`) and two resource templates
301
301
  (`bantamkit://skills/{name}`, `bantamkit://rubrics/{name}`):
302
302
 
303
303
  | Tool | What it does |
@@ -38,6 +38,91 @@
38
38
  "items": {"type": "string", "minLength": 1},
39
39
  "description": "The model identifiers this role may report, spelled exactly as a session logs them. Non-empty: a role allowed no model is a typo, not a policy."
40
40
  }
41
+ },
42
+ "authorized": {
43
+ "type": "array",
44
+ "items": {"type": "string", "minLength": 1},
45
+ "description": "OPTIONAL (#225). The irreversible verbs the user granted for this job (merge, tag, publish, ...), written once at plan time. Declared, clock_in escalates on a unit whose `irreversible` verb is not listed; absent keeps today's behaviour."
46
+ },
47
+ "kind": {
48
+ "type": "string",
49
+ "enum": ["investigation", "experimentation"],
50
+ "description": "OPTIONAL (#264, #265). `investigation`: the job answers `question` by testing `hypotheses` in run units, each supported claim replayed by another role before `conclusion` may say resolved. `experimentation`: candidate units compete in their own worktrees on `experiment.objective`, each validated by another role at the exact SHA it submitted. Absent = today's job."
51
+ },
52
+ "experiment": {
53
+ "type": "object",
54
+ "required": ["objective", "direction", "base_sha", "harness", "concurrency_cap"],
55
+ "additionalProperties": false,
56
+ "properties": {
57
+ "objective": {"type": "string", "minLength": 1, "description": "What a candidate's score measures."},
58
+ "direction": {"type": "string", "enum": ["minimize", "maximize"], "description": "Which way a better score points."},
59
+ "base_sha": {"type": "string", "minLength": 1, "description": "The commit every candidate starts from. Frozen: once a brief or clock-out has read it, a checkpoint that says otherwise is refused."},
60
+ "harness": {"type": "string", "minLength": 1, "description": "The command that scores a candidate. Frozen like base_sha."},
61
+ "concurrency_cap": {"type": "integer", "minimum": 1, "description": "At most this many candidates in flight; clock_in refuses the next."},
62
+ "candidate_budget": {
63
+ "type": "object",
64
+ "additionalProperties": false,
65
+ "minProperties": 1,
66
+ "properties": {
67
+ "tokens": {"type": "integer", "minimum": 0, "description": "Tokens one candidate's accounting lines may record."},
68
+ "wallclock_ms": {"type": "integer", "minimum": 0, "description": "duration_ms one candidate's accounting lines may record."}
69
+ },
70
+ "description": "Per candidate, read off its own accounting lines; a candidate that has spent it is refused at clock_in."
71
+ }
72
+ },
73
+ "description": "OPTIONAL (#265). Required by `kind: experimentation`."
74
+ },
75
+ "question": {
76
+ "type": "string",
77
+ "minLength": 1,
78
+ "description": "OPTIONAL (#264). The question an investigation answers."
79
+ },
80
+ "hypotheses": {
81
+ "type": "array",
82
+ "items": {
83
+ "type": "object",
84
+ "required": ["id", "claim", "falsified_by"],
85
+ "additionalProperties": false,
86
+ "properties": {
87
+ "id": {"type": "string", "minLength": 1, "description": "What a run's `tests` and the conclusion's `supported` name."},
88
+ "claim": {"type": "string", "minLength": 1, "description": "What the hypothesis says is true."},
89
+ "falsified_by": {"type": "string", "minLength": 1, "description": "The observation that would refute it, written before any run."}
90
+ }
91
+ },
92
+ "description": "OPTIONAL (#264). An investigation declares at least two, or one with `single_hypothesis_rationale`; the batch view, clock_in and clock_out refuse one that does not."
93
+ },
94
+ "single_hypothesis_rationale": {
95
+ "type": "string",
96
+ "minLength": 1,
97
+ "description": "OPTIONAL (#264). Why an investigation tests only one hypothesis."
98
+ },
99
+ "conclusion": {
100
+ "type": "object",
101
+ "required": ["outcome", "evidence"],
102
+ "additionalProperties": false,
103
+ "properties": {
104
+ "outcome": {"type": "string", "enum": ["resolved", "inconclusive", "stopped"], "description": "`resolved` needs `supported`, a done run testing it, a done replay of that run, and a done review of either; the other two are never refused."},
105
+ "supported": {"type": "string", "minLength": 1, "description": "The hypothesis id the evidence supports."},
106
+ "evidence": {"type": "array", "items": {"type": "string", "minLength": 1}, "description": "Refs to what was observed: run outputs, commits, files."}
107
+ },
108
+ "description": "OPTIONAL (#264). Set only through clock_out's `conclusion`, by a unit with `concludes: true`."
109
+ },
110
+ "agreements": {
111
+ "type": "array",
112
+ "maxItems": 20,
113
+ "items": {"type": "string", "minLength": 1},
114
+ "description": "OPTIONAL (#261). Working agreements adopted during the job, carried on every brief. Changed only through clock_out's `agreements` {adopt, retire}; each change is recorded in retro[]."
115
+ },
116
+ "budget": {
117
+ "type": "object",
118
+ "description": "OPTIONAL (#262). What the job may spend, read back from <checkpoint>.log.jsonl: shiftwork_plan reports spent/remaining/affordable, clock_in refuses a brief that does not fit, and clock_out refuses a 0-token accounting line not marked `estimate`. Absent keeps today's behaviour exactly.",
119
+ "additionalProperties": false,
120
+ "minProperties": 1,
121
+ "properties": {
122
+ "tokens": {"type": "integer", "minimum": 1, "description": "Token ceiling, counted as accounting `tokens`."},
123
+ "units": {"type": "integer", "minimum": 1, "description": "Accounting lines (clock-outs) the job may record."},
124
+ "wallclock_ms": {"type": "integer", "minimum": 1, "description": "Sum of accounting `duration_ms` the job may record."}
125
+ }
41
126
  }
42
127
  }
43
128
  },
@@ -76,6 +161,79 @@
76
161
  "description": "Driver dispatch key: role -> model/allowed tools, set in driver config."
77
162
  },
78
163
  "depends_on": {"type": "array", "items": {"type": "string", "minLength": 1}},
164
+ "attempts": {
165
+ "type": "array",
166
+ "maxItems": 3,
167
+ "description": "This unit's clock-outs, newest last, at most 3 (#259). Written by clock_out from its status and history_entry; clock_in hands them back as prior_attempts and as a dependant's upstream[].last.",
168
+ "items": {
169
+ "type": "object",
170
+ "required": ["status", "outcome"],
171
+ "additionalProperties": false,
172
+ "properties": {
173
+ "status": {"type": "string", "enum": ["todo", "in_progress", "done", "blocked", "dropped"]},
174
+ "outcome": {"type": "string", "minLength": 1},
175
+ "notes": {"type": "string", "maxLength": 2000},
176
+ "produced": {
177
+ "type": "array",
178
+ "items": {
179
+ "type": "object",
180
+ "required": ["kind", "ref"],
181
+ "additionalProperties": false,
182
+ "properties": {"kind": {"type": "string", "minLength": 1}, "ref": {"type": "string", "minLength": 1}}
183
+ }
184
+ }
185
+ }
186
+ }
187
+ },
188
+ "reviews": {
189
+ "type": "array",
190
+ "items": {"type": "string", "minLength": 1},
191
+ "description": "Unit ids this unit reviews (#263). Optional. Each must be declared, be in this unit's depends_on, and have a different role from this unit; the batch view, clock_in and clock_out refuse a checkpoint that breaks any of the three."
192
+ },
193
+ "candidate": {
194
+ "type": "object",
195
+ "required": ["workspace", "author_role"],
196
+ "additionalProperties": false,
197
+ "properties": {
198
+ "workspace": {"type": "string", "minLength": 1, "description": "The worktree the orchestrator created for this candidate, recorded here and removed by the orchestrator after validation."},
199
+ "author_role": {"type": "string", "minLength": 1, "description": "The role that writes the candidate; must be this unit's role."}
200
+ },
201
+ "description": "OPTIONAL (#265). This unit is a candidate: `touches` does not hold it (its own worktree), its clock-out done reports {kind: commit, ref: <full sha>} and {kind: score, ref: <number>}, and a unit that `reviews` it validates that exact SHA."
202
+ },
203
+ "tests": {
204
+ "type": "array",
205
+ "items": {"type": "string", "minLength": 1},
206
+ "description": "OPTIONAL (#264). The hypothesis ids this run unit tests; each must be declared. A run clocked out done must report a `produced` item of kind `run-output`."
207
+ },
208
+ "procedure": {
209
+ "type": "string",
210
+ "minLength": 1,
211
+ "description": "OPTIONAL (#264). The command or brief path a run follows; a replay must name the same text exactly."
212
+ },
213
+ "replay_of": {
214
+ "type": "string",
215
+ "minLength": 1,
216
+ "description": "OPTIONAL (#264). The run this unit repeats: it must be declared, name a procedure equal to this unit's, and be in another role."
217
+ },
218
+ "concludes": {
219
+ "type": "boolean",
220
+ "description": "OPTIONAL (#264). The unit whose clock_out may set job.conclusion."
221
+ },
222
+ "irreversible": {
223
+ "type": "string",
224
+ "minLength": 1,
225
+ "description": "OPTIONAL (#225). The verb of an action that cannot be undone (merge, tag, publish, delete-branch). clock_in refuses such a unit without `prove`, and escalates when job.authorized is declared and does not list the verb."
226
+ },
227
+ "prove": {
228
+ "type": "string",
229
+ "minLength": 1,
230
+ "description": "OPTIONAL (#225). A command run against the BUILT artifact (packed tarball, installed wheel), beside `verify`, which checks the source. Required on an `irreversible` unit."
231
+ },
232
+ "touches": {
233
+ "type": "array",
234
+ "items": {"type": "string"},
235
+ "description": "Repo-relative POSIX paths this unit will WRITE (#257). Optional; absent or [] claims nothing. The batch view never puts two units sharing a path in one batch, and clock_in refuses a unit whose path a unit still in flight touches."
236
+ },
79
237
  "verify": {
80
238
  "type": "string",
81
239
  "minLength": 1,
@@ -185,8 +343,23 @@
185
343
  },
186
344
  "open_questions": {
187
345
  "type": "array",
188
- "items": {"type": "string", "minLength": 1},
189
- "description": "The autonomy switch: empty = driver keeps cycling, non-empty = STOP and ask."
346
+ "items": {
347
+ "anyOf": [
348
+ {"type": "string", "minLength": 1, "description": "A decision question: the user's to answer."},
349
+ {
350
+ "type": "object",
351
+ "required": ["q", "kind"],
352
+ "additionalProperties": false,
353
+ "description": "#225: a question with a kind. `decision` is the user's; `relay` is answered by its `probe` (shell, exit 0 = answered), which clock_in runs before deciding to escalate.",
354
+ "properties": {
355
+ "q": {"type": "string", "minLength": 1, "description": "The question."},
356
+ "kind": {"type": "string", "enum": ["relay", "decision"], "description": "`decision` needs the user; `relay` needs only its probe run."},
357
+ "probe": {"type": "string", "minLength": 1, "description": "Shell command run from the repo root; exit 0 answers a relay question. Required on a relay: clock_out refuses one without it."}
358
+ }
359
+ }
360
+ ]
361
+ },
362
+ "description": "The autonomy switch: empty = driver keeps cycling, non-empty = STOP and ask — unless every entry is a relay question its probe answers (#225)."
190
363
  },
191
364
  "do_not": {
192
365
  "type": "array",
@@ -1,12 +1,18 @@
1
1
  {
2
2
  "name": "bantamkit_status",
3
3
  "title": "bantamkit status",
4
- "description": "Is bantamkit working, and which bantamkit? Returns a short report a person can read in the transcript: `bantamkit Active 🟢` or `bantamkit Degraded 🟠` on the first line, then the version and `build_id` of the code answering, the surfaces it serves, the memory store it is bound to with its index size against its budget, whether the event log is on, and — when degraded — every condition in full with what to do about it. Call it when the user asks whether the server is alive or working, when a bantamkit tool answered oddly and you need to know whether the server is the reason, or when a reply arrived carrying a `bantamkit degraded` footer and you want the rest of it. Every fact is observed at call time from the server's own state; nothing is a heartbeat or a cached verdict. Takes no arguments, writes nothing, and never echoes another call's arguments. build_identity answers only the `build_id` fingerprint, as JSON, when all you need is to compare two installs; shiftwork_status reports a job, not the server.",
4
+ "description": "Is bantamkit working, and which bantamkit? Returns a short report a person can read in the transcript: `bantamkit Active 🟢` or `bantamkit Degraded 🟠` on the first line, then the version and `build_id` of the code answering, the surfaces it serves, the memory store it is bound to with its index size against its budget, whether the event log is on, and — when degraded — every condition in full with what to do about it. Call it when the user asks whether the server is alive or working, when a bantamkit tool answered oddly and you need to know whether the server is the reason, or when a reply arrived carrying a `bantamkit degraded` footer and you want the rest of it. Every fact is observed at call time from the server's own state; nothing is a heartbeat or a cached verdict. Pass `detail: true` to list every usage and touch ledger on its own line instead of one summary line per family. Writes nothing, and never echoes another call's arguments. build_identity answers only the `build_id` fingerprint, as JSON, when all you need is to compare two installs; shiftwork_status reports a job, not the server.",
5
5
  "surfaces": [
6
6
  "mcp"
7
7
  ],
8
8
  "parameters": {
9
- "properties": {},
9
+ "properties": {
10
+ "detail": {
11
+ "type": "boolean",
12
+ "default": false,
13
+ "description": "true lists every usage and touch ledger on its own line; the default folds each family into one summary line."
14
+ }
15
+ },
10
16
  "type": "object",
11
17
  "title": "bantamkit_statusArguments",
12
18
  "additionalProperties": false
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shiftwork_clock_in",
3
3
  "title": "Shift work: clock in",
4
- "description": "Shift-work clock-in: validate the checkpoint against the checkpoint schema and return the brief of ONE unit — {unit, role, invariants, handoff, do_not, files} — to hand to the agent you spawn, verbatim. Call it once per unit, right before spawning; use shiftwork_plan first to see the `ready` batch when several units are to run at once, and shiftwork_clock_out, not this tool, when a unit finishes. The unit briefed is plan.cursor, or `unit_id` when given; either way it must be in shiftwork_plan's `ready` — a done or dropped cursor, a cursor whose dependencies have not run, or a `unit_id` naming no unit answers {\"result\": \"error\", \"reason\": \"unit <id> is not ready; ready is <a, b>\"}, and the batch view's own refusals (cycle, unknown dependency, unreadable checkpoint) pass through verbatim. The other outcomes, never exceptions: `escalate` when handoff.open_questions is non-empty (stop and ask the user) or when the cursor names no unit, `success` when every unit is done or dropped, `error` when the checkpoint fails validation. It never moves plan.cursor; clock_out does. What it WRITES: on result=brief, and only then, one line {event: brief, ts, unit, role} appended to <checkpoint>.log.jsonl — best-effort, so a log it cannot write costs the brief nothing. That line is what later lets clock_out accept the unit while the cursor is elsewhere and sets `briefed` on its accounting line. The checkpoint file itself is never modified. See docs/shiftwork.md.",
4
+ "description": "Shift-work clock-in: validate the checkpoint against the checkpoint schema and return the brief of ONE unit — {unit, role, invariants, handoff, do_not, files} — to hand to the agent you spawn, verbatim. Call it once per unit, right before spawning; use shiftwork_plan first to see the `ready` batch when several units are to run at once, and shiftwork_clock_out, not this tool, when a unit finishes. The unit briefed is plan.cursor, or `unit_id` when given; either way it must be in shiftwork_plan's `ready` — a done or dropped cursor, a cursor whose dependencies have not run, or a `unit_id` naming no unit answers {\"result\": \"error\", \"reason\": \"unit <id> is not ready; ready is <a, b>\"}, and the batch view's own refusals (cycle, unknown dependency, unreadable checkpoint) pass through verbatim. A ready unit whose `touches` shares a path with a unit briefed and not yet clocked out is refused too, before any brief: `unit <id> touches <path>, which <other> holds until its clock-out`. A checkpoint whose `reviews` break review independence is refused with shiftwork_plan's sentence. With job.budget declared, a brief that does not fit is refused: `budget <dim> spent: <n> of <limit>; raise job.budget or stop the job`. The other outcomes, never exceptions: `escalate` when handoff.open_questions is non-empty (stop and ask the user) or when the cursor names no unit, `success` when every unit is done or dropped, `error` when the checkpoint fails validation. It never moves plan.cursor; clock_out does. What it WRITES: on result=brief, and only then, one line {event: brief, ts, unit, role} appended to <checkpoint>.log.jsonl — best-effort, so a log it cannot write costs the brief nothing. That line is what later lets clock_out accept the unit while the cursor is elsewhere and sets `briefed` on its accounting line. The checkpoint file itself is never modified. See docs/shiftwork.md.",
5
5
  "surfaces": [
6
6
  "mcp"
7
7
  ],
@@ -70,12 +70,30 @@
70
70
  "type": "array",
71
71
  "description": "state.artifacts: the files the job has produced so far."
72
72
  },
73
- "open_questions": {
73
+ "upstream": {
74
+ "type": "array",
75
+ "description": "One {unit, title, status, last} per depends_on id, in depends_on order: last is that unit's newest attempt (status, outcome, notes?, produced?) or null. Always present with a brief."
76
+ },
77
+ "prior_attempts": {
78
+ "type": "array",
79
+ "description": "This unit's own attempts, oldest first, at most 3; [] when none. A unit clocked out todo and briefed again is a rework, and this is what it found."
80
+ },
81
+ "agreements": {
74
82
  "type": "array",
75
83
  "items": {
76
84
  "type": "string"
77
85
  },
78
- "description": "With result `escalate`: the questions the orchestrator must put to the user before any unit runs."
86
+ "description": "job.agreements: the working agreements adopted so far through clock_out, carried on every brief; [] when none."
87
+ },
88
+ "open_questions": {
89
+ "type": "array",
90
+ "items": {
91
+ "anyOf": [
92
+ {"type": "string", "description": "A decision question."},
93
+ {"type": "object", "description": "A question with a kind (#225): {q, kind: relay|decision, probe}. Escalation happens only for a decision or a relay whose probe did not exit 0; an answered relay is logged as a `resolved` ledger event."}
94
+ ]
95
+ },
96
+ "description": "With result `escalate`: the questions the orchestrator must put to the user before any unit runs. An irreversible unit whose verb job.authorized does not grant also escalates (#225), with no open_questions."
79
97
  },
80
98
  "reason": {
81
99
  "type": "string",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shiftwork_clock_out",
3
3
  "title": "Shift work: clock out",
4
- "description": "Shift-work clock-out: record that a unit finished — set its status, advance plan.cursor, merge `handoff_patch` into handoff, push `history_entry` onto the 5-entry history ring, and append one accounting line to <checkpoint>.log.jsonl. Call it once per unit after its agent returns: shiftwork_clock_in briefs, this tool closes, and shiftwork_status reads what both wrote. The whole mutated document is validated against the checkpoint schema BEFORE one atomic write, so a failure writes nothing and answers {\"result\": \"error\", \"reason\": ...}; nothing is ever deleted from the checkpoint. `unit_id` must be plan.cursor — which needs no brief and clocks out with briefed=false — or a unit clock_in briefed since its own last clock-out; any other id is refused with `unit X is not the cursor unit Y`. `handoff_patch` and `history_entry` are both required arguments: pass `{}` to leave handoff unchanged, and give history_entry at least `unit` and `outcome`. plan.cursor then moves to the head of the ready batch recomputed on the new document — plan.units order over the remaining non-terminal units when the graph cannot batch, `unit_id` when none remain. The accounting line carries unit, role, status, ts and `briefed` (written by the runtime, never taken from you: true only when a brief was issued since this unit's LAST clock-out) plus your `accounting` fields when given. When job.roles names this unit's role, `accounting.model` must be on that role's list, spelled exactly, or nothing is written — see the `model` property.",
4
+ "description": "Shift-work clock-out: record that a unit finished — set its status, advance plan.cursor, merge `handoff_patch` into handoff, push `history_entry` onto the 5-entry history ring, and append one accounting line to <checkpoint>.log.jsonl. Call it once per unit after its agent returns: shiftwork_clock_in briefs, this tool closes, and shiftwork_status reads what both wrote. The whole mutated document is validated against the checkpoint schema BEFORE one atomic write, so a failure writes nothing and answers {\"result\": \"error\", \"reason\": ...}; nothing is ever deleted from the checkpoint. `unit_id` must be plan.cursor — which needs no brief and clocks out with briefed=false — or a unit clock_in briefed since its own last clock-out; any other id is refused with `unit X is not the cursor unit Y`. `handoff_patch` and `history_entry` are both required arguments: pass `{}` to leave handoff unchanged, and give history_entry at least `unit` and `outcome`. plan.cursor then moves to the head of the ready batch recomputed on the new document — plan.units order over the remaining non-terminal units when the graph cannot batch, `unit_id` when none remain. The accounting line carries unit, role, status, ts and `briefed` (written by the runtime, never taken from you: true only when a brief was issued since this unit's LAST clock-out) plus your `accounting` fields when given. `follow_ups` appends the work it discovered as todo units. `agreements` adopts or retires a working agreement every later brief carries. Each clock-out also appends {status, outcome, notes?, produced?} to the unit's attempts (newest 3 kept). With job.budget declared, a line reporting 0 tokens is refused unless it carries `estimate: true`. When job.roles names this unit's role, `accounting.model` must be on that role's list, spelled exactly, or nothing is written — see the `model` property.",
5
5
  "surfaces": [
6
6
  "mcp"
7
7
  ],
@@ -43,10 +43,21 @@
43
43
  "open_questions": {
44
44
  "type": "array",
45
45
  "items": {
46
- "type": "string",
47
- "minLength": 1
46
+ "anyOf": [
47
+ {"type": "string", "minLength": 1, "description": "A decision question: the user's to answer."},
48
+ {
49
+ "type": "object",
50
+ "required": ["q", "kind"],
51
+ "additionalProperties": false,
52
+ "properties": {
53
+ "q": {"type": "string", "minLength": 1, "description": "The question."},
54
+ "kind": {"type": "string", "enum": ["relay", "decision"], "description": "`decision` needs the user; `relay` is answered by its probe."},
55
+ "probe": {"type": "string", "minLength": 1, "description": "Shell command run from the repo root by clock_in; exit 0 answers the relay. Required on a relay, or nothing is written."}
56
+ }
57
+ }
58
+ ]
48
59
  },
49
- "description": "The autonomy switch: empty = driver keeps cycling, non-empty = STOP and ask."
60
+ "description": "The autonomy switch: empty = driver keeps cycling, non-empty = STOP and ask. A bare string is a decision; a `relay` question carries a `probe` that clock_in runs instead of escalating (#225)."
50
61
  },
51
62
  "do_not": {
52
63
  "type": "array",
@@ -84,7 +95,30 @@
84
95
  },
85
96
  "notes": {
86
97
  "type": "string",
87
- "description": "Optional free text for the next session reading the ring."
98
+ "description": "Optional free text for the next session reading the ring, and recorded in the unit's attempt (#259): at most 2000 code points."
99
+ },
100
+ "produced": {
101
+ "type": "array",
102
+ "items": {
103
+ "type": "object",
104
+ "required": [
105
+ "kind",
106
+ "ref"
107
+ ],
108
+ "properties": {
109
+ "kind": {
110
+ "type": "string",
111
+ "minLength": 1,
112
+ "description": "What sort of thing: commit, file, pr, run-output."
113
+ },
114
+ "ref": {
115
+ "type": "string",
116
+ "minLength": 1,
117
+ "description": "Where it is: a SHA, a path, a URL."
118
+ }
119
+ }
120
+ },
121
+ "description": "What the unit produced, [{kind, ref}] (a commit, a file, a run output). Recorded with the unit's attempt, and handed to every unit that depends on it as upstream[].last."
88
122
  }
89
123
  }
90
124
  },
@@ -92,7 +126,7 @@
92
126
  "anyOf": [
93
127
  {
94
128
  "type": "object",
95
- "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, except the five the runtime writes itself — unit, role, status, ts, event — which are refused (result=error) before anything is written; a self-reported briefed is overwritten, not refused. Lines written before this schema existed may spell these differently; the schema governs new writes only.",
129
+ "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, except the six the runtime writes itself — unit, role, status, ts, event, agent_id — which are refused (result=error) before anything is written; a self-reported briefed is overwritten, not refused. Lines written before this schema existed may spell these differently; the schema governs new writes only.",
96
130
  "properties": {
97
131
  "tokens": {
98
132
  "type": "integer",
@@ -118,6 +152,10 @@
118
152
  "minimum": 0,
119
153
  "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)."
120
154
  },
155
+ "estimate": {
156
+ "type": "boolean",
157
+ "description": "true when `tokens` is a guess rather than the host's figure. With job.budget declared, a line reporting 0 tokens is refused unless it carries estimate: true."
158
+ },
121
159
  "note": {
122
160
  "type": "string",
123
161
  "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`."
@@ -136,6 +174,154 @@
136
174
  "default": null,
137
175
  "title": "Accounting",
138
176
  "description": "Per-unit cost line, or null (the default) to log a line with no cost figures at all. A non-null line must carry `tokens` and `duration_ms`; `model` is required when job.roles names this unit's role. The object shape is described below."
177
+ },
178
+ "follow_ups": {
179
+ "anyOf": [
180
+ {
181
+ "type": "array",
182
+ "items": {
183
+ "type": "object",
184
+ "required": [
185
+ "id",
186
+ "title",
187
+ "role",
188
+ "brief_path"
189
+ ],
190
+ "properties": {
191
+ "id": {
192
+ "type": "string",
193
+ "minLength": 1,
194
+ "description": "The new unit's id; must not be a unit already, nor repeat in this list."
195
+ },
196
+ "title": {
197
+ "type": "string",
198
+ "minLength": 1,
199
+ "description": "One line naming the work."
200
+ },
201
+ "role": {
202
+ "type": "string",
203
+ "enum": [
204
+ "planner",
205
+ "implementer",
206
+ "reviewer"
207
+ ],
208
+ "description": "Who runs it; when job.roles is declared it must be one of its keys."
209
+ },
210
+ "brief_path": {
211
+ "type": "string",
212
+ "minLength": 1,
213
+ "description": "Its brief, a file that must already exist, relative to the repo (the nearest ancestor of the checkpoint holding .git)."
214
+ },
215
+ "depends_on": {
216
+ "type": "array",
217
+ "items": {
218
+ "type": "string",
219
+ "minLength": 1
220
+ },
221
+ "description": "Unit ids it waits for; absent means the unit being clocked out."
222
+ },
223
+ "verify": {
224
+ "type": "string",
225
+ "minLength": 1,
226
+ "description": "Command proving it done; absent means the clocked-out unit's verify."
227
+ },
228
+ "touches": {
229
+ "type": "array",
230
+ "items": {
231
+ "type": "string"
232
+ },
233
+ "description": "Repo-relative paths it will write (#257)."
234
+ }
235
+ }
236
+ }
237
+ },
238
+ {
239
+ "type": "null"
240
+ }
241
+ ],
242
+ "default": null,
243
+ "title": "Follow Ups",
244
+ "description": "Work this unit discovered (#260): each item becomes a todo unit appended to plan.units in the given order, on the same write. Refused whole, nothing written, on a duplicate id, a brief that is not a file, an unknown dependency or a cycle (the planner's sentence), or a role job.roles does not declare."
245
+ },
246
+ "agreements": {
247
+ "anyOf": [
248
+ {
249
+ "type": "object",
250
+ "additionalProperties": false,
251
+ "properties": {
252
+ "adopt": {
253
+ "type": "array",
254
+ "items": {
255
+ "type": "string",
256
+ "minLength": 1
257
+ },
258
+ "description": "Agreements to add to job.agreements; text already listed is left as it is."
259
+ },
260
+ "retire": {
261
+ "type": "array",
262
+ "items": {
263
+ "type": "string",
264
+ "minLength": 1
265
+ },
266
+ "description": "Agreements to remove, by exact text; one not on the list is refused."
267
+ }
268
+ }
269
+ },
270
+ {
271
+ "type": "null"
272
+ }
273
+ ],
274
+ "default": null,
275
+ "title": "Agreements",
276
+ "description": "A lesson this unit wants every later brief to carry (#261): retire by exact text, then adopt. Refused, nothing written, for text not on the list or a result over 20; each applied change is recorded in retro[]."
277
+ },
278
+ "conclusion": {
279
+ "anyOf": [
280
+ {
281
+ "type": "object",
282
+ "additionalProperties": false,
283
+ "required": ["outcome", "evidence"],
284
+ "properties": {
285
+ "outcome": {
286
+ "type": "string",
287
+ "enum": ["resolved", "inconclusive", "stopped"],
288
+ "description": "`inconclusive` and `stopped` are never refused; `resolved` needs the evidence below."
289
+ },
290
+ "supported": {
291
+ "type": "string",
292
+ "minLength": 1,
293
+ "description": "The hypothesis id the evidence supports; required for `resolved`."
294
+ },
295
+ "evidence": {
296
+ "type": "array",
297
+ "items": {
298
+ "type": "string",
299
+ "minLength": 1
300
+ },
301
+ "description": "Refs to what was observed: run outputs, commits, files."
302
+ }
303
+ }
304
+ },
305
+ {
306
+ "type": "null"
307
+ }
308
+ ],
309
+ "default": null,
310
+ "title": "Conclusion",
311
+ "description": "An investigation's answer (#264), written to job.conclusion. Only a unit with `concludes: true` may send it; `resolved` is refused unless `supported` has a done run, a done replay of that run in another role, and a done review of either. A run unit (`tests` or `replay_of`) clocked out done must report a `run-output` in history_entry.produced."
312
+ },
313
+ "agent_id": {
314
+ "anyOf": [
315
+ {
316
+ "type": "string"
317
+ },
318
+ {
319
+ "type": "null"
320
+ }
321
+ ],
322
+ "default": null,
323
+ "title": "Agent Id",
324
+ "description": "The `agentId` the Agent tool's result returned for this unit's subagent (#266), copied verbatim: 1 to 64 letters, digits, - or _, or nothing is written. It goes on the accounting line, never into the checkpoint, and is how the skill miner attributes the skill uses the hook logged inside that subagent to this unit. Omit it for a unit run inline."
139
325
  }
140
326
  },
141
327
  "required": [