bantamkit 0.32.1__tar.gz → 0.34.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bantamkit-0.32.1 → bantamkit-0.34.0}/PKG-INFO +66 -1
- {bantamkit-0.32.1 → bantamkit-0.34.0}/README.md +65 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/schemas/shiftwork-checkpoint.json +5 -1
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/bantamkit_read.json +1 -3
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/repo_map.json +1 -3
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/shiftwork_clock_in.json +1 -1
- bantamkit-0.34.0/_assets/tools/shiftwork_clock_out.json +95 -0
- bantamkit-0.34.0/_assets/tools/skill_audit.json +70 -0
- bantamkit-0.34.0/_assets/tools/token_ledger.json +40 -0
- bantamkit-0.34.0/dist-0.33.0/bantamkit-0.33.0-py3-none-any.whl +0 -0
- bantamkit-0.34.0/dist-0.33.0/bantamkit-0.33.0.tar.gz +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/__init__.py +1 -1
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/eventlog.py +32 -6
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/hostinstall.py +6 -4
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/mcpserver.py +32 -5
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/memory/__init__.py +2 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/memory/__main__.py +1 -1
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/memory/store.py +67 -0
- bantamkit-0.34.0/src/bantamkit/shiftwork.py +552 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/platform-assumption-baseline.json +0 -3
- bantamkit-0.34.0/tests/data/served-tool-surface.json +454 -0
- bantamkit-0.34.0/tests/test_bantamkit_gitignore.py +236 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_bantamkit_read_tool.py +11 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_conformance.py +7 -2
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_criticreplay.py +4 -2
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_document_manifest_parity.py +19 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_eventlog.py +15 -10
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_mcpserver.py +80 -11
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_memory_compact_tool.py +0 -2
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_repo_map_tool.py +11 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_served_tool_count_records.py +11 -11
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_shiftwork.py +691 -28
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_skillaudit.py +5 -2
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_status_surface.py +1 -1
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_tokenledger.py +7 -6
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_tool_manifest.py +73 -3
- bantamkit-0.32.1/_assets/tools/shiftwork_clock_out.json +0 -60
- bantamkit-0.32.1/_assets/tools/skill_audit.json +0 -70
- bantamkit-0.32.1/_assets/tools/token_ledger.json +0 -40
- bantamkit-0.32.1/src/bantamkit/shiftwork.py +0 -299
- bantamkit-0.32.1/tests/data/served-tool-surface.json +0 -505
- {bantamkit-0.32.1 → bantamkit-0.34.0}/.gitignore +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/contracts/default.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/manifest.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/HISTORY.md +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/README.md +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/docs/architecture.md +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/docs/runbook.md +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/issues/142-settlement-timeout.md +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/patches/0009-retry-budget.patch +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/src/ledger/__init__.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/src/ledger/config.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/src/ledger/errors.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/src/ledger/posting.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/src/ledger/registry.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/src/ledger/report.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/src/ledger/retry.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/src/ledger/settle.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/src/ledger/validate.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/tests/test_posting.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/repo/tests/test_settle.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/tasks/dt-error-contract.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/tasks/dt-handler-map.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/tasks/dt-patch-before-after.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/tasks/dt-retry-attempts.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/tasks/dt-settlement-config.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/tasks/dt-symbol-home.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/tasks/dt-trace-blame.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/devteam/tasks/dt-unread-key.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/document/tasks/doc-large-in-137.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/document/tasks/doc-large-in-359.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/document/tasks/doc-large-in-372.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/document/tasks/doc-large-out-11764.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/document/tasks/doc-large-out-4137.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/document/tasks/doc-large-out-8022.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/document/tasks/doc-small-137.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/document/tasks/doc-small-261.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/document/tasks/doc-small-388.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/fixtures/.gitkeep +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/fixtures/catalog.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/perturbations/task-completion.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/.gitkeep +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/extract-contact.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/extract-invoice.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/extract-order.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/extract-schedule.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/extract-versions.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/nav-prod-port.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/nav-release-bundle.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/recall-audit-retention.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/recall-cache-ttl.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/recall-db-port.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/recall-deploy.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/recall-env-endpoint.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/recall-oncall-rotation.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/recall-oncall.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/recall-org-quota.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/recall-owner.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/shop-basket-total.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/shop-cheapest.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/shop-compare.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/shop-gadget-value.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/shop-stock-total.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/evals/tasks/shop-total.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/pricing/default.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/profiles/default.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/profiles/patient.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/rubrics/.gitkeep +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/rubrics/code-quality.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/rubrics/grounded-completion.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/rubrics/task-completion.yaml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/skills/.gitkeep +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/skills/file-graph.md +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/skills/memory.md +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/.gitkeep +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/bantamkit_status.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/build_identity.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/document_list.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/document_read.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/file_graph.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/memory_compact.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/memory_dream.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/memory_recall.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/memory_save.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/shiftwork_status.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/_assets/tools/validate_json.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/hatch_build.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/pyproject.toml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/agent.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/assets.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/budget.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/client.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/contract.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/criticreplay.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/critique.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/docmanifest.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/docread.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/evalrun.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/filegraph.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/loopguard.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/mcpreport.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/memory/component.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/memory/divergence.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/memory/dream.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/memory/layers.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/pdfread.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/pricing.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/profile.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/repomap.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/selfupdate.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/skillaudit.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/statusline.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/structured.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/textutil.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/src/bantamkit/tokenledger.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/cli_exit_status_probe.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/conftest.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/docread/bad-crc.docx +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/docread/charref-4301-digits.html +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/docread/charset-table.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/docread/compression-method-9.docx +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/docread/corrupt-deflate.docx +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/docread/encrypted-member.docx +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/docread/encrypted-mimetype.odt +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/docread/eszett-cell-ref.xlsx +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/docread/internal-dtd-entity.docx +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/docread/rfc2231-charset.eml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/docread/rfc822-nested-twice.eml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/docread/unicode-digit-shared-string.xlsx +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/docread/x-uuencode.eml +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/data/f8404ab-perturbation-baseline.json +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/docread_fixtures.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/perturbation_baseline_harness.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/rbp16_effect_probe.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/rbp18_payload_probe.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_adapter.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_agent.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_amendguard.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_budget.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_build_identity.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_client.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_compaction_corpus_survey.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_conformance_harness_resilience.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_conformance_suite_table_gate.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_contract_fanout.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_critique.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_doc_commands_gate.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_docread.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_docread_ceilings.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_document_setup.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_document_tasks.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_document_tools.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_encoding_gate.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_evalrun.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_field_program_gates.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_field_programs.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_filegraph.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_hostinstall.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_install_shape.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_ladder_statistics.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_launcher_which.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_layers.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_loopguard.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_mcp_endpoint.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_mcpdrift.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_mcpreport.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_memory.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_memory_component.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_memory_divergence.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_memory_dream.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_memory_layers.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_memory_store_tripwire.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_mutmatrix.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_newline_gate.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_packaging.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_pdfread.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_pinharness_ledger.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_platform_assumption_gate.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_pricing.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_repomap.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_selfupdate.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_statusline.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_structured.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_thread_exception_gate.py +0 -0
- {bantamkit-0.32.1 → bantamkit-0.34.0}/tests/test_version_agreement.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: bantamkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.34.0
|
|
4
4
|
Summary: bantamweight tooling — harness primitives that lift small-model agents
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -50,6 +50,63 @@ The uv equivalent is `uvx --from "bantamkit[mcp]" bantamkit-mcp`. uv is not
|
|
|
50
50
|
installed on the machine this README was measured on, so unlike every other
|
|
51
51
|
command here that one is the documented form rather than a measured one.
|
|
52
52
|
|
|
53
|
+
> **AMENDED 2026-09-15 (job51) — `pipx run` launches online, and it is offline only while
|
|
54
|
+
> pipx's own cache lasts.** The first form above is fine to try the server. As the command a
|
|
55
|
+
> host runs on every launch, it has a cost. Measured with pipx 1.11.1 and `bantamkit 0.33.0`,
|
|
56
|
+
> with the network cut by pointing the proxy variables at a closed port:
|
|
57
|
+
>
|
|
58
|
+
> ```bash
|
|
59
|
+
> PIPX_HOME=<scratch> https_proxy=http://127.0.0.1:1 HTTPS_PROXY=http://127.0.0.1:1 \
|
|
60
|
+
> http_proxy=http://127.0.0.1:1 HTTP_PROXY=http://127.0.0.1:1 PIP_PROXY=http://127.0.0.1:1 \
|
|
61
|
+
> PIP_RETRIES=0 PIP_TIMEOUT=5 pipx run --spec "bantamkit[mcp]==0.33.0" bantamkit-mcp --assets-root
|
|
62
|
+
> ```
|
|
63
|
+
>
|
|
64
|
+
> On a `PIPX_HOME` that had never run it, this exited 1 in 1.33 s. After one run online into
|
|
65
|
+
> the same `PIPX_HOME`, the same command exited 0 in 0.47 s. So a `pipx run` host entry needs
|
|
66
|
+
> the package index on a new machine, after the cache is cleared, and whenever pipx decides
|
|
67
|
+
> its cached environment is stale. That last one is pipx's policy and was not measured here.
|
|
68
|
+
> For a host, install into an environment you keep, as in the next section.
|
|
69
|
+
|
|
70
|
+
### Install once, run offline
|
|
71
|
+
|
|
72
|
+
Install into an environment you keep, then let `--install` record that environment's console
|
|
73
|
+
script:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
python -m venv <env>
|
|
77
|
+
<env>/bin/pip install "bantamkit[mcp]"
|
|
78
|
+
<env>/bin/bantamkit-mcp --install cursor # or claude, claude-desktop, copilot
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
After that, no launch needs the network. `--install` writes the absolute path of the console
|
|
82
|
+
script you ran. Measured 2026-09-15 on macOS arm64 against `bantamkit 0.33.0`,
|
|
83
|
+
`<env>/bin/bantamkit-mcp --install cursor` wrote `"command": "<env>/bin/bantamkit-mcp", "args": []`.
|
|
84
|
+
That command answered `initialize` and `tools/list` with 12 tools under the PATH a GUI app
|
|
85
|
+
inherits on macOS, `/usr/bin:/bin:/usr/sbin:/sbin`. The Windows layout (`<env>\Scripts\`) was
|
|
86
|
+
not measured.
|
|
87
|
+
|
|
88
|
+
**For a machine with no network at all, carry a wheelhouse.** On a connected machine with the
|
|
89
|
+
**same operating system, CPU architecture and Python minor version** as the target:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
python -m pip download "bantamkit[mcp]==0.33.0" -d wheels
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
With Python 3.12.13 on macOS arm64 that wrote 33 files. One of them is
|
|
96
|
+
`pydantic_core-2.46.5-cp312-cp312-macosx_11_0_arm64.whl`, which is built for CPython 3.12 on
|
|
97
|
+
arm64 macOS and nothing else. That is why the two machines must match. Copy `wheels/` across,
|
|
98
|
+
then on the target:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
python -m venv <env>
|
|
102
|
+
<env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.33.0"
|
|
103
|
+
<env>/bin/bantamkit-mcp --install cursor
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Measured in a fresh venv with `PIP_INDEX_URL=http://127.0.0.1:1/` (a closed port): the install
|
|
107
|
+
finished in 1.69 s, and the installed console script served the 12 tools as above. To move to
|
|
108
|
+
a newer version, repeat the download and the install with the new version number.
|
|
109
|
+
|
|
53
110
|
### Connect it to a host
|
|
54
111
|
|
|
55
112
|
**One command, and it writes the entry for you:**
|
|
@@ -80,6 +137,14 @@ hand. Every host runs the same command; only the file and the key around it chan
|
|
|
80
137
|
you installed with `pip` into an environment you keep, replace the `command`/`args` pair
|
|
81
138
|
with the absolute path to the `bantamkit-mcp` console script in that environment.
|
|
82
139
|
|
|
140
|
+
**Prefer that absolute form over the `pipx run` lines below.** A `pipx run` entry needs the
|
|
141
|
+
package index whenever pipx's cache is cold (measured in the amendment under *Install and
|
|
142
|
+
run*). An entry that names a kept console script needs nothing at launch:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{"mcpServers": {"bantamkit": {"command": "/absolute/path/to/env/bin/bantamkit-mcp", "args": []}}}
|
|
146
|
+
```
|
|
147
|
+
|
|
83
148
|
**Claude Code** — one command, no file to edit. `-s user` makes it available in every
|
|
84
149
|
project; drop it for this project only.
|
|
85
150
|
|
|
@@ -33,6 +33,63 @@ The uv equivalent is `uvx --from "bantamkit[mcp]" bantamkit-mcp`. uv is not
|
|
|
33
33
|
installed on the machine this README was measured on, so unlike every other
|
|
34
34
|
command here that one is the documented form rather than a measured one.
|
|
35
35
|
|
|
36
|
+
> **AMENDED 2026-09-15 (job51) — `pipx run` launches online, and it is offline only while
|
|
37
|
+
> pipx's own cache lasts.** The first form above is fine to try the server. As the command a
|
|
38
|
+
> host runs on every launch, it has a cost. Measured with pipx 1.11.1 and `bantamkit 0.33.0`,
|
|
39
|
+
> with the network cut by pointing the proxy variables at a closed port:
|
|
40
|
+
>
|
|
41
|
+
> ```bash
|
|
42
|
+
> PIPX_HOME=<scratch> https_proxy=http://127.0.0.1:1 HTTPS_PROXY=http://127.0.0.1:1 \
|
|
43
|
+
> http_proxy=http://127.0.0.1:1 HTTP_PROXY=http://127.0.0.1:1 PIP_PROXY=http://127.0.0.1:1 \
|
|
44
|
+
> PIP_RETRIES=0 PIP_TIMEOUT=5 pipx run --spec "bantamkit[mcp]==0.33.0" bantamkit-mcp --assets-root
|
|
45
|
+
> ```
|
|
46
|
+
>
|
|
47
|
+
> On a `PIPX_HOME` that had never run it, this exited 1 in 1.33 s. After one run online into
|
|
48
|
+
> the same `PIPX_HOME`, the same command exited 0 in 0.47 s. So a `pipx run` host entry needs
|
|
49
|
+
> the package index on a new machine, after the cache is cleared, and whenever pipx decides
|
|
50
|
+
> its cached environment is stale. That last one is pipx's policy and was not measured here.
|
|
51
|
+
> For a host, install into an environment you keep, as in the next section.
|
|
52
|
+
|
|
53
|
+
### Install once, run offline
|
|
54
|
+
|
|
55
|
+
Install into an environment you keep, then let `--install` record that environment's console
|
|
56
|
+
script:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
python -m venv <env>
|
|
60
|
+
<env>/bin/pip install "bantamkit[mcp]"
|
|
61
|
+
<env>/bin/bantamkit-mcp --install cursor # or claude, claude-desktop, copilot
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
After that, no launch needs the network. `--install` writes the absolute path of the console
|
|
65
|
+
script you ran. Measured 2026-09-15 on macOS arm64 against `bantamkit 0.33.0`,
|
|
66
|
+
`<env>/bin/bantamkit-mcp --install cursor` wrote `"command": "<env>/bin/bantamkit-mcp", "args": []`.
|
|
67
|
+
That command answered `initialize` and `tools/list` with 12 tools under the PATH a GUI app
|
|
68
|
+
inherits on macOS, `/usr/bin:/bin:/usr/sbin:/sbin`. The Windows layout (`<env>\Scripts\`) was
|
|
69
|
+
not measured.
|
|
70
|
+
|
|
71
|
+
**For a machine with no network at all, carry a wheelhouse.** On a connected machine with the
|
|
72
|
+
**same operating system, CPU architecture and Python minor version** as the target:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
python -m pip download "bantamkit[mcp]==0.33.0" -d wheels
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
With Python 3.12.13 on macOS arm64 that wrote 33 files. One of them is
|
|
79
|
+
`pydantic_core-2.46.5-cp312-cp312-macosx_11_0_arm64.whl`, which is built for CPython 3.12 on
|
|
80
|
+
arm64 macOS and nothing else. That is why the two machines must match. Copy `wheels/` across,
|
|
81
|
+
then on the target:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
python -m venv <env>
|
|
85
|
+
<env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.33.0"
|
|
86
|
+
<env>/bin/bantamkit-mcp --install cursor
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Measured in a fresh venv with `PIP_INDEX_URL=http://127.0.0.1:1/` (a closed port): the install
|
|
90
|
+
finished in 1.69 s, and the installed console script served the 12 tools as above. To move to
|
|
91
|
+
a newer version, repeat the download and the install with the new version number.
|
|
92
|
+
|
|
36
93
|
### Connect it to a host
|
|
37
94
|
|
|
38
95
|
**One command, and it writes the entry for you:**
|
|
@@ -63,6 +120,14 @@ hand. Every host runs the same command; only the file and the key around it chan
|
|
|
63
120
|
you installed with `pip` into an environment you keep, replace the `command`/`args` pair
|
|
64
121
|
with the absolute path to the `bantamkit-mcp` console script in that environment.
|
|
65
122
|
|
|
123
|
+
**Prefer that absolute form over the `pipx run` lines below.** A `pipx run` entry needs the
|
|
124
|
+
package index whenever pipx's cache is cold (measured in the amendment under *Install and
|
|
125
|
+
run*). An entry that names a kept console script needs nothing at launch:
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{"mcpServers": {"bantamkit": {"command": "/absolute/path/to/env/bin/bantamkit-mcp", "args": []}}}
|
|
129
|
+
```
|
|
130
|
+
|
|
66
131
|
**Claude Code** — one command, no file to edit. `-s user` makes it available in every
|
|
67
132
|
project; drop it for this project only.
|
|
68
133
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://bantamkit.dev/schemas/shiftwork-checkpoint.json",
|
|
4
4
|
"title": "Shift-work checkpoint contract v1",
|
|
5
|
-
"$comment": "Encodes checkpoint contract v1 (docs/superpowers/specs/2026-08-10-shift-work-checkpoint-contract-draft.md) plus the two driver-forced deltas: plan.units[].role (model dispatch without reading briefs) and state.external[].until_cmd (machine-checkable wait, replacing prose `until`). Re-planning needs no schema change: a planner unit is just a unit. STRICTNESS POSTURE: `version` is const-pinned to 1 so a reader can refuse unknown majors; every object the driver or a session reads by field name sets additionalProperties:false, and every field the draft's schema block shows on every instance is required (empty arrays are legal, so a fresh checkpoint is cheap to write). The two exceptions are `history[]` and `retro[]` items: those are the free-text annotation space the draft treats as notes, so they allow extra keys (e.g. a session adding `seq` or `tokens`) while still requiring their load-bearing fields. `units[].commits` is optional because the draft only carries it on completed units. `state.external[].status` is a non-empty string rather than an enum: the draft closes the enum for unit status (the driver's SUCCESS test) but never enumerates external status, and inventing values here would reject honest checkpoints. `plan.cursor` must name an existing unit id — JSON Schema cannot express that cross-reference, so the driver checks it structurally and escalates on a dangling cursor. Serialization: checkpoints are YAML for humans per the draft, but the v1 driver reads JSON only (stdlib-only rule), so sessions driven by driver.py write .json; this schema validates the parsed document either way. AMENDMENT (job46/AS-2, docs/roadmap-agent-stack.md): `job.roles` is a THIRD v1 addition, beyond the two driver-forced deltas named above, and it is OPTIONAL — a checkpoint that omits it is exactly the document the rest of this comment describes, and every checkpoint written before it existed still validates unchanged. Both CLAUDE.md files say the model a unit runs on is `per role, never random, always logged`; logged it was, in `history[]`/`retro[]`, which are the two objects here that allow extra keys, so nothing could ever compare the model a role was ALLOWED to use against the model that answered. `job.roles` is that declaration, and it sits on `job` because that is where a reader already looks for the rules binding every unit. It is a MAP (unit role -> the model identifiers that role may report), not a record the driver reads by fixed field name, so the closure the rest of this file spells `additionalProperties: false` is spelled here as `propertyNames` over the SAME three names `plan.units[].role` enumerates, with `additionalProperties` carrying the value schema once instead of three times: a key outside the role enum is refused, and so is a value that is not a non-empty array of non-empty strings (an empty list would be a rule no session could satisfy, which is a typo and not a policy). A role the map does not name is unconstrained — declaring one role does not silently forbid the others. The ENFORCEMENT is not here: this file states the contract and the runtimes state the refusal, so no example error text appears in these descriptions. `version` stays 1 because nothing already in the document changes meaning: a reader that ignored `roles` would still read every other field correctly. What it would not do is enforce the rule — and since `job` is closed, an older reader does not ignore the key, it refuses the whole file. That refusal is the intended behaviour and not a gap: opening `job` so an old reader could skip the key is what would make this check bypassable by running an older bantamkit.",
|
|
5
|
+
"$comment": "Encodes checkpoint contract v1 (docs/superpowers/specs/2026-08-10-shift-work-checkpoint-contract-draft.md) plus the two driver-forced deltas: plan.units[].role (model dispatch without reading briefs) and state.external[].until_cmd (machine-checkable wait, replacing prose `until`). Re-planning needs no schema change: a planner unit is just a unit. STRICTNESS POSTURE: `version` is const-pinned to 1 so a reader can refuse unknown majors; every object the driver or a session reads by field name sets additionalProperties:false, and every field the draft's schema block shows on every instance is required (empty arrays are legal, so a fresh checkpoint is cheap to write). The two exceptions are `history[]` and `retro[]` items: those are the free-text annotation space the draft treats as notes, so they allow extra keys (e.g. a session adding `seq` or `tokens`) while still requiring their load-bearing fields. `units[].commits` is optional because the draft only carries it on completed units. `state.external[].status` is a non-empty string rather than an enum: the draft closes the enum for unit status (the driver's SUCCESS test) but never enumerates external status, and inventing values here would reject honest checkpoints. `plan.cursor` must name an existing unit id — JSON Schema cannot express that cross-reference, so the driver checks it structurally and escalates on a dangling cursor. Serialization: checkpoints are YAML for humans per the draft, but the v1 driver reads JSON only (stdlib-only rule), so sessions driven by driver.py write .json; this schema validates the parsed document either way. AMENDMENT (job46/AS-2, docs/roadmap-agent-stack.md): `job.roles` is a THIRD v1 addition, beyond the two driver-forced deltas named above, and it is OPTIONAL — a checkpoint that omits it is exactly the document the rest of this comment describes, and every checkpoint written before it existed still validates unchanged. Both CLAUDE.md files say the model a unit runs on is `per role, never random, always logged`; logged it was, in `history[]`/`retro[]`, which are the two objects here that allow extra keys, so nothing could ever compare the model a role was ALLOWED to use against the model that answered. `job.roles` is that declaration, and it sits on `job` because that is where a reader already looks for the rules binding every unit. It is a MAP (unit role -> the model identifiers that role may report), not a record the driver reads by fixed field name, so the closure the rest of this file spells `additionalProperties: false` is spelled here as `propertyNames` over the SAME three names `plan.units[].role` enumerates, with `additionalProperties` carrying the value schema once instead of three times: a key outside the role enum is refused, and so is a value that is not a non-empty array of non-empty strings (an empty list would be a rule no session could satisfy, which is a typo and not a policy). A role the map does not name is unconstrained — declaring one role does not silently forbid the others. The ENFORCEMENT is not here: this file states the contract and the runtimes state the refusal, so no example error text appears in these descriptions. `version` stays 1 because nothing already in the document changes meaning: a reader that ignored `roles` would still read every other field correctly. What it would not do is enforce the rule — and since `job` is closed, an older reader does not ignore the key, it refuses the whole file. That refusal is the intended behaviour and not a gap: opening `job` so an old reader could skip the key is what would make this check bypassable by running an older bantamkit. AMENDMENT (job50/F8): `handoff.notes` is a FOURTH v1 addition and, like `job.roles`, OPTIONAL, so every checkpoint written before it validates unchanged. `handoff` was the one closed object with nowhere to put a fact that is not an imperative, a question, or a prohibition — a gate baseline, a last commit, a technique worth reusing — and the ledger shows sessions inventing a key for each such fact, being refused, and folding the fact into `next_action` prose instead. The field is a STRING and `handoff` stays `additionalProperties: false`: the defect was the absence of a place for a sentence, not the strictness, and a misspelled `next_action` is refused after this amendment exactly as it was before. The reason it is a string and not a map is in its own description.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": ["version", "job", "plan", "state", "history", "retro", "handoff"],
|
|
8
8
|
"additionalProperties": false,
|
|
@@ -192,6 +192,10 @@
|
|
|
192
192
|
"type": "array",
|
|
193
193
|
"items": {"type": "string", "minLength": 1},
|
|
194
194
|
"description": "Negative space — near-mistakes past sessions made."
|
|
195
|
+
},
|
|
196
|
+
"notes": {
|
|
197
|
+
"type": "string",
|
|
198
|
+
"description": "OPTIONAL. Free-form prose the next session should read that no other key names: a gate baseline, the last commit, a technique worth reusing. A STRING, not a map: every key sessions tried to carry here before this field existed was an attempt to say one sentence, and a map keyed by fact would grow a key per session — the journal the ≤ 2 KB index posture bans, one level down, and an object no schema can close. The same word means the same thing as `history[].notes`. Empty is legal: `handoff` is shallow-merged at clock-out, so a note outlives the unit that wrote it until a later session overwrites it, and the empty string is that overwrite. Declaring this key is what keeps `handoff` closed — a sentence has a home, so an unknown sibling is still a typo and still refused."
|
|
195
199
|
}
|
|
196
200
|
}
|
|
197
201
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bantamkit_read",
|
|
3
3
|
"description": "Read a document through a program, never its raw bytes. Call with `path` alone for the manifest: the file's kind, every part (sheet, document, page) with its row count and byte size, and every omission the reader had to make (embedded images, blank rows, unmapped glyphs, unread pages). Then call with `part` (and `offset`) to page rows; row 0 is the header and each page ends with a continuation line naming the next offset or the end of the part. Do not page through a part to find a row: estimate its offset from the row count and jump. Supported kinds: text/markdown/code, docx, xlsx, html, mhtml; pdf on the Python server only. The Node server refuses pdf, doc and rtf until its reader is ported. A refusal names what the reader actually saw in the file rather than the format's error.",
|
|
4
|
-
"surfaces": [
|
|
5
|
-
"mcp"
|
|
6
|
-
],
|
|
4
|
+
"surfaces": [],
|
|
7
5
|
"parameters": {
|
|
8
6
|
"type": "object",
|
|
9
7
|
"required": [
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "repo_map",
|
|
3
3
|
"description": "A ranked map of a source tree: every file's definitions, ordered by how central that file is to the files you name in `focus`, truncated to a byte budget. Call it when you are about to work on a file and want to know which OTHER files matter to it — the ports, the callers, the module it reaches through a private helper — rather than reading a directory listing and guessing. `focus` is the file or files you are editing, relative to `root` and POSIX-separated; they are excluded from the listing because you already have them open, and an empty focus gives plain centrality over the whole tree. This is a PRECISION pass and it is not a token saving: the gate this feature was supposed to clear was refuted by measurement — discovery is 0.114% of real prompt tokens, because 97.8% of the bill is cache_read — so a map does not make a session cheaper. What it buys is the right file found sooner. Nothing the scanner cannot read is dropped silently: every unread file resolves into a named omission (unknown-language, unreadable-bytes, size-cap, no-definitions, unreachable, per-file-cap, budget) counted in a footer that is NOT charged to the budget. The budget is UTF-8 BYTES of the listing, not tokens; there is no model tokenizer in either runtime and this tool will not pretend to one.",
|
|
4
|
-
"surfaces": [
|
|
5
|
-
"mcp"
|
|
6
|
-
],
|
|
4
|
+
"surfaces": [],
|
|
7
5
|
"parameters": {
|
|
8
6
|
"type": "object",
|
|
9
7
|
"required": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
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. 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.",
|
|
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. 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
4
|
"surfaces": [
|
|
5
5
|
"mcp"
|
|
6
6
|
],
|
|
@@ -0,0 +1,95 @@
|
|
|
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). 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`). `briefed` is written by the runtime, never taken from you — a self-reported value is overwritten by the measured one: true when a brief was issued for this unit since its LAST clock-out (not ever), so a unit re-run inline after a blocked clock-out reads false. It records; it never refuses — a unit that was never clocked in still clocks out, with briefed=false. If the checkpoint's job.roles names this unit's role, accounting.model must be one of that role's model identifiers, spelled exactly \u2014 a model that is not on the list, or none reported at all, is refused before anything is written; a role job.roles omits, and a checkpoint carrying no job.roles, are unconstrained.",
|
|
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
|
+
},
|
|
17
|
+
"status": {
|
|
18
|
+
"title": "Status",
|
|
19
|
+
"type": "string"
|
|
20
|
+
},
|
|
21
|
+
"handoff_patch": {
|
|
22
|
+
"additionalProperties": true,
|
|
23
|
+
"title": "Handoff Patch",
|
|
24
|
+
"type": "object"
|
|
25
|
+
},
|
|
26
|
+
"history_entry": {
|
|
27
|
+
"additionalProperties": true,
|
|
28
|
+
"title": "History Entry",
|
|
29
|
+
"type": "object"
|
|
30
|
+
},
|
|
31
|
+
"accounting": {
|
|
32
|
+
"anyOf": [
|
|
33
|
+
{
|
|
34
|
+
"type": "object",
|
|
35
|
+
"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.",
|
|
36
|
+
"properties": {
|
|
37
|
+
"tokens": {
|
|
38
|
+
"type": "integer",
|
|
39
|
+
"minimum": 0,
|
|
40
|
+
"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. Required, because a unit whose cost is unknown cannot be compared with any other; a rounded self-estimate is allowed only if `note` says it is one."
|
|
41
|
+
},
|
|
42
|
+
"cache_read_tokens": {
|
|
43
|
+
"type": "integer",
|
|
44
|
+
"minimum": 0,
|
|
45
|
+
"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."
|
|
46
|
+
},
|
|
47
|
+
"duration_ms": {
|
|
48
|
+
"type": "integer",
|
|
49
|
+
"minimum": 0,
|
|
50
|
+
"description": "Wall-clock from spawning the subagent to its final message, in whole milliseconds. Required, and the only duration key with a defined meaning: older lines carry `duration`, `duration_min` or `duration_s`, which this schema neither reads nor renames."
|
|
51
|
+
},
|
|
52
|
+
"model": {
|
|
53
|
+
"type": "string",
|
|
54
|
+
"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."
|
|
55
|
+
},
|
|
56
|
+
"tool_uses": {
|
|
57
|
+
"type": "integer",
|
|
58
|
+
"minimum": 0,
|
|
59
|
+
"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)."
|
|
60
|
+
},
|
|
61
|
+
"note": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"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`."
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"required": [
|
|
67
|
+
"tokens",
|
|
68
|
+
"duration_ms"
|
|
69
|
+
],
|
|
70
|
+
"additionalProperties": true
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"type": "null"
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
"default": null,
|
|
77
|
+
"title": "Accounting"
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"required": [
|
|
81
|
+
"checkpoint",
|
|
82
|
+
"unit_id",
|
|
83
|
+
"status",
|
|
84
|
+
"handoff_patch",
|
|
85
|
+
"history_entry"
|
|
86
|
+
],
|
|
87
|
+
"type": "object",
|
|
88
|
+
"title": "shiftwork_clock_outArguments"
|
|
89
|
+
},
|
|
90
|
+
"output_schema": {
|
|
91
|
+
"type": "object",
|
|
92
|
+
"additionalProperties": true,
|
|
93
|
+
"title": "shiftwork_clock_outDictOutput"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "skill_audit",
|
|
3
|
+
"description": "Price the skill catalogue every session pays for, and name the collisions in it. A skill's `description:` frontmatter is loaded into the agent's context in EVERY session; its body is read only when the skill is invoked, so the descriptions are the standing bill. Call it before adding or retiring a skill, or when two skills keep firing on the same phrase. Walks `root` for `<marketplace>/<plugin>/<version>/skills/<name>/SKILL.md` and answers one JSON document: `roots`, `skills` (counted), `catalogue_bytes` (UTF-8 bytes of their `description:` values), `findings` and `omissions`. Read `findings` first — each is `{kind, severity, skills, detail}`: `shared-trigger-phrase` (high; two skills quote the same literal phrase, so which fires is a coin flip), `catalogue-over-budget` (high; only when `budget` is given), `never-invoked` (low; only when `usage` is given), `frontmatter-malformed` and `name-mismatch` (medium). Then `omissions`: counted skills plus omissions account for every SKILL.md found, each `{subject, count, size, what}` with subject one of `plugin-not-enabled`, `duplicate-skill`, `stale-version`, `unreadable-file`, `unparsed-frontmatter`. The tool reads nothing but `root`; the three facts a directory cannot answer come from the caller — `enabled` (plugin ids the host has switched on, `<plugin>@<marketplace>`; the cache also holds disabled plugins, so without it the bill is inflated), `usage` (call counts per skill) and `versions` (the version directory the host serves per plugin; a plugin absent from it gets the directory name that sorts LAST in byte order, which is wrong for `10.0.0` against `9.0.0`). Refused with their own sentence, never as a partial answer: an unknown `check`, a negative `budget`, an EMPTY `root`, a `root` that is missing or is a file. Full rules in docs/skill-audit.md.",
|
|
4
|
+
"surfaces": [
|
|
5
|
+
"mcp"
|
|
6
|
+
],
|
|
7
|
+
"parameters": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"required": [
|
|
10
|
+
"root"
|
|
11
|
+
],
|
|
12
|
+
"properties": {
|
|
13
|
+
"root": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Directory to scan for SKILL.md files, absolute or relative to the server's working directory. It must name a directory: the empty string is refused rather than resolved, because resolving it would audit whatever directory the server happens to be standing in"
|
|
16
|
+
},
|
|
17
|
+
"enabled": {
|
|
18
|
+
"type": "array",
|
|
19
|
+
"items": {
|
|
20
|
+
"type": "string"
|
|
21
|
+
},
|
|
22
|
+
"description": "Plugin ids that are switched on, `<plugin>@<marketplace>`; when given only skills under those plugins are counted, when omitted every skill under `root` counts"
|
|
23
|
+
},
|
|
24
|
+
"usage": {
|
|
25
|
+
"type": "object",
|
|
26
|
+
"additionalProperties": {
|
|
27
|
+
"type": "integer",
|
|
28
|
+
"minimum": 0
|
|
29
|
+
},
|
|
30
|
+
"description": "Skill id (`<plugin>:<name>`) to call count, the caller's own measurement; a counted skill absent from a supplied map is treated as zero"
|
|
31
|
+
},
|
|
32
|
+
"check": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"enum": [
|
|
35
|
+
"all",
|
|
36
|
+
"phrase",
|
|
37
|
+
"budget",
|
|
38
|
+
"frontmatter"
|
|
39
|
+
],
|
|
40
|
+
"description": "Which family of findings to report; default `all`. `skills`, `catalogue_bytes` and `omissions` are reported whatever this says"
|
|
41
|
+
},
|
|
42
|
+
"budget": {
|
|
43
|
+
"type": "integer",
|
|
44
|
+
"minimum": 0,
|
|
45
|
+
"maximum": 9007199254740991,
|
|
46
|
+
"description": "Catalogue byte budget; `catalogue-over-budget` is only reported when this is given"
|
|
47
|
+
},
|
|
48
|
+
"versions": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"additionalProperties": {
|
|
51
|
+
"type": "string"
|
|
52
|
+
},
|
|
53
|
+
"description": "Plugin id (`<plugin>@<marketplace>`) to the version directory name the host actually serves; when a plugin is named here that directory is resolved whatever byte order would have said, and a plugin absent from it falls back to byte order"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"output_schema": {
|
|
58
|
+
"properties": {
|
|
59
|
+
"result": {
|
|
60
|
+
"title": "Result",
|
|
61
|
+
"type": "string"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"required": [
|
|
65
|
+
"result"
|
|
66
|
+
],
|
|
67
|
+
"type": "object",
|
|
68
|
+
"title": "skill_auditOutput"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "token_ledger",
|
|
3
|
+
"description": "What a session actually cost, read off the host's own transcripts. Walks `root` for `*.jsonl` transcripts — the host writes `<cwd-slug>/<session>.jsonl` and `<cwd-slug>/<session>/subagents/*.jsonl` beneath `~/.claude/projects` — and answers ONE JSON document: `root`, `transcripts`, `lines`, `requests` (distinct API requests), `totals` (the four classes: `input_tokens`, `cache_creation_input_tokens`, `cache_read_input_tokens`, `output_tokens`), `sessions` (one row each), `omissions`, and `cost` only when `model` is given. Call it to answer 'what did this work cost' from the API's own `usage` blocks — nothing here is estimated. Point `root` at ONE project's slug directory, not the whole projects tree: there is no time window and no summary mode, so a whole-corpus call answers a row per session ever recorded and blows the host's tool-result cap. The four classes are reported and priced separately because on a real prompt 98.1 % of the tokens were `cache_read`. Counting is per `requestId`, never per line: one response is written as several records with the same `usage`, so the dedupe spans the whole walk and every later copy is a `duplicate-request` omission. A subagent's transcript carries its PARENT's `sessionId`, so its cost lands in the parent row as `sidechain_requests`. `lines` equals `requests` plus the sum of every omission's `count`, always. An omission is `{subject, count, what}`; `what` names the first site as `<relpath>:<line>` plus `and N more`. `cost` needs a rate: the shipped price table has none, so `{\"unavailable\": \"no rate recorded for model ...\"}` is the NORMAL answer, not an error; a rate enters through `$BANTAMKIT_PRICES` or `prices`. Refused with their own sentence: an EMPTY `root`, a `root` that is missing or is a file, an EMPTY `model`, and a token total above 2**53-1. The record rule and the nine omission subjects: docs/ledger.md.",
|
|
4
|
+
"surfaces": [
|
|
5
|
+
"mcp"
|
|
6
|
+
],
|
|
7
|
+
"parameters": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"required": [
|
|
10
|
+
"root"
|
|
11
|
+
],
|
|
12
|
+
"properties": {
|
|
13
|
+
"root": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Directory of host transcripts to walk, absolute or relative to the server's working directory; `~/.claude/projects` is where the host keeps them on this machine. It must name a directory: the empty string is refused rather than resolved, because resolving it would read whatever directory the server happens to be standing in"
|
|
16
|
+
},
|
|
17
|
+
"model": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "Model to price the totals as, e.g. the id an assistant record's `message.model` carries. Omit it and no `cost` key is reported at all; name one with no recorded rate and `cost` is `{\"unavailable\": ...}`, which is what the shipped table answers for every model"
|
|
20
|
+
},
|
|
21
|
+
"prices": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "Price table to read instead of `$BANTAMKIT_PRICES` or the shipped one; only consulted when `model` is given. A malformed table is a configuration fault and stops with its own sentence, rather than being reported as an unpriced model"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"output_schema": {
|
|
28
|
+
"properties": {
|
|
29
|
+
"result": {
|
|
30
|
+
"title": "Result",
|
|
31
|
+
"type": "string"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"required": [
|
|
35
|
+
"result"
|
|
36
|
+
],
|
|
37
|
+
"type": "object",
|
|
38
|
+
"title": "token_ledgerOutput"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -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.
|
|
32
|
+
__version__ = "0.34.0"
|
|
@@ -30,12 +30,15 @@ THREE HARD RULES, each with the failure it prevents:
|
|
|
30
30
|
byte-compares both runtimes' streams; one stray write breaks the wire suite. Nothing
|
|
31
31
|
in this module touches `sys.stderr` or `sys.stdout`.
|
|
32
32
|
* **Metadata only.** Never a tool argument's value, never a memory body, never a
|
|
33
|
-
validated output, never a query, never a document row. Eight of the
|
|
34
|
-
unbounded
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
validated output, never a query, never a document row. Eight of the twelve tools take
|
|
34
|
+
an unbounded string (counted over `assets/tools/`: a `string` parameter with no `enum`
|
|
35
|
+
or `maxLength`, or an array of such; `bantamkit_read` and `repo_map` were two more until
|
|
36
|
+
job50 I5 retired them from the roster) and among those `skill_audit`'s `root`,
|
|
37
|
+
`token_ledger`'s `root` and `prices` and the three shift-work tools' `checkpoint` are
|
|
38
|
+
absolute paths; each record carries counts and tokens from a closed set, never the
|
|
39
|
+
path, never a part name, never a skill id, never a mapped file, never a session id,
|
|
40
|
+
never a model name. The dormant `bantamkit_read` and `repo_map` handlers keep the same
|
|
41
|
+
discipline: a token and two counts, never `path`, `part`, `root` or `focus`.
|
|
39
42
|
Every value written here is an ASCII token from a closed
|
|
40
43
|
set, an `int`, or a `bool`.
|
|
41
44
|
* **Never `str(exception)`.** Only `type(exc).__name__`. This is not hypothetical: the
|
|
@@ -66,6 +69,8 @@ from datetime import UTC, datetime, timedelta
|
|
|
66
69
|
from pathlib import Path
|
|
67
70
|
from typing import Any
|
|
68
71
|
|
|
72
|
+
from bantamkit.memory.store import ensure_bantamkit_gitignore
|
|
73
|
+
|
|
69
74
|
#: Environment switch. Unset or `off`/`0`/`false`/`no`/empty -> disabled. `on`/`1`/
|
|
70
75
|
#: `true`/`yes` -> the default file inside the memory store. Anything else is taken as
|
|
71
76
|
#: the literal path of the log file.
|
|
@@ -273,7 +278,28 @@ class EventLog:
|
|
|
273
278
|
intent, not a live path.
|
|
274
279
|
"""
|
|
275
280
|
assert self.path is not None
|
|
281
|
+
# AUDIT FINDING (J51-1): this `mkdir(parents=True)` can bring a whole `.bantamkit`
|
|
282
|
+
# directory into existence on its own -- `BANTAMKIT_EVENT_LOG=on` with a project
|
|
283
|
+
# store that was never saved to reaches here first -- entirely bypassing
|
|
284
|
+
# `MemoryStore._ensure_dirs`, which is the only other place a `.bantamkit`
|
|
285
|
+
# directory gets created. Without this call a store built that way would never get
|
|
286
|
+
# its self-ignoring `.gitignore`. Cheap and idempotent: a no-op unless one of
|
|
287
|
+
# `self.path`'s ancestors is literally named `.bantamkit`.
|
|
288
|
+
#
|
|
289
|
+
# USER RULING #2 (J51-8a): the ignore file is written only when THIS call is what
|
|
290
|
+
# creates `.bantamkit`, so existence has to be checked BEFORE the mkdir below --
|
|
291
|
+
# after it, the directory unconditionally exists and the question is unanswerable.
|
|
292
|
+
bantamkit_dir = None
|
|
293
|
+
for parent in self.path.parents:
|
|
294
|
+
if parent.name == ".bantamkit":
|
|
295
|
+
bantamkit_dir = parent
|
|
296
|
+
break
|
|
297
|
+
bantamkit_dir_existed_before = bantamkit_dir is not None and bantamkit_dir.exists()
|
|
276
298
|
self.path.parent.mkdir(parents=True, exist_ok=True)
|
|
299
|
+
if bantamkit_dir is not None:
|
|
300
|
+
ensure_bantamkit_gitignore(
|
|
301
|
+
bantamkit_dir, created=not bantamkit_dir_existed_before
|
|
302
|
+
)
|
|
277
303
|
try:
|
|
278
304
|
size = self.path.stat().st_size
|
|
279
305
|
except FileNotFoundError:
|
|
@@ -15,10 +15,12 @@ convenience — a file the host owns and rewrites is a file we should not be mer
|
|
|
15
15
|
hand.
|
|
16
16
|
|
|
17
17
|
WHAT THIS WRITES IS WHAT IS RUNNING. The command recorded is this interpreter's own
|
|
18
|
-
`bantamkit-mcp` console script, by absolute path.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
`bantamkit-mcp` console script, by absolute path. Since J51-4, the Node side records its
|
|
19
|
+
own absolute command the same way -- `<absolute node> <absolute dist/cli.js>` of the kept
|
|
20
|
+
install under `~/.bantamkit/mcp` -- for the same reason: the thing installed should be the
|
|
21
|
+
thing that answers, and neither side should send a host looking for the other's runtime.
|
|
22
|
+
The two outputs therefore DIFFER by construction (different interpreter, different path)
|
|
23
|
+
and that difference is ruled in `docs/porting.md`.
|
|
22
24
|
|
|
23
25
|
WHY IT NEVER PROMPTS. An overwrite is exactly the moment a program wants to ask, and asking
|
|
24
26
|
requires a terminal. Measured repeatedly on this machine: Claude Code's `!` channel has no
|
|
@@ -1015,6 +1015,9 @@ class _ArgMetadata(FuncMetadata): # type: ignore[misc,valid-type]
|
|
|
1015
1015
|
|
|
1016
1016
|
|
|
1017
1017
|
# Tools whose arguments reach the handler exactly as sent — see `_ArgMetadata`.
|
|
1018
|
+
# DORMANT — `bantamkit_read` left the roster (job50 I5, 2026-09-12), so no served tool is
|
|
1019
|
+
# in this set today and `unwrap_json` is `True` for all twelve. The entry stays so that
|
|
1020
|
+
# restoring the roster line restores the property with it.
|
|
1018
1021
|
_NO_JSON_UNWRAP = frozenset({"bantamkit_read"})
|
|
1019
1022
|
|
|
1020
1023
|
|
|
@@ -1039,6 +1042,9 @@ OFFSET_MAXIMUM = 9007199254740991
|
|
|
1039
1042
|
class _DocumentCache:
|
|
1040
1043
|
"""The last `docread.extract` result this server produced, and what it was OF.
|
|
1041
1044
|
|
|
1045
|
+
DORMANT — its one user, `bantamkit_read`, left the roster (job50 I5, 2026-09-12); kept
|
|
1046
|
+
with the handler so the roster line can come back without re-deriving the cache.
|
|
1047
|
+
|
|
1042
1048
|
Register entry (i): `bantamkit_read` re-parsed the whole document on EVERY call, so a
|
|
1043
1049
|
caller paging a 12,001-row sheet in 200-row pages parsed the workbook once per page —
|
|
1044
1050
|
paging was O(N^2) in the row window. Measured on this machine over a 1,538,280-byte
|
|
@@ -1220,6 +1226,10 @@ def _record_result(log: EventLog, tool: str, call: Callable[[], dict[str, Any]])
|
|
|
1220
1226
|
|
|
1221
1227
|
#: The last paragraph of every `repo_map` reply, refusal excepted. FIXED AND MANDATORY.
|
|
1222
1228
|
#:
|
|
1229
|
+
#: DORMANT — `repo_map` left the roster (job50 I5, 2026-09-12). The tail, the empty-listing
|
|
1230
|
+
#: sentence and `repo_map_reply` below stay with the handler: a roster decision, not a
|
|
1231
|
+
#: deletion of working code.
|
|
1232
|
+
#:
|
|
1223
1233
|
#: Roadmap row 10's build gate was "build only after #4 shows discovery tokens dominate",
|
|
1224
1234
|
#: and #4 REFUTED it: discovery is 0.114 % of real prompt tokens because 97.8 % of the
|
|
1225
1235
|
#: bill is `cache_read`. The feature ships on an explicit ruling to build it anyway, as a
|
|
@@ -1516,6 +1526,12 @@ def build_server(memory: Memory, log: EventLog | None = None) -> Any:
|
|
|
1516
1526
|
) -> str:
|
|
1517
1527
|
"""The reader on the MCP surface (job43): `docread` digests, `contract` words it.
|
|
1518
1528
|
|
|
1529
|
+
DORMANT — NOT REGISTERED since job50 I5 (user ruling, 2026-09-12): `bantamkit_read`
|
|
1530
|
+
left the roster because the transcript corpus showed it was never called. The
|
|
1531
|
+
reader (`docread`, `docmanifest`, `contract`) and its tests are untouched; this
|
|
1532
|
+
handler, its document cache and `OFFSET_MAXIMUM` are kept, unregistered, so the
|
|
1533
|
+
roster line can return without a rewrite.
|
|
1534
|
+
|
|
1519
1535
|
The eval pair (`evalrun._document_tools`) already renders a manifest, a page and
|
|
1520
1536
|
every refusal from these two modules, and this handler makes the SAME calls with
|
|
1521
1537
|
the path standing in for the document name, so the two surfaces print the same
|
|
@@ -1660,6 +1676,11 @@ def build_server(memory: Memory, log: EventLog | None = None) -> Any:
|
|
|
1660
1676
|
) -> str:
|
|
1661
1677
|
"""The ranked definition map on the MCP surface: `repomap` measures, this serves it.
|
|
1662
1678
|
|
|
1679
|
+
DORMANT — NOT REGISTERED since job50 I5 (user ruling, 2026-09-12): `repo_map` left
|
|
1680
|
+
the roster because the transcript corpus showed it was never called. The engine
|
|
1681
|
+
(`repomap.py`) and its tests are untouched; this handler is kept, unregistered, so
|
|
1682
|
+
the roster line can return without a rewrite.
|
|
1683
|
+
|
|
1663
1684
|
THE THREE REFUSALS LIVE HERE AND NOT IN `repomap.py`, and that is deliberate.
|
|
1664
1685
|
`repo_map()` over a root that does not exist answers an EMPTY map on both runtimes
|
|
1665
1686
|
— `os.walk` yields nothing for a missing directory and `walkSources`' `readdirSync`
|
|
@@ -1784,12 +1805,20 @@ def build_server(memory: Memory, log: EventLog | None = None) -> Any:
|
|
|
1784
1805
|
# the server, because the server cannot start without it.
|
|
1785
1806
|
#
|
|
1786
1807
|
# `bantamkit_status` went LAST rather than first, `memory_compact` after it rather
|
|
1787
|
-
# than beside `memory_save` where a reader would look for it, `
|
|
1788
|
-
#
|
|
1789
|
-
#
|
|
1808
|
+
# than beside `memory_save` where a reader would look for it, `skill_audit` after
|
|
1809
|
+
# that, `memory_dream` after that and `token_ledger` after that. Registration order
|
|
1810
|
+
# IS the served order
|
|
1790
1811
|
# (`test_tool_manifest.py::test_the_golden_records_the_order_the_wire_actually_
|
|
1791
1812
|
# serves`), and appending is the only edit that leaves the others where every
|
|
1792
1813
|
# existing declaration says they are.
|
|
1814
|
+
#
|
|
1815
|
+
# `bantamkit_read` (tenth) and `repo_map` (thirteenth) LEFT this list on the user's
|
|
1816
|
+
# ruling of 2026-09-12 (job50, I5): measured over the transcript corpus, neither was
|
|
1817
|
+
# called — auto-mode routes discovery and reading through Bash — and every request
|
|
1818
|
+
# re-sent their descriptions. Their assets claim NO surface now (`"surfaces": []`),
|
|
1819
|
+
# so putting either name back here without also restoring `"mcp"` to its asset is
|
|
1820
|
+
# refused by `_from_manifest` at startup. The handlers below are DORMANT, not gone:
|
|
1821
|
+
# a roster decision, not a deletion of working code.
|
|
1793
1822
|
tools = [
|
|
1794
1823
|
_from_manifest(memory_save, "memory_save"),
|
|
1795
1824
|
_from_manifest(memory_recall, "memory_recall"),
|
|
@@ -1800,10 +1829,8 @@ def build_server(memory: Memory, log: EventLog | None = None) -> Any:
|
|
|
1800
1829
|
_from_manifest(build_identity_tool, "build_identity"),
|
|
1801
1830
|
_from_manifest(bantamkit_status, "bantamkit_status"),
|
|
1802
1831
|
_from_manifest(memory_compact, "memory_compact"),
|
|
1803
|
-
_from_manifest(bantamkit_read, "bantamkit_read"),
|
|
1804
1832
|
_from_manifest(skill_audit, "skill_audit"),
|
|
1805
1833
|
_from_manifest(memory_dream, "memory_dream"),
|
|
1806
|
-
_from_manifest(repo_map, "repo_map"),
|
|
1807
1834
|
_from_manifest(token_ledger, "token_ledger"),
|
|
1808
1835
|
]
|
|
1809
1836
|
|