bantamkit 0.36.2__tar.gz → 0.37.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.36.2 → bantamkit-0.37.0}/PKG-INFO +14 -17
- {bantamkit-0.36.2 → bantamkit-0.37.0}/README.md +12 -15
- bantamkit-0.37.0/_assets/skills/memory-queries.md +12 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/skills/memory.md +7 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/memory_compact.json +1 -1
- bantamkit-0.37.0/_assets/tools/memory_queries.json +92 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/memory_recall.json +11 -4
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/memory_save.json +14 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/shiftwork_status.json +26 -1
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/__init__.py +1 -1
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/eventlog.py +31 -13
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/hookadapter.py +373 -45
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/hostinstall.py +15 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/mcpserver.py +216 -15
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/memory/__main__.py +1 -1
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/memory/component.py +687 -80
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/memory/divergence.py +3 -2
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/memory/dream.py +19 -0
- bantamkit-0.37.0/src/bantamkit/memory/native.py +209 -0
- bantamkit-0.37.0/src/bantamkit/memory/queries.py +248 -0
- bantamkit-0.37.0/src/bantamkit/memory/retrieval.py +476 -0
- bantamkit-0.37.0/src/bantamkit/memory/skills.py +238 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/memory/store.py +847 -86
- bantamkit-0.37.0/src/bantamkit/memory/usage.py +342 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/shiftwork.py +13 -3
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/skillaudit.py +139 -49
- bantamkit-0.37.0/src/bantamkit/skilldraft.py +671 -0
- bantamkit-0.37.0/src/bantamkit/skillfile.py +621 -0
- bantamkit-0.37.0/src/bantamkit/skillhost.py +369 -0
- bantamkit-0.37.0/src/bantamkit/skillinstall.py +1482 -0
- bantamkit-0.37.0/src/bantamkit/skillmine.py +1844 -0
- bantamkit-0.37.0/src/bantamkit/skillpromote.py +382 -0
- bantamkit-0.37.0/src/bantamkit/skillpropose.py +795 -0
- bantamkit-0.37.0/src/bantamkit/skillreport.py +603 -0
- bantamkit-0.37.0/src/bantamkit/storage/__init__.py +20 -0
- bantamkit-0.37.0/src/bantamkit/storage/coldindex.py +308 -0
- bantamkit-0.37.0/src/bantamkit/storage/hotindex.py +1002 -0
- bantamkit-0.37.0/src/bantamkit/storage/lock.py +75 -0
- bantamkit-0.37.0/src/bantamkit/storage/logsegment.py +394 -0
- bantamkit-0.37.0/src/bantamkit/storage/retention.py +838 -0
- bantamkit-0.37.0/src/bantamkit/storage/tiers.py +207 -0
- bantamkit-0.37.0/src/bantamkit/touch/__init__.py +89 -0
- bantamkit-0.37.0/src/bantamkit/touch/bashturn.py +91 -0
- bantamkit-0.37.0/src/bantamkit/touch/context.py +112 -0
- bantamkit-0.37.0/src/bantamkit/touch/graph.py +214 -0
- bantamkit-0.37.0/src/bantamkit/touch/log.py +351 -0
- bantamkit-0.37.0/src/bantamkit/touch/recallfile.py +99 -0
- bantamkit-0.37.0/src/bantamkit/touch/refs.py +105 -0
- bantamkit-0.37.0/src/bantamkit/touch/repo.py +335 -0
- bantamkit-0.37.0/src/bantamkit/touch/summary.py +196 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/conftest.py +62 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/served-tool-surface.json +142 -7
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_build_identity.py +1 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_conformance_suite_table_gate.py +7 -1
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_docread_ceilings.py +5 -2
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_eventlog.py +12 -2
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_hookadapter.py +620 -14
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_layers.py +2 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_mcpserver.py +54 -2
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_memory.py +339 -32
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_memory_compact_tool.py +2 -1
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_memory_component.py +131 -26
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_memory_dream.py +36 -0
- bantamkit-0.37.0/tests/test_memory_native.py +210 -0
- bantamkit-0.37.0/tests/test_memory_queries.py +566 -0
- bantamkit-0.37.0/tests/test_memory_retrieval.py +263 -0
- bantamkit-0.37.0/tests/test_memory_skills.py +273 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_memory_strings.py +73 -1
- bantamkit-0.37.0/tests/test_memory_usage.py +291 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_served_tool_count_records.py +11 -11
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_skillaudit.py +1 -1
- bantamkit-0.37.0/tests/test_skillaudit_roots.py +111 -0
- bantamkit-0.37.0/tests/test_skilldraft.py +444 -0
- bantamkit-0.37.0/tests/test_skillfile.py +488 -0
- bantamkit-0.37.0/tests/test_skillhost.py +246 -0
- bantamkit-0.37.0/tests/test_skillimprove.py +429 -0
- bantamkit-0.37.0/tests/test_skillimprove_signals.py +558 -0
- bantamkit-0.37.0/tests/test_skillinstall.py +334 -0
- bantamkit-0.37.0/tests/test_skillmine.py +1014 -0
- bantamkit-0.37.0/tests/test_skillmine_daily.py +418 -0
- bantamkit-0.37.0/tests/test_skillpromote.py +269 -0
- bantamkit-0.37.0/tests/test_skillpropose.py +356 -0
- bantamkit-0.37.0/tests/test_skillreport.py +479 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_status_surface.py +145 -5
- bantamkit-0.37.0/tests/test_storage_bar.py +42 -0
- bantamkit-0.37.0/tests/test_storage_coldindex.py +174 -0
- bantamkit-0.37.0/tests/test_storage_hotindex.py +302 -0
- bantamkit-0.37.0/tests/test_storage_log.py +348 -0
- bantamkit-0.37.0/tests/test_storage_log_consumers.py +187 -0
- bantamkit-0.37.0/tests/test_storage_recall_index.py +182 -0
- bantamkit-0.37.0/tests/test_storage_retention.py +499 -0
- bantamkit-0.37.0/tests/test_storage_tiers.py +186 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_tokenledger.py +1 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_tool_annotations.py +2 -2
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_tool_manifest.py +23 -0
- bantamkit-0.37.0/tests/test_touch_bashturn.py +79 -0
- bantamkit-0.37.0/tests/test_touch_context.py +104 -0
- bantamkit-0.37.0/tests/test_touch_graph.py +235 -0
- bantamkit-0.37.0/tests/test_touch_log.py +517 -0
- bantamkit-0.37.0/tests/test_touch_recall_file.py +187 -0
- bantamkit-0.37.0/tests/test_touch_refs.py +152 -0
- bantamkit-0.37.0/tests/test_touch_summary.py +262 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_unknown_arguments.py +2 -2
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_version_agreement.py +99 -2
- {bantamkit-0.36.2 → bantamkit-0.37.0}/.gitignore +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/contracts/default.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/manifest.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/HISTORY.md +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/README.md +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/docs/architecture.md +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/docs/runbook.md +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/issues/142-settlement-timeout.md +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/patches/0009-retry-budget.patch +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/src/ledger/__init__.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/src/ledger/config.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/src/ledger/errors.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/src/ledger/posting.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/src/ledger/registry.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/src/ledger/report.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/src/ledger/retry.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/src/ledger/settle.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/src/ledger/validate.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/tests/test_posting.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/repo/tests/test_settle.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/tasks/dt-error-contract.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/tasks/dt-handler-map.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/tasks/dt-patch-before-after.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/tasks/dt-retry-attempts.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/tasks/dt-settlement-config.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/tasks/dt-symbol-home.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/tasks/dt-trace-blame.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/devteam/tasks/dt-unread-key.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/document/tasks/doc-large-in-137.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/document/tasks/doc-large-in-359.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/document/tasks/doc-large-in-372.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/document/tasks/doc-large-out-11764.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/document/tasks/doc-large-out-4137.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/document/tasks/doc-large-out-8022.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/document/tasks/doc-small-137.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/document/tasks/doc-small-261.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/document/tasks/doc-small-388.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/fixtures/.gitkeep +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/fixtures/catalog.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/perturbations/task-completion.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/.gitkeep +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/extract-contact.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/extract-invoice.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/extract-order.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/extract-schedule.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/extract-versions.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/nav-prod-port.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/nav-release-bundle.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/recall-audit-retention.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/recall-cache-ttl.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/recall-db-port.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/recall-deploy.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/recall-env-endpoint.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/recall-oncall-rotation.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/recall-oncall.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/recall-org-quota.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/recall-owner.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/shop-basket-total.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/shop-cheapest.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/shop-compare.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/shop-gadget-value.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/shop-stock-total.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/evals/tasks/shop-total.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/pricing/default.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/profiles/default.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/profiles/patient.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/rubrics/.gitkeep +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/rubrics/code-quality.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/rubrics/grounded-completion.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/rubrics/task-completion.yaml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/schemas/shiftwork-checkpoint.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/skills/.gitkeep +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/skills/file-graph.md +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/.gitkeep +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/bantamkit_read.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/bantamkit_status.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/build_identity.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/document_list.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/document_read.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/file_graph.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/memory_dream.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/repo_map.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/shiftwork_clock_in.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/shiftwork_clock_out.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/shiftwork_plan.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/skill_audit.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/token_ledger.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/validate_json.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/_assets/tools/work_plan.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/hatch_build.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/pyproject.toml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/agent.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/assets.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/budget.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/client.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/contract.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/criticreplay.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/critique.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/docmanifest.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/docread.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/evalrun.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/filegraph.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/loopguard.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/mcpreport.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/mcpstdio.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/memory/__init__.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/memory/layers.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/pdfread.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/pricing.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/profile.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/repomap.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/selfupdate.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/statusline.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/structured.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/textutil.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/tokenledger.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/updatecheck.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/src/bantamkit/workplan.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/cli_exit_status_probe.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/docread/bad-crc.docx +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/docread/charref-4301-digits.html +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/docread/charset-table.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/docread/compression-method-9.docx +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/docread/corrupt-deflate.docx +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/docread/encrypted-member.docx +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/docread/encrypted-mimetype.odt +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/docread/eszett-cell-ref.xlsx +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/docread/internal-dtd-entity.docx +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/docread/rfc2231-charset.eml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/docread/rfc822-nested-twice.eml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/docread/unicode-digit-shared-string.xlsx +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/docread/x-uuencode.eml +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/f8404ab-perturbation-baseline.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/data/platform-assumption-baseline.json +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/docread_fixtures.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/perturbation_baseline_harness.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/rbp16_effect_probe.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/rbp18_payload_probe.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_adapter.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_agent.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_amendguard.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_assets.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_bantamkit_gitignore.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_bantamkit_read_tool.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_budget.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_cli_oneshot.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_client.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_compaction_corpus_survey.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_conformance.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_conformance_harness_resilience.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_contract_fanout.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_contract_patterns.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_contract_refs.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_criticreplay.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_critique.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_doc_commands_gate.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_docread.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_document_manifest_parity.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_document_setup.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_document_tasks.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_document_tools.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_encoding_gate.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_evalrun.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_field_program_gates.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_field_programs.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_filegraph.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_hostinstall.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_hostinstall_hooks.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_install_shape.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_ladder_statistics.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_launcher_which.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_loopguard.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_mcp_endpoint.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_mcp_request_guard.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_mcpdrift.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_mcpreport.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_mcpstdio_frames.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_memory_divergence.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_memory_layers.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_memory_lifecycle.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_memory_store_tripwire.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_mutmatrix.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_nativeexport.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_newline_gate.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_packaging.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_pdfread.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_pinharness_ledger.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_platform_assumption_gate.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_pricing.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_readme_separation.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_repo_map_tool.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_repomap.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_selfupdate.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_shiftwork.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_statusline.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_structured.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_thread_exception_gate.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_updatecheck.py +0 -0
- {bantamkit-0.36.2 → bantamkit-0.37.0}/tests/test_workplan.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: bantamkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.37.0
|
|
4
4
|
Summary: Persistent memory for coding agents: an MCP server for Claude Code, Claude Desktop, Cursor and VS Code Copilot, plus a Python library that lifts small-model agents. Install once, run offline.
|
|
5
5
|
Project-URL: Homepage, https://github.com/Ink01101011/bantamkit
|
|
6
6
|
Project-URL: Repository, https://github.com/Ink01101011/bantamkit
|
|
@@ -74,13 +74,12 @@ Then restart the host (in Claude Code, open a new session) and ask the agent to
|
|
|
74
74
|
- **Offline after one install.** `--install` records the venv's console script by absolute path,
|
|
75
75
|
so no launch needs the network or your shell's PATH.
|
|
76
76
|
- **Claude Code hooks, if you want them.** `--install-hooks` puts the memory index in front of
|
|
77
|
-
each new session, surfaces matching facts on each prompt,
|
|
78
|
-
|
|
79
|
-
the end of a long session that saved nothing
|
|
77
|
+
each new session, surfaces matching facts on each prompt, and nudges a save at the end of a
|
|
78
|
+
long session that saved nothing
|
|
80
79
|
([docs/hooks.md](https://github.com/Ink01101011/bantamkit/blob/main/docs/hooks.md)).
|
|
81
80
|
- **More than memory.** JSON Schema validation, a token ledger read off the host's transcripts,
|
|
82
81
|
a skill-catalogue audit, and shift-work tools that plan and hand off multi-step jobs —
|
|
83
|
-
[the
|
|
82
|
+
[the fifteen tools](#-what-it-serves).
|
|
84
83
|
- **Same answers as the Node server.** The two share a memory store on disk, and every surface
|
|
85
84
|
is compared between both runtimes by a conformance suite (`node tools/conformance/run.mjs
|
|
86
85
|
--all` in the repository), so install whichever your host makes easy.
|
|
@@ -103,10 +102,10 @@ Then restart the host (in Claude Code, open a new session) and ask the agent to
|
|
|
103
102
|
| [Configuration](#-configuration) | Every flag and variable, with its default |
|
|
104
103
|
| [Update](#-update) | `--update`, pipx, uv, then restart |
|
|
105
104
|
| [Troubleshooting](#-troubleshooting) | Timeouts, refusals, the wrong store |
|
|
106
|
-
| [What it serves](#-what-it-serves) |
|
|
105
|
+
| [What it serves](#-what-it-serves) | 15 tools, three prompts, two resource templates |
|
|
107
106
|
| [Requirements](#-requirements) | Python and dependencies |
|
|
108
107
|
| [The asset pack](#-the-asset-pack) | `--assets-root`, `BANTAMKIT_ASSETS` |
|
|
109
|
-
| [The operator CLI: `python -m bantamkit.memory`](#-the-operator-cli-python--m-bantamkitmemory) | status, lint, compact, archived, archive, restore
|
|
108
|
+
| [The operator CLI: `python -m bantamkit.memory`](#-the-operator-cli-python--m-bantamkitmemory) | status, lint, compact, archived, archive, restore |
|
|
110
109
|
| [Where the Python and Node servers differ](#-where-the-python-and-node-servers-differ) | One store; pdf/.doc/.rtf, CLI name, `build_id`, YAML only PyYAML reads |
|
|
111
110
|
| [Module API](#-module-api) | `import bantamkit`: the library half, measured from the wheel |
|
|
112
111
|
| [Development](#-development) | Clone, test, lint, conformance |
|
|
@@ -145,9 +144,9 @@ CPU architecture and Python minor version** (some wheels, such as `pydantic_core
|
|
|
145
144
|
one platform only), copy `wheels/` across, and install from it:
|
|
146
145
|
|
|
147
146
|
```bash
|
|
148
|
-
python -m pip download "bantamkit[mcp]==0.
|
|
147
|
+
python -m pip download "bantamkit[mcp]==0.37.0" -d wheels
|
|
149
148
|
python -m venv <env>
|
|
150
|
-
<env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.
|
|
149
|
+
<env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.37.0"
|
|
151
150
|
<env>/bin/bantamkit-mcp --install cursor
|
|
152
151
|
```
|
|
153
152
|
|
|
@@ -279,6 +278,7 @@ Flags go in the entry's `args`; environment variables in its `env` block (or
|
|
|
279
278
|
| `--k K` | Default recall budget | `3` | `"--k", "5"` |
|
|
280
279
|
| `--index-budget BYTES` | Memory index byte budget | `24000` | `"--index-budget", "32000"` |
|
|
281
280
|
| `BANTAMKIT_EVENT_LOG` | Logs tool outcomes as JSONL | off; `on` → `<store>/events/mcp.jsonl`; other values are a path | `"env": {"BANTAMKIT_EVENT_LOG": "on"}` |
|
|
281
|
+
| `BANTAMKIT_SKILL_AUTO` | Skills from experience (#206): lets the daily run install a skill it mined, make low-risk edits to installed skills and promote a much-used one to a native link on its own. Off, the same work waits for you as proposals in the `skill_propose` prompt | **off** in 0.37.0; `on` (or `1`/`true`/`yes`) opts in | `"env": {"BANTAMKIT_SKILL_AUTO": "on"}` |
|
|
282
282
|
| `BANTAMKIT_ASSETS` | Your own asset pack (skills, rubrics, schemas) | the pack inside the package | `"env": {"BANTAMKIT_ASSETS": "/abs/my-assets"}` |
|
|
283
283
|
| `BANTAMKIT_HOST_LOG_ROOT` | Where `--mcp-report` finds the host's MCP logs | macOS `~/Library/Caches/claude-cli-nodejs`; elsewhere unset | `BANTAMKIT_HOST_LOG_ROOT=/abs/logs bantamkit-mcp --mcp-report` |
|
|
284
284
|
| `BANTAMKIT_PRICES` | Price table for the token ledger | `pricing/default.json` in the asset pack | `"env": {"BANTAMKIT_PRICES": "/abs/prices.json"}` |
|
|
@@ -328,7 +328,7 @@ you**; a new version with an old `build_id` means an old process.
|
|
|
328
328
|
|
|
329
329
|
## 🧰 What it serves
|
|
330
330
|
|
|
331
|
-
It serves
|
|
331
|
+
It serves 15 tools, three prompts (`bantamkit_status`, `skill_audit` and `skill_propose`) and two resource templates
|
|
332
332
|
(`bantamkit://skills/{name}`, `bantamkit://rubrics/{name}`):
|
|
333
333
|
|
|
334
334
|
| Tool | What it does |
|
|
@@ -337,6 +337,7 @@ It serves 14 tools, the `bantamkit_status` prompt and two resource templates
|
|
|
337
337
|
| `memory_recall` | retrieve facts matching a query |
|
|
338
338
|
| `memory_compact` | archive the stalest facts to fit the index budget |
|
|
339
339
|
| `memory_dream` | consolidate facts the project and profile layers hold under the same name |
|
|
340
|
+
| `memory_queries` | list the facts that have no likely-prompt queries yet, and store the queries written for them; recall matches a prompt against them |
|
|
340
341
|
| `validate_json` | validate a document against a JSON Schema |
|
|
341
342
|
| `skill_audit` | audit a skill catalogue for findings |
|
|
342
343
|
| `shiftwork_clock_in` | open a unit of work and get its brief |
|
|
@@ -374,13 +375,9 @@ python -m bantamkit.memory compact # archive the stalest facts
|
|
|
374
375
|
python -m bantamkit.memory archived # list what compaction has moved out
|
|
375
376
|
python -m bantamkit.memory archive <name>
|
|
376
377
|
python -m bantamkit.memory restore <name>
|
|
377
|
-
python -m bantamkit.memory list [--type T] [--outcome error|success] [--status active|done]
|
|
378
|
-
python -m bantamkit.memory candidates [--older-than DAYS] [--apply]
|
|
379
|
-
python -m bantamkit.memory merge --names A B --name NEW --type T --description D --body TEXT [--apply]
|
|
380
378
|
```
|
|
381
379
|
|
|
382
|
-
`archive` moves a fact out without deleting it; `restore` brings it back by name.
|
|
383
|
-
and `merge` are dry runs unless `--apply` is given.
|
|
380
|
+
`archive` moves a fact out without deleting it; `restore` brings it back by name.
|
|
384
381
|
Full reference: [docs/memory.md → The operator CLI](https://github.com/Ink01101011/bantamkit/blob/main/docs/memory.md#the-operator-cli).
|
|
385
382
|
|
|
386
383
|
## 🔀 Where the Python and Node servers differ
|
|
@@ -438,7 +435,7 @@ as a side effect of the package's own imports (`agent`, `assets`, `budget`, `cli
|
|
|
438
435
|
| `bantamkit.memory` | the memory store | `Memory`, `MemoryStore` |
|
|
439
436
|
| **9 modules** | | **30 values, no `__all__`** |
|
|
440
437
|
|
|
441
|
-
**This is not the npm package's export surface.** Both runtimes serve the same
|
|
438
|
+
**This is not the npm package's export surface.** Both runtimes serve the same fifteen MCP
|
|
442
439
|
tools, but what each one exports *to an importer* is a different product: here it is the
|
|
443
440
|
agent/critique/eval library above; there it is the memory store, the asset pack, the event log,
|
|
444
441
|
the shift-work tools and a set of CPython-semantics shims — 141 values behind one entry point. Of
|
|
@@ -43,13 +43,12 @@ Then restart the host (in Claude Code, open a new session) and ask the agent to
|
|
|
43
43
|
- **Offline after one install.** `--install` records the venv's console script by absolute path,
|
|
44
44
|
so no launch needs the network or your shell's PATH.
|
|
45
45
|
- **Claude Code hooks, if you want them.** `--install-hooks` puts the memory index in front of
|
|
46
|
-
each new session, surfaces matching facts on each prompt,
|
|
47
|
-
|
|
48
|
-
the end of a long session that saved nothing
|
|
46
|
+
each new session, surfaces matching facts on each prompt, and nudges a save at the end of a
|
|
47
|
+
long session that saved nothing
|
|
49
48
|
([docs/hooks.md](https://github.com/Ink01101011/bantamkit/blob/main/docs/hooks.md)).
|
|
50
49
|
- **More than memory.** JSON Schema validation, a token ledger read off the host's transcripts,
|
|
51
50
|
a skill-catalogue audit, and shift-work tools that plan and hand off multi-step jobs —
|
|
52
|
-
[the
|
|
51
|
+
[the fifteen tools](#-what-it-serves).
|
|
53
52
|
- **Same answers as the Node server.** The two share a memory store on disk, and every surface
|
|
54
53
|
is compared between both runtimes by a conformance suite (`node tools/conformance/run.mjs
|
|
55
54
|
--all` in the repository), so install whichever your host makes easy.
|
|
@@ -72,10 +71,10 @@ Then restart the host (in Claude Code, open a new session) and ask the agent to
|
|
|
72
71
|
| [Configuration](#-configuration) | Every flag and variable, with its default |
|
|
73
72
|
| [Update](#-update) | `--update`, pipx, uv, then restart |
|
|
74
73
|
| [Troubleshooting](#-troubleshooting) | Timeouts, refusals, the wrong store |
|
|
75
|
-
| [What it serves](#-what-it-serves) |
|
|
74
|
+
| [What it serves](#-what-it-serves) | 15 tools, three prompts, two resource templates |
|
|
76
75
|
| [Requirements](#-requirements) | Python and dependencies |
|
|
77
76
|
| [The asset pack](#-the-asset-pack) | `--assets-root`, `BANTAMKIT_ASSETS` |
|
|
78
|
-
| [The operator CLI: `python -m bantamkit.memory`](#-the-operator-cli-python--m-bantamkitmemory) | status, lint, compact, archived, archive, restore
|
|
77
|
+
| [The operator CLI: `python -m bantamkit.memory`](#-the-operator-cli-python--m-bantamkitmemory) | status, lint, compact, archived, archive, restore |
|
|
79
78
|
| [Where the Python and Node servers differ](#-where-the-python-and-node-servers-differ) | One store; pdf/.doc/.rtf, CLI name, `build_id`, YAML only PyYAML reads |
|
|
80
79
|
| [Module API](#-module-api) | `import bantamkit`: the library half, measured from the wheel |
|
|
81
80
|
| [Development](#-development) | Clone, test, lint, conformance |
|
|
@@ -114,9 +113,9 @@ CPU architecture and Python minor version** (some wheels, such as `pydantic_core
|
|
|
114
113
|
one platform only), copy `wheels/` across, and install from it:
|
|
115
114
|
|
|
116
115
|
```bash
|
|
117
|
-
python -m pip download "bantamkit[mcp]==0.
|
|
116
|
+
python -m pip download "bantamkit[mcp]==0.37.0" -d wheels
|
|
118
117
|
python -m venv <env>
|
|
119
|
-
<env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.
|
|
118
|
+
<env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.37.0"
|
|
120
119
|
<env>/bin/bantamkit-mcp --install cursor
|
|
121
120
|
```
|
|
122
121
|
|
|
@@ -248,6 +247,7 @@ Flags go in the entry's `args`; environment variables in its `env` block (or
|
|
|
248
247
|
| `--k K` | Default recall budget | `3` | `"--k", "5"` |
|
|
249
248
|
| `--index-budget BYTES` | Memory index byte budget | `24000` | `"--index-budget", "32000"` |
|
|
250
249
|
| `BANTAMKIT_EVENT_LOG` | Logs tool outcomes as JSONL | off; `on` → `<store>/events/mcp.jsonl`; other values are a path | `"env": {"BANTAMKIT_EVENT_LOG": "on"}` |
|
|
250
|
+
| `BANTAMKIT_SKILL_AUTO` | Skills from experience (#206): lets the daily run install a skill it mined, make low-risk edits to installed skills and promote a much-used one to a native link on its own. Off, the same work waits for you as proposals in the `skill_propose` prompt | **off** in 0.37.0; `on` (or `1`/`true`/`yes`) opts in | `"env": {"BANTAMKIT_SKILL_AUTO": "on"}` |
|
|
251
251
|
| `BANTAMKIT_ASSETS` | Your own asset pack (skills, rubrics, schemas) | the pack inside the package | `"env": {"BANTAMKIT_ASSETS": "/abs/my-assets"}` |
|
|
252
252
|
| `BANTAMKIT_HOST_LOG_ROOT` | Where `--mcp-report` finds the host's MCP logs | macOS `~/Library/Caches/claude-cli-nodejs`; elsewhere unset | `BANTAMKIT_HOST_LOG_ROOT=/abs/logs bantamkit-mcp --mcp-report` |
|
|
253
253
|
| `BANTAMKIT_PRICES` | Price table for the token ledger | `pricing/default.json` in the asset pack | `"env": {"BANTAMKIT_PRICES": "/abs/prices.json"}` |
|
|
@@ -297,7 +297,7 @@ you**; a new version with an old `build_id` means an old process.
|
|
|
297
297
|
|
|
298
298
|
## 🧰 What it serves
|
|
299
299
|
|
|
300
|
-
It serves
|
|
300
|
+
It serves 15 tools, three prompts (`bantamkit_status`, `skill_audit` and `skill_propose`) and two resource templates
|
|
301
301
|
(`bantamkit://skills/{name}`, `bantamkit://rubrics/{name}`):
|
|
302
302
|
|
|
303
303
|
| Tool | What it does |
|
|
@@ -306,6 +306,7 @@ It serves 14 tools, the `bantamkit_status` prompt and two resource templates
|
|
|
306
306
|
| `memory_recall` | retrieve facts matching a query |
|
|
307
307
|
| `memory_compact` | archive the stalest facts to fit the index budget |
|
|
308
308
|
| `memory_dream` | consolidate facts the project and profile layers hold under the same name |
|
|
309
|
+
| `memory_queries` | list the facts that have no likely-prompt queries yet, and store the queries written for them; recall matches a prompt against them |
|
|
309
310
|
| `validate_json` | validate a document against a JSON Schema |
|
|
310
311
|
| `skill_audit` | audit a skill catalogue for findings |
|
|
311
312
|
| `shiftwork_clock_in` | open a unit of work and get its brief |
|
|
@@ -343,13 +344,9 @@ python -m bantamkit.memory compact # archive the stalest facts
|
|
|
343
344
|
python -m bantamkit.memory archived # list what compaction has moved out
|
|
344
345
|
python -m bantamkit.memory archive <name>
|
|
345
346
|
python -m bantamkit.memory restore <name>
|
|
346
|
-
python -m bantamkit.memory list [--type T] [--outcome error|success] [--status active|done]
|
|
347
|
-
python -m bantamkit.memory candidates [--older-than DAYS] [--apply]
|
|
348
|
-
python -m bantamkit.memory merge --names A B --name NEW --type T --description D --body TEXT [--apply]
|
|
349
347
|
```
|
|
350
348
|
|
|
351
|
-
`archive` moves a fact out without deleting it; `restore` brings it back by name.
|
|
352
|
-
and `merge` are dry runs unless `--apply` is given.
|
|
349
|
+
`archive` moves a fact out without deleting it; `restore` brings it back by name.
|
|
353
350
|
Full reference: [docs/memory.md → The operator CLI](https://github.com/Ink01101011/bantamkit/blob/main/docs/memory.md#the-operator-cli).
|
|
354
351
|
|
|
355
352
|
## 🔀 Where the Python and Node servers differ
|
|
@@ -407,7 +404,7 @@ as a side effect of the package's own imports (`agent`, `assets`, `budget`, `cli
|
|
|
407
404
|
| `bantamkit.memory` | the memory store | `Memory`, `MemoryStore` |
|
|
408
405
|
| **9 modules** | | **30 values, no `__all__`** |
|
|
409
406
|
|
|
410
|
-
**This is not the npm package's export surface.** Both runtimes serve the same
|
|
407
|
+
**This is not the npm package's export surface.** Both runtimes serve the same fifteen MCP
|
|
411
408
|
tools, but what each one exports *to an importer* is a different product: here it is the
|
|
412
409
|
agent/critique/eval library above; there it is the memory store, the asset pack, the event log,
|
|
413
410
|
the shift-work tools and a set of CPython-semantics shims — 141 values behind one entry point. Of
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Likely-prompt queries
|
|
2
|
+
|
|
3
|
+
For each fact, write the prompts a user would type to a coding assistant when this fact is what they need.
|
|
4
|
+
|
|
5
|
+
- Three in the user's own language and three in English (`queries` holds all six, the user's language first).
|
|
6
|
+
- Short: 5 to 25 words. Vary them: one direct question, one task request, one terse follow-up.
|
|
7
|
+
- Keep technical terms in English where the user would: commands, file names, product names, error codes.
|
|
8
|
+
- Use only what the fact says. Do not invent facts, do not just restate the fact's name, and never copy more than
|
|
9
|
+
five words of the body verbatim.
|
|
10
|
+
|
|
11
|
+
Store them with `memory_queries` (`{"facts": [{"name": ..., "layer": ..., "queries": [...]}]}`), or pass
|
|
12
|
+
`queries` to `memory_save` when you save the fact.
|
|
@@ -23,6 +23,13 @@ past-you would have used. Do this before acting, not after.
|
|
|
23
23
|
|
|
24
24
|
Write it to match the future recall QUERY, not to summarize the body.
|
|
25
25
|
Ask: "what words will future-me search with?" Put related memory names in links.
|
|
26
|
+
Fill keywords with the words the user will actually type, in their language — recall matches those too.
|
|
27
|
+
|
|
28
|
+
## Likely-prompt queries
|
|
29
|
+
|
|
30
|
+
When you save, also pass `queries`: three prompts in the user's language and three in English that a user would
|
|
31
|
+
type when this fact is what they need. Short and varied, technical terms kept in English, never more than five
|
|
32
|
+
words copied from the body. When `memory_queries` lists facts without queries, write theirs.
|
|
26
33
|
|
|
27
34
|
## On "duplicate" replies
|
|
28
35
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memory_compact",
|
|
3
3
|
"title": "Compact the memory store",
|
|
4
|
-
"description": "Free room in persistent memory when `memory_save` was refused for budget. Archives the stalest facts of the writable project store until a fact as large as the biggest one kept will fit, and returns what moved — every archived name with its type and description. Nothing is deleted: archived facts leave the index but stay on disk under archive/, and bringing one back is an operator action rather than a tool — `bantamkit-memory restore <name>` (Node) or `python -m bantamkit.memory restore <name>` (Python) on the store; no tool deletes a fact. Read-only grants and the profile layer are never touched. Call it after a budget refusal, then retry the save; calling it under budget archives nothing and says so. It is not the pass for two copies of one name across layers — that is memory_dream.",
|
|
4
|
+
"description": "Free room in persistent memory when `memory_save` was refused for budget. Archives the stalest facts of the writable project store until a fact as large as the biggest one kept will fit, and returns what moved — every archived name with its type and description. Nothing is deleted: archived facts leave the index but stay on disk under archive/, memory_recall with `include_archived` still finds them, and bringing one back is an operator action rather than a tool — `bantamkit-memory restore <name>` (Node) or `python -m bantamkit.memory restore <name>` (Python) on the store; no tool deletes a fact. Read-only grants and the profile layer are never touched. Call it after a budget refusal, then retry the save; calling it under budget archives nothing and says so. It is not the pass for two copies of one name across layers — that is memory_dream.",
|
|
5
5
|
"surfaces": [
|
|
6
6
|
"agent",
|
|
7
7
|
"mcp"
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "memory_queries",
|
|
3
|
+
"title": "Likely-prompt queries for saved facts",
|
|
4
|
+
"description": "Write, or list the facts that still lack, the likely-prompt queries recall matches a user's prompt against — for each fact, the prompts a user would type when that fact is what they need. Call it with {} at the end of a session that saved facts, or when bantamkit_status reports `queries: n of m facts` with n below m: it answers up to 10 facts with no queries yet (layer, name, description, a body excerpt), the writing instructions, and `remaining`. Then call it with {\"facts\": [{name, layer?, queries}]} to store what you wrote. Every item is checked before anything is written and the first bad one refuses the whole call — an unknown name or layer, more than 8 queries, one over 200 characters; `queries: []` removes a fact's entry. No fact file changes: queries live in a per-layer sidecar under ~/.bantamkit/queries/, keyed to the fact's content, so a fact edited later is listed as missing again. memory_save takes `queries` directly for a fact you are saving now; this tool is for facts already on disk.",
|
|
5
|
+
"surfaces": [
|
|
6
|
+
"mcp"
|
|
7
|
+
],
|
|
8
|
+
"parameters": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"properties": {
|
|
11
|
+
"facts": {
|
|
12
|
+
"anyOf": [
|
|
13
|
+
{
|
|
14
|
+
"type": "array",
|
|
15
|
+
"items": {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"properties": {
|
|
18
|
+
"name": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"description": "The fact's exact name (its slug)."
|
|
21
|
+
},
|
|
22
|
+
"layer": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "project, profile, extra:<name> or native; optional: the first layer holding the name"
|
|
25
|
+
},
|
|
26
|
+
"queries": {
|
|
27
|
+
"type": "array",
|
|
28
|
+
"items": {
|
|
29
|
+
"type": "string"
|
|
30
|
+
},
|
|
31
|
+
"description": "Up to 8 prompts, each at most 200 characters, in the user's language and in English; [] removes the fact's entry."
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"required": [
|
|
35
|
+
"name",
|
|
36
|
+
"queries"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"type": "null"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"description": "Omit to list the facts missing queries"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"title": "memory_queriesArguments",
|
|
48
|
+
"additionalProperties": false
|
|
49
|
+
},
|
|
50
|
+
"output_schema": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"properties": {
|
|
53
|
+
"result": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"description": "`missing` for the list call, `written` for the store call, `error` with `reason` when refused."
|
|
56
|
+
},
|
|
57
|
+
"facts": {
|
|
58
|
+
"type": "array",
|
|
59
|
+
"items": {
|
|
60
|
+
"type": "object"
|
|
61
|
+
},
|
|
62
|
+
"description": "With `missing`: up to 10 {layer, name, description, body} still without queries."
|
|
63
|
+
},
|
|
64
|
+
"remaining": {
|
|
65
|
+
"type": "integer",
|
|
66
|
+
"description": "How many facts across the readable layers still have no queries after this call."
|
|
67
|
+
},
|
|
68
|
+
"instructions": {
|
|
69
|
+
"type": "string",
|
|
70
|
+
"description": "With `missing`: how to write good queries."
|
|
71
|
+
},
|
|
72
|
+
"written": {
|
|
73
|
+
"type": "integer",
|
|
74
|
+
"description": "With `written`: how many items were stored."
|
|
75
|
+
},
|
|
76
|
+
"reason": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"description": "With result `error`: one sentence saying why the call was refused."
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"required": [
|
|
82
|
+
"result"
|
|
83
|
+
],
|
|
84
|
+
"additionalProperties": true,
|
|
85
|
+
"title": "memory_queriesDictOutput"
|
|
86
|
+
},
|
|
87
|
+
"annotations": {
|
|
88
|
+
"readOnlyHint": false,
|
|
89
|
+
"destructiveHint": false,
|
|
90
|
+
"openWorldHint": false
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memory_recall",
|
|
3
3
|
"title": "Recall memories",
|
|
4
|
-
"description": "Search persistent memory for facts a past session saved. Call it BEFORE starting a task that resembles past work, and when the user refers to something decided earlier; use memory_save to add a fact, and memory_compact or memory_dream only to tidy the store — this tool never changes what a fact says. Reads every layer in order — the project store, any read-only grants in .bantamkit/config.yaml, then the machine-wide profile — and returns the top word matches, never fewer than the store default of 3 when that many match; a query that is exactly a fact's name returns that fact alone. Why it is not read-only: every hit is appended to the usage ledger (~/.bantamkit/usage/<store-id>.jsonl) as a recall event — the staleness order memory_compact archives by — and a project fact file still in the 0.35.x format is rewritten once into the current one; both are best-effort and never fail a recall. A fact file that cannot be read is named in the reply, never silently skipped. Pass outcome: error to see only recorded failures.",
|
|
4
|
+
"description": "Search persistent memory for facts a past session saved. Call it BEFORE starting a task that resembles past work, and when the user refers to something decided earlier; use memory_save to add a fact, and memory_compact or memory_dream only to tidy the store — this tool never changes what a fact says. Reads every layer in order — the project store, any read-only grants in .bantamkit/config.yaml, then the machine-wide profile — and returns the top word matches, never fewer than the store default of 3 when that many match; a query that is exactly a fact's name returns that fact alone. Pass `file` instead of `query` to see the facts linked to a file. Why it is not read-only: every hit is appended to the usage ledger (~/.bantamkit/usage/<store-id>.jsonl) as a recall event — the staleness order memory_compact archives by — and a project fact file still in the 0.35.x format is rewritten once into the current one; both are best-effort and never fail a recall. A fact file that cannot be read is named in the reply, never silently skipped. Pass outcome: error to see only recorded failures.",
|
|
5
5
|
"surfaces": [
|
|
6
6
|
"agent",
|
|
7
7
|
"mcp"
|
|
8
8
|
],
|
|
9
9
|
"parameters": {
|
|
10
10
|
"type": "object",
|
|
11
|
-
"required": [
|
|
12
|
-
"query"
|
|
13
|
-
],
|
|
11
|
+
"required": [],
|
|
14
12
|
"properties": {
|
|
15
13
|
"query": {
|
|
16
14
|
"type": "string",
|
|
@@ -20,6 +18,15 @@
|
|
|
20
18
|
"type": "integer",
|
|
21
19
|
"description": "Facts wanted, clamped to 1..5. Raised to the store default of 3 when smaller; never lowered below it."
|
|
22
20
|
},
|
|
21
|
+
"include_archived": {
|
|
22
|
+
"type": "boolean",
|
|
23
|
+
"default": false,
|
|
24
|
+
"description": "Also search facts compaction moved to archive/. Archived matches come after the live ones, tagged [archived]."
|
|
25
|
+
},
|
|
26
|
+
"file": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "A tracked file, or the shortest unique suffix of one (store.ts, memory/store.ts). Returns the facts linked to it and when it was last touched; query is then ignored."
|
|
29
|
+
},
|
|
23
30
|
"outcome": {
|
|
24
31
|
"type": "string",
|
|
25
32
|
"enum": [
|
|
@@ -45,6 +45,20 @@
|
|
|
45
45
|
},
|
|
46
46
|
"description": "names of related memories"
|
|
47
47
|
},
|
|
48
|
+
"keywords": {
|
|
49
|
+
"type": "array",
|
|
50
|
+
"items": {
|
|
51
|
+
"type": "string"
|
|
52
|
+
},
|
|
53
|
+
"description": "Words the user will type when they need this fact, in the user's own language as well as English (e.g. Thai and English terms)"
|
|
54
|
+
},
|
|
55
|
+
"queries": {
|
|
56
|
+
"type": "array",
|
|
57
|
+
"items": {
|
|
58
|
+
"type": "string"
|
|
59
|
+
},
|
|
60
|
+
"description": "The prompts a user would type when this fact is what they need: three in the user's language and three in English, at most 8, each at most 200 characters"
|
|
61
|
+
},
|
|
48
62
|
"outcome": {
|
|
49
63
|
"type": "string",
|
|
50
64
|
"enum": [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shiftwork_status",
|
|
3
3
|
"title": "Shift work: status",
|
|
4
|
-
"description": "Shift-work status: where ONE checkpoint file stands — units counted by status, the unit plan.cursor points at, how many handoff.open_questions are waiting, and the last history entry. Call it first when resuming a job or answering 'where is job X'; it is the cheap read before any clock-in. It does not say WHICH units may run now — that is shiftwork_plan, the dependency batches — and it says nothing about the server itself, which is bantamkit_status. Every fact is read from the checkpoint on this call, nothing is cached, and a checkpoint that is missing, not valid JSON or failing the checkpoint schema answers {\"result\": \"error\", \"reason\": \"<sentence>\"} instead of a partial summary — the same refusals shiftwork_plan and shiftwork_clock_in give for that file. Opens only the checkpoint; writes nothing, not even the log shiftwork_clock_in appends to.",
|
|
4
|
+
"description": "Shift-work status: where ONE checkpoint file stands — units counted by status, the unit plan.cursor points at, how many handoff.open_questions are waiting, and the last history entry. Call it first when resuming a job or answering 'where is job X'; it is the cheap read before any clock-in. It does not say WHICH units may run now — that is shiftwork_plan, the dependency batches — and it says nothing about the server itself, which is bantamkit_status. Every fact is read from the checkpoint on this call, nothing is cached, and a checkpoint that is missing, not valid JSON or failing the checkpoint schema answers {\"result\": \"error\", \"reason\": \"<sentence>\"} instead of a partial summary — the same refusals shiftwork_plan and shiftwork_clock_in give for that file. With `search`, it also returns the lines of jobs Retention archived under the checkpoint's .shiftwork/archive/ that hold every word of the query. Opens only the checkpoint (and that archive directory when `search` is given); writes nothing, not even the log shiftwork_clock_in appends to.",
|
|
5
5
|
"surfaces": [
|
|
6
6
|
"mcp"
|
|
7
7
|
],
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
"title": "Checkpoint",
|
|
12
12
|
"type": "string",
|
|
13
13
|
"description": "Path to the shift-work checkpoint JSON file (by convention .shiftwork/checkpoint.json in the repo the job works on), absolute or relative to the server's working directory. The same file shiftwork_plan, shiftwork_clock_in and shiftwork_clock_out take; it must validate against assets/schemas/shiftwork-checkpoint.json."
|
|
14
|
+
},
|
|
15
|
+
"search": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Also search jobs Retention archived under this checkpoint's .shiftwork/archive/: every line holding all the query's words, as {job, file, line}."
|
|
14
18
|
}
|
|
15
19
|
},
|
|
16
20
|
"required": [
|
|
@@ -53,6 +57,27 @@
|
|
|
53
57
|
],
|
|
54
58
|
"description": "The newest entry of the 5-entry history ring ({unit, outcome, notes?, ...}), or null when the ring is empty."
|
|
55
59
|
},
|
|
60
|
+
"search": {
|
|
61
|
+
"type": "array",
|
|
62
|
+
"items": {
|
|
63
|
+
"type": "object",
|
|
64
|
+
"properties": {
|
|
65
|
+
"job": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"description": "The archived job the line belongs to."
|
|
68
|
+
},
|
|
69
|
+
"file": {
|
|
70
|
+
"type": "string",
|
|
71
|
+
"description": "Path of the archived file, relative to the job."
|
|
72
|
+
},
|
|
73
|
+
"line": {
|
|
74
|
+
"type": "integer",
|
|
75
|
+
"description": "1-based line number within that file."
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"description": "Only when `search` was given: every archived line holding all its words, as {job, file, line}."
|
|
80
|
+
},
|
|
56
81
|
"reason": {
|
|
57
82
|
"type": "string",
|
|
58
83
|
"description": "With result `error`: one sentence saying why the call was refused."
|
|
@@ -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.37.0"
|
|
@@ -30,12 +30,13 @@ 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. Nine of the
|
|
33
|
+
validated output, never a query, never a document row. Nine of the fifteen tools take
|
|
34
34
|
an unbounded string (counted over `assets/tools/`: a `string` parameter with no `enum`
|
|
35
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 `work_plan`
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
job50 I5 retired them from the roster — and `work_plan` and `memory_queries` are NOT
|
|
37
|
+
among them: `nodes` and `facts` are arrays of objects, not arrays of strings, so the
|
|
38
|
+
rule does not reach the strings inside them; `memory_queries` records its `result`
|
|
39
|
+
token only) and among those `skill_audit`'s `root`,
|
|
39
40
|
`token_ledger`'s `root` and `prices` and the four shift-work tools' `checkpoint` are
|
|
40
41
|
absolute paths; each record carries counts and tokens from a closed set, never the
|
|
41
42
|
path, never a part name, never a skill id, never a mapped file, never a session id,
|
|
@@ -72,6 +73,7 @@ from pathlib import Path
|
|
|
72
73
|
from typing import Any
|
|
73
74
|
|
|
74
75
|
from bantamkit.memory.store import bantamkit_dir_for, ensure_bantamkit_gitignore
|
|
76
|
+
from bantamkit.storage.logsegment import LogSegment
|
|
75
77
|
|
|
76
78
|
#: Environment switch. Unset or `off`/`0`/`false`/`no`/empty -> disabled. `on`/`1`/
|
|
77
79
|
#: `true`/`yes` -> the default file inside the memory store. Anything else is taken as
|
|
@@ -135,15 +137,23 @@ def encode_record(epoch_ms: int, tool: str, outcome: str, detail: dict[str, Any]
|
|
|
135
137
|
module is non-ASCII today; the setting is what keeps that a fact about the data
|
|
136
138
|
rather than a difference between the runtimes if it ever stops being one.
|
|
137
139
|
"""
|
|
138
|
-
|
|
140
|
+
text = json.dumps(
|
|
141
|
+
_record_object(epoch_ms, tool, outcome, detail), ensure_ascii=False, separators=(",", ":")
|
|
142
|
+
)
|
|
143
|
+
return text.encode("utf-8") + b"\n"
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _record_object(
|
|
147
|
+
epoch_ms: int, tool: str, outcome: str, detail: dict[str, Any]
|
|
148
|
+
) -> dict[str, Any]:
|
|
149
|
+
"""The record `encode_record` spells, as the object `LogSegment.append` writes."""
|
|
150
|
+
return {
|
|
139
151
|
"v": SCHEMA_VERSION,
|
|
140
152
|
"ts": format_timestamp(epoch_ms),
|
|
141
153
|
"tool": tool,
|
|
142
154
|
"outcome": outcome,
|
|
143
155
|
"detail": {key: detail[key] for key in sorted(detail)},
|
|
144
156
|
}
|
|
145
|
-
text = json.dumps(record, ensure_ascii=False, separators=(",", ":"))
|
|
146
|
-
return text.encode("utf-8") + b"\n"
|
|
147
157
|
|
|
148
158
|
|
|
149
159
|
def default_path(store_root: Path) -> Path:
|
|
@@ -266,9 +276,10 @@ class EventLog:
|
|
|
266
276
|
"""
|
|
267
277
|
if self.path is None:
|
|
268
278
|
return
|
|
269
|
-
|
|
279
|
+
obj = _record_object(self._clock(), tool, outcome, detail or {})
|
|
280
|
+
payload = json.dumps(obj, ensure_ascii=False, separators=(",", ":")).encode("utf-8") + b"\n"
|
|
270
281
|
try:
|
|
271
|
-
self._append(payload)
|
|
282
|
+
self._append(obj, payload)
|
|
272
283
|
except OSError:
|
|
273
284
|
self.write_failed = True
|
|
274
285
|
return
|
|
@@ -282,8 +293,15 @@ class EventLog:
|
|
|
282
293
|
"""
|
|
283
294
|
self.record(tool, "raised", {"type": type(exc).__name__})
|
|
284
295
|
|
|
285
|
-
def _append(self, payload: bytes) -> None:
|
|
286
|
-
"""Rotate if this record would cross the cap, then append
|
|
296
|
+
def _append(self, obj: dict[str, Any], payload: bytes) -> None:
|
|
297
|
+
"""Rotate if this record would cross the cap, then append through `LogSegment`.
|
|
298
|
+
|
|
299
|
+
#204 (J69-4): the line goes through `storage.LogSegment.append` (the shared O_EXCL
|
|
300
|
+
lock, a newline before a cut last line, the same bytes `encode_record` spells). THE
|
|
301
|
+
ROTATION RULE BELOW IS NOT `LogSegment.rotate`'s, on purpose: this log keeps exactly
|
|
302
|
+
one plain `<path>.1` that `--statusline` and `--mcp-report` read in both runtimes, and
|
|
303
|
+
a 2 MiB ceiling with no retention job behind it; docs/eventlog.md says one rotation
|
|
304
|
+
rule cannot be right for both this log and the hook log.
|
|
287
305
|
|
|
288
306
|
Binary, not text: a text-mode write translates `\\n` to `os.linesep`, which is
|
|
289
307
|
`\\r\\n` on Windows, and a Node reader byte-comparing the file would see a
|
|
@@ -332,5 +350,5 @@ class EventLog:
|
|
|
332
350
|
size = 0
|
|
333
351
|
if size and size + len(payload) > self.cap_bytes:
|
|
334
352
|
os.replace(self.path, self.path.with_name(self.path.name + ".1"))
|
|
335
|
-
|
|
336
|
-
|
|
353
|
+
if not LogSegment(self.path).append(obj):
|
|
354
|
+
raise OSError("the record could not be appended") # caught by `record`
|