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.
- {bantamkit-0.35.2 → bantamkit-0.35.4}/PKG-INFO +107 -5
- {bantamkit-0.35.2 → bantamkit-0.35.4}/README.md +104 -3
- bantamkit-0.35.4/_assets/tools/shiftwork_clock_in.json +37 -0
- bantamkit-0.35.4/_assets/tools/shiftwork_clock_out.json +150 -0
- bantamkit-0.35.4/_assets/tools/shiftwork_plan.json +25 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/pyproject.toml +10 -2
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/__init__.py +1 -1
- bantamkit-0.35.4/src/bantamkit/hookadapter.py +2084 -0
- bantamkit-0.35.4/src/bantamkit/hostinstall.py +722 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/mcpserver.py +328 -2
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/dream.py +5 -5
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/store.py +25 -9
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/selfupdate.py +22 -2
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/shiftwork.py +172 -61
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/updatecheck.py +78 -16
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/served-tool-surface.json +78 -11
- bantamkit-0.35.4/tests/test_hookadapter.py +1262 -0
- bantamkit-0.35.4/tests/test_hostinstall_hooks.py +1033 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_mcpserver.py +22 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory.py +1 -1
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory_dream.py +3 -3
- bantamkit-0.35.4/tests/test_nativeexport.py +830 -0
- bantamkit-0.35.4/tests/test_readme_separation.py +331 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_selfupdate.py +36 -10
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_shiftwork.py +330 -2
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_tool_manifest.py +48 -1
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_updatecheck.py +86 -4
- bantamkit-0.35.2/_assets/tools/shiftwork_clock_in.json +0 -25
- bantamkit-0.35.2/_assets/tools/shiftwork_clock_out.json +0 -95
- bantamkit-0.35.2/_assets/tools/shiftwork_plan.json +0 -25
- bantamkit-0.35.2/src/bantamkit/hostinstall.py +0 -296
- {bantamkit-0.35.2 → bantamkit-0.35.4}/.gitignore +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/contracts/default.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/manifest.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/HISTORY.md +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/README.md +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/docs/architecture.md +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/docs/runbook.md +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/issues/142-settlement-timeout.md +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/patches/0009-retry-budget.patch +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/__init__.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/config.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/errors.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/posting.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/registry.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/report.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/retry.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/settle.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/src/ledger/validate.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/tests/test_posting.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/repo/tests/test_settle.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-error-contract.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-handler-map.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-patch-before-after.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-retry-attempts.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-settlement-config.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-symbol-home.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-trace-blame.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/devteam/tasks/dt-unread-key.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-large-in-137.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-large-in-359.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-large-in-372.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-large-out-11764.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-large-out-4137.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-large-out-8022.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-small-137.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-small-261.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/document/tasks/doc-small-388.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/fixtures/.gitkeep +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/fixtures/catalog.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/perturbations/task-completion.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/.gitkeep +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/extract-contact.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/extract-invoice.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/extract-order.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/extract-schedule.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/extract-versions.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/nav-prod-port.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/nav-release-bundle.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-audit-retention.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-cache-ttl.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-db-port.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-deploy.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-env-endpoint.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-oncall-rotation.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-oncall.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-org-quota.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/recall-owner.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/shop-basket-total.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/shop-cheapest.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/shop-compare.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/shop-gadget-value.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/shop-stock-total.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/evals/tasks/shop-total.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/pricing/default.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/profiles/default.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/profiles/patient.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/rubrics/.gitkeep +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/rubrics/code-quality.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/rubrics/grounded-completion.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/rubrics/task-completion.yaml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/schemas/shiftwork-checkpoint.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/skills/.gitkeep +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/skills/file-graph.md +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/skills/memory.md +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/.gitkeep +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/bantamkit_read.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/bantamkit_status.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/build_identity.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/document_list.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/document_read.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/file_graph.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/memory_compact.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/memory_dream.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/memory_recall.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/memory_save.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/repo_map.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/shiftwork_status.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/skill_audit.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/token_ledger.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/validate_json.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/_assets/tools/work_plan.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/hatch_build.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/agent.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/assets.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/budget.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/client.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/contract.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/criticreplay.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/critique.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/docmanifest.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/docread.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/evalrun.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/eventlog.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/filegraph.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/loopguard.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/mcpreport.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/__init__.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/__main__.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/component.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/divergence.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/memory/layers.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/pdfread.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/pricing.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/profile.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/repomap.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/skillaudit.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/statusline.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/structured.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/textutil.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/tokenledger.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/src/bantamkit/workplan.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/cli_exit_status_probe.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/conftest.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/bad-crc.docx +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/charref-4301-digits.html +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/charset-table.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/compression-method-9.docx +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/corrupt-deflate.docx +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/encrypted-member.docx +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/encrypted-mimetype.odt +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/eszett-cell-ref.xlsx +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/internal-dtd-entity.docx +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/rfc2231-charset.eml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/rfc822-nested-twice.eml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/unicode-digit-shared-string.xlsx +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/docread/x-uuencode.eml +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/f8404ab-perturbation-baseline.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/data/platform-assumption-baseline.json +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/docread_fixtures.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/perturbation_baseline_harness.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/rbp16_effect_probe.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/rbp18_payload_probe.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_adapter.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_agent.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_amendguard.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_bantamkit_gitignore.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_bantamkit_read_tool.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_budget.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_build_identity.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_client.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_compaction_corpus_survey.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_conformance.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_conformance_harness_resilience.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_conformance_suite_table_gate.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_contract_fanout.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_criticreplay.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_critique.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_doc_commands_gate.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_docread.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_docread_ceilings.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_document_manifest_parity.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_document_setup.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_document_tasks.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_document_tools.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_encoding_gate.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_evalrun.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_eventlog.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_field_program_gates.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_field_programs.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_filegraph.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_hostinstall.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_install_shape.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_ladder_statistics.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_launcher_which.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_layers.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_loopguard.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_mcp_endpoint.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_mcpdrift.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_mcpreport.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory_compact_tool.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory_component.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory_divergence.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory_layers.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_memory_store_tripwire.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_mutmatrix.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_newline_gate.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_packaging.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_pdfread.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_pinharness_ledger.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_platform_assumption_gate.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_pricing.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_repo_map_tool.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_repomap.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_served_tool_count_records.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_skillaudit.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_status_surface.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_statusline.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_structured.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_thread_exception_gate.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_tokenledger.py +0 -0
- {bantamkit-0.35.2 → bantamkit-0.35.4}/tests/test_version_agreement.py +0 -0
- {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.
|
|
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<
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
72
|
-
|
|
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.
|
|
32
|
+
__version__ = "0.35.4"
|