apsimo 1.3.0__tar.gz → 1.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {apsimo-1.3.0 → apsimo-1.3.1}/PKG-INFO +2 -2
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/authority.py +2 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/host.py +53 -4
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/cli.py +1 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/setup.py +2 -2
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/setup_hermes.py +41 -3
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo.egg-info/PKG-INFO +2 -2
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo.egg-info/SOURCES.txt +2 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo.egg-info/requires.txt +1 -1
- {apsimo-1.3.0 → apsimo-1.3.1}/pyproject.toml +2 -2
- apsimo-1.3.1/tests/test_enrolled_sender_turns.py +94 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_native_setup.py +93 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_scoped_api_authority.py +11 -9
- apsimo-1.3.1/tests/test_scoped_contact_resolution.py +48 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/LICENSE +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/README.md +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/__main__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/agent/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/agent/client.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/agent/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/agents/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/agents/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/agents/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/agents/websocket.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/auth_telemetry.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/contact_grants.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/middleware.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/commitment_work.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/context_gate.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/executions.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/followup_plans.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/governed_actions.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/initiative_work.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/mining.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/observations.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/social_state.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/task_queue.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/temporal_followups.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/transport.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/routers/transport_ingress_api.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/schemas/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/api/schemas/host.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/autonomy/cli.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/autonomy/condition_worker.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/autonomy/config.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/autonomy/loop.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/autonomy/registry.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/autonomy/scheduler.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/autonomy/synthesis.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/backup.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/beliefs/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/beliefs/contradictions.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/beliefs/decay.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/beliefs/engine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/beliefs/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/beliefs/promotion.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/beliefs/resolve.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/beliefs/source_claims.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/beliefs/source_projection.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/beliefs/source_time.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/beliefs/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/briefings/aggregators.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/briefings/composer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/briefings/config.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/briefings/delivery.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/briefings/engagement.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/briefings/engine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/briefings/enhancer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/briefings/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/briefings/scheduler.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/briefings/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/block.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/cli.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/genesis.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/identity.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/keys.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/local_keys.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/manager.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/node.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/plugin_transactions.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/protocol.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/state_machine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/storage.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/transactions.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/chain/validation.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/channels/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/channels/manifest.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/channels/migrations/001_channels_schema.sql +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/channels/phone_gateways.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/channels/presence.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/channels/router.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/channels/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/cognition/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/cognition/charter.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/cognition/drive_governance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/cognition/evidence_pipeline.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/cognition/external_events.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/cognition/goal_spine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/cognition/introspection.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/cognition/prompt.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/cognition/runtime.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/cognition/trigger.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/commitments/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/commitments/local_work.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/commitments/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/commitments/work.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/compat.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/compression/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/connectors/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/connectors/base.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/connectors/caldav_calendar.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/connectors/fs_documents.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/connectors/imap_email.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/connectors/manager.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/connectors/webhook_pull.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/comms.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/config.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/exporters/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/exporters/vcard.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/identity_links.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/importer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/importers/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/importers/batch.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/importers/macos_contacts.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/migrations/001_contacts_schema.sql +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/migrations/002_trust_scopes.sql +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/migrations/003_open_gateway_enum.sql +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/migrations/004_contact_provision_operations.sql +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/migrations/005_identity_links.sql +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/scoring.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/transport_ingress.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contacts/world_bridge.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contextgate/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contextgate/chunker.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contextgate/estimate.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contextgate/gate.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/contextgate/retrieve.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/delivery/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/delivery/bridge.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/delivery/channels.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/delivery/classification.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/delivery/rate_limiter.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/delivery/reachout_policy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/directed/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/directed/audit.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/directed/intake.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/directed/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/directed/service.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/directives/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/directives/evidence.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/directives/extractor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/directives/guard.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/directives/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/directives/service.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/directives/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/doctor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/environment.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/events/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/events/broadcaster.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/events/bus.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/events/journal.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/events/stream.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/events/types.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/execution_results.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/feedback/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/feedback/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/feeds/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/feeds/cli.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/feeds/engine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/feeds/example-feed.yaml +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/feeds/hermes_cron.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/feeds/manager.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/feeds/spec.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/feeds/template.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/audit.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/communication_policy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/config.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/context_provenance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/env_risk.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/guard_audit.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/layers/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/layers/base.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/layers/l1_recipient.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/layers/l2_pii.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/layers/l3_cross_context.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/layers/l4_trust_tier.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/layers/l5_injection.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/layers/l6_review.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/layers/l7_delay.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/layers/tom2_epistemic.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/pending_dispatch.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/pipeline.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/rejection.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/response_guard.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/rulesets/injection_v1.yaml +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/surface_policy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/gate/taint.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/genesis.json +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/goals/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/goals/config.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/goals/decomposer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/goals/engine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/goals/inference.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/goals/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/goals/priority.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/goals/queue_bridge.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/goals/replan.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/goals/schema.sql +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/goals/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/governed_actions.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/harness_integration/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/harness_integration/context.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/harness_integration/skills.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity/participants.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity/resolver.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/builder.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/corpus.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/runner.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/seeders/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/seeders/briefings.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/seeders/chain.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/seeders/goals.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/seeders/memory.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/seeders/neo4j_cognition.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/seeders/relationship.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/seeders/sessions.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/seeders/skills.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/seeders/task_queue.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/seeders/world_model.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/self_query.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/self_reflection.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/skill.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/identity_bootstrap/verifier.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/initiatives/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/initiatives/action_registry.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/initiatives/approval_authority.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/initiatives/approval_policy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/initiatives/assignment.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/initiatives/backup_evidence.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/initiatives/context_freshness.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/initiatives/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/initiatives/native_work.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/initiatives/standing_approvals.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/initiatives/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/initiatives/temporal_followup.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/cognition/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/cognition/gap_detector.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/cognition/metalearner.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/cognition/metrics_collector.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/cognition/performance_index.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/cognition/registry.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/cognition/strategy_adjuster.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/cognition/types.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/components/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/components/anomaly_detector.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/components/initiative_engine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/components/preference_learner.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/components/research_orchestrator.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/components/self_directed_thinker.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/components/self_reflector.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/components/session_continuity.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/components/task_planner.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/components/tool_learner.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/graph/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/graph/client.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/graph/consolidator.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/graph/distiller.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/graph/migrations.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/graph/queries.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/graph/recall.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/graph/reconciler.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/graph/schema.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/graph/selection.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/learning/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/learning/continuous_learner.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/learning/feedback_store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/mind_model/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/mind_model/graph_baseline.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/mind_model/signal_collector.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/relationships/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/relationships/profiler.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/relationships/scorer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/relationships/signal_floor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/relationships/trust_tiers.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/synthesis/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/synthesis/connection_discoverer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/synthesis/cross_domain_analyzer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/synthesis/insight_deliverer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/synthesis/insight_store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/synthesis/insight_validator.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/synthesis/novelty_scorer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/turn_middleware/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/intelligence/turn_middleware/memory_sync.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/mcp/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/mcp/__main__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/mcp/config.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/mcp/server.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/migrations.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/mining/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/mining/corpus.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/mining/escalations.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/mining/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/mining/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/models/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/models/memory.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/models/mesh.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/models/person.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/models/signal.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/observations/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/observations/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/patterns/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/patterns/extract.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/patterns/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/persona/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/persona/engine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/persona/manifest.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/projects/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/projects/engine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/projects/event_outbox.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/projects/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/projects/planner.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/projects/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/proposals/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/proposals/engine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/proposals/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/qualification/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/qualification/cases.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/qualification/cli.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/qualification/memory_cases.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/qualification/records.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/qualification/report.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/qualification/runner.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/qualification/structured_cases.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/reasoning/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/reasoning/executor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/reasoning/loop.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/reasoning/native_tools/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/reasoning/native_tools/calculate.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/reasoning/native_tools/file_ops.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/reasoning/native_tools/web_search.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/reasoning/tool_policy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/redact/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/repos/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/repos/mirrors.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/research/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/research/artifact.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/research/gatherer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/research/pipeline.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/research/search/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/research/search/base.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/research/search/brave.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/research/search/cache.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/research/search/duckduckgo.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/research/search/orchestrator.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/research/search/serpapi.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/research/search/tavily.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/research/synthesizer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/router/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/router/complexity_scorer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/router/endpoints.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/router/fallback.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/router/functions.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/router/native_policy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/router/router.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/router/self_learning.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/router/tiers.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/sandbox/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/sandbox/backend.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/sandbox/manager.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/scope_bounds.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/secrets/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/secrets/backends/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/secrets/backends/base.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/secrets/backends/env.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/secrets/backends/keyring.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/secrets/backends/onepassword.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/secrets/cli.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/secrets/manager.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/secrets/migration.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/secrets/types.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/seed.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/appraisals.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/benchmark.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/brief.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/event_concerns.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/execution_forecasts.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/expectations.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/experiments.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/journal.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/judgments.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/native_outcomes.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/params.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/perspective.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/reconcile.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/reply_forecasts.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/runtime_forecasts.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/runtime_models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/settlement.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/situation.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/supervised.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/thinker.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/trust.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/self_model/workspace.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/server.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/services/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/services/agent_bridge.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/services/initiative_executor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/services/instance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/sessions/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/sessions/config.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/sessions/context_loader.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/sessions/federation_session.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/sessions/isolated_session.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/sessions/reports.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/sessions/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/setup_local_work.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/setup_native_goals.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/setup_native_reviews.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/base.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/budget.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/executor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/executors/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/executors/behavioral_correction.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/executors/capability_gap.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/executors/data_quality.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/executors/knowledge_acquisition.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/executors/operational_hygiene.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/executors/subsystem_health.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/hermes_export.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/index.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/learning/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/learning/novelty_detector.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/learning/pattern_extractor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/learning/triggers.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/loader.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/migrations/002_progressive_loading.sql +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/migrations/backfill_triggers.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/packager.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/protocols.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/registry.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/runtime.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/sandbox_runner.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/scheduler.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/schema.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/security/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/security/guards.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills/security/scanner.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills_memory/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills_memory/distill.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills_memory/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills_memory/retrieve.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/skills_memory/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/surprise/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/surprise/accumulation.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/surprise/scorer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/surprise/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/action_receipts.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/approval_relay_canary.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/config.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/contract.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/events.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/governor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/handlers/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/handlers/base.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/handlers/inference.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/handlers/monitoring.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/handlers/registry.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/handlers/subtask_handler.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/handlers/system_maintenance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/mesh_integration.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/models.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/queue_manager.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/routing.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/scheduler.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/schema.sql +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/work_control.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/task_queue/worker.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/telemetry.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/affect.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/approvals.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/arcs.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/asymmetry.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/eligibility.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/engagement.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/exposure.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/extractor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/fact_adapters.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/facts.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/integration.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/leveled.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/levels.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/recipient_audit.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/recipient_simulator.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/source_lineage.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/tom2.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/visibility.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tom/visibility_store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tools/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tools/definitions.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/tools/handlers.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/toolsmith/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/toolsmith/authority.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/toolsmith/engine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/toolsmith/integrity.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/toolsmith/miner.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/toolsmith/policy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/toolsmith/registry.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/audio.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/documents.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/executions.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/hermes_history.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/hermes_kanban.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/hermes_work.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/idempotency.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/local_work.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/media.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/reported_workers.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/source_annotations.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/source_attribution.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/source_read.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/source_vectors.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/turns/video.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/util/autonomy_preset.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/util/instance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/util/model_output.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/util/quiet_hours.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/util/session_safety.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/util/temporal.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/backfill.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/caption.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/collections.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/config.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/embedder.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/image_preprocess.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/image_store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/indexes.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/migrate.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/multimodal_provider.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/multimodal_types.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/openai_provider.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/query.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/reranker.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/safety_image.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/scanner.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/setup.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/vector/tiers.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/work_orders.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/workers/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/workers/agent_bridge.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/workers/colony_worker.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/workers/queue_worker.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/workers/skills_sync.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/causal_maintenance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/causal_policy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/causal_query.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/confidence.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/config.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/constants.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/entities.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/expectation_resolvers.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/extraction/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/extraction/base.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/extraction/conversation_extractor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/extraction/detector.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/extraction/document_extractor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/extraction/formats/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/extraction/formats/csv_fmt.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/extraction/formats/html_fmt.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/extraction/formats/json_fmt.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/extraction/formats/pdf.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/extraction/formats/text.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/extraction/llm_extractor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/extraction/pipeline.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/integrations/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/integrations/mind_model_bridge.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/integrations/social_intel_bridge.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/jobs/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/jobs/extraction_job.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/llm_extract.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/neo4j/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/neo4j/backend.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/observations.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/populator.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/postgres/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/postgres/backend.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/relationships.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/resolution/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/resolution/entity_resolver.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/resolution/merge_audit.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/resolution/merge_workflow.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/source_reports.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/sqlite/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/sqlite/backend.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/sqlite/schema.sql +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo/world_model/store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo.egg-info/dependency_links.txt +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo.egg-info/entry_points.txt +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/apsimo.egg-info/top_level.txt +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/colony_sidecar/__init__.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/setup.cfg +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_accepted_local_work.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_adaptive_params.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_affect.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_agent_action_routing.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_agent_api.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_agent_bridge.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_agent_bridge_service.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_agent_sdk.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_agent_sensor_loop.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_agent_snapshot.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_agent_store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_annotated_recall_reinforcement.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_answer_source_lineage.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_appraisal_incident_decisions.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_approval_gate.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_approval_relay_canary.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_apsimo_compat.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_apsimo_harness_guidance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_assignment_engine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_audit_cleanup.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_auth_coverage.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_auth_migration_readiness.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_authz_scope_api.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_autonomy_preset.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_backup.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_backup_receipt_evidence.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_beliefs.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_bind_auth_guard.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_boundary_fail_closed.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_bounded_approval_authority.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_briefing_aggregators.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_canonical_scoped_context.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_canonical_source_read.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_causal_extract.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_causal_falsifiability.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_causal_maintenance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_causal_policy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_causal_query.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_causal_query_only_guard.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_chain_keys.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_channel_preferences.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_channel_registry.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_channel_store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_cognition.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_cognition_evidence_pipeline.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_cognition_evidence_server_wiring.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_cognition_goal_spine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_cognition_observability.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_cognition_p4_controlled_learning.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_cognition_p4_server_integration.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_cognition_p6_p7_server_wiring.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_cognition_p7_drive_governance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_cognition_phase_b_runtime.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_cognition_phase_c_scheduler.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_cognition_server_wiring.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_colony_memory_provider.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_commitment_resolution.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_commitment_resolution_downgrade.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_commitment_resolution_schema.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_commitment_work.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_commitments.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_competence_reconciliation.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_compression.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_concern_resolution_receipts.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_condition_producer.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_connectors.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_contact_fact_recall.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_contact_policy_projection.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_contact_provisioning.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_contact_timezone.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_contacts_intro.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_contacts_persistence.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_context_gate.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_context_phase1.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_context_provenance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_conversation_presence.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_conversation_turn_concerns.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_current_work_recall_selection.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_delivery_bridge_503.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_delivery_gateway_identity.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_delivery_reachout_routing.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_directed.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_directed_envelope.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_directed_reports.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_directed_trust.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_directive_sources.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_directives.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_distill.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_doctor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_document_memory_guard.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_duckduckgo_provider.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_embedding_generations.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_ensure_channel_id.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_env_risk.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_event_broadcasts.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_event_bus_types.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_event_concerns.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_event_stream_reliability.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_execution_forecasts.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_execution_input_purpose.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_execution_registry.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_expectations.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_expectations_v2.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_experiments.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_external_cognition_events.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_external_event_concerns.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_facts_backfill.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_feedback.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_followup_plans.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_forecast_learning.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_function_routing.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_gap_generators.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_genesis_manifest.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_global_pause.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_goal_dispatch_availability.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_goal_inference_provenance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_goal_reader_imports.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_governed_actions.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_governed_research_handoff.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_graduated_approvals.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_grant_envelope.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_graph_reindex_metadata.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_guard_audit.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_guard_chat_mode.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_guard_derive_context.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_guard_enforce_policy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_export.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_general_governance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_history_import.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_native_tool_authority.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_plugin_contract.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_plugin_event_lifecycle.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_plugin_event_replay.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_plugin_guard_shadow.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_plugin_signals.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_plugin_turn_id.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_queue_stats_projection.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_setup.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_turn_outbox.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hermes_work_projection.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_host_input_provenance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_hostworker_agreement.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_identity_continuity.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_identity_corrections.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_inference_context_gate.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_initiative_engine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_initiative_evidence.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_initiative_executor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_initiative_feedback.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_initiative_pipeline_v016.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_initiative_retry.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_initiative_store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_input_source_lineage.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_insight_store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_instance_service.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_instance_service_live.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_intelligence_components.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_intelligence_synthesis.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_introduction_initiatives.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_job_writeback.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_journal.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_legacy_fact_context.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_local_work_context.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_loop_stats_accuracy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_mcp_config.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_mcp_server.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_media_read_reference_presentation.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_memory_decay.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_memory_formation.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_memory_governance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_memory_promotion.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_memory_prune.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_memory_read_hydration.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_memory_response_schemas.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_migrations.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_mining.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_model_qualification_cli.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_model_qualification_memory.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_model_qualification_runner.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_model_qualification_structured.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_native_accepted_local_work.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_native_initiative_work.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_native_input_carrier.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_native_outcome_judgments.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_native_request_erasure.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_native_review_recurrence.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_native_source_image_read.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_native_source_read.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_native_source_video_read.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_neo4j_backend.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_operator_deck_read_truth.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_ordinary_context_briefings.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_owner_preferences.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_p2_wirings.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_partial_work_rendering.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_patterns.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_pending_work_coverage.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_persona.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_persona_setup_result.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_phase_capability_check.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_preset_loop_coupling.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_procedure_source_context.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_project_event_outbox.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_project_result_reconciliation_phase.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_projects.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_prompt_evals.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_proposals.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_provenance_population.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_pseudo_agi_production_chain.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_queue_completed_filter.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_queue_contract.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_quiet_hours_and_reload.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_reachout_policy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_recall_hybrid.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_recall_person_boost.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_recall_ranking.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_recall_rerank.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_recall_source_presentation.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_recall_unified_context.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_recency.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_reflection_task_routing.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_rejection_loop.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_relationship_calendar_aggregators.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_relationship_score_refresh.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_relationship_signal_floor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_relationships.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_reply_forecast_callback_order.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_reply_forecast_stops.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_reply_forecasts.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_repo_tools.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_reported_worker_status.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_request_capabilities.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_request_work_context.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_reranker_remote.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_research_orchestrator.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_resolve_messaging_handle.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_response_guard.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_response_guard_communication_policy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_response_guard_endpoint.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_response_guard_surface_policy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_router_tiers.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_runtime_model_observations.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_sandbox.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_secondary_review_contract.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_seed_retirement.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_selected_autonomy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_self_directed_thinker.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_self_initiatives.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_self_judgment_opt_in.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_self_judgment_premises.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_self_judgments.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_self_model.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_self_perspective.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_selfhood_benchmark.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_session_reports.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_shared_facts.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_shared_local_undertaking.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_short_source_context.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_sidecar.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_signals_attribution.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_situation_spine.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_skill_approval.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_skill_attribution.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_skill_sandbox.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_skill_synthesis.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_skill_synthesis_wiring.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_skills_memory.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_social_context_flow.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_social_transport.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_annotation_claim_survivors.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_annotations.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_appraisals.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_attribution.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_audio.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_audio_claims.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_claim_budget.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_claim_diagnostics.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_claim_media_eligibility.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_claim_projection.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_claim_review.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_claim_subject_basis.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_document_read.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_documents.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_episode_admission.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_episode_memory.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_episode_revisions.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_event_precision.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_excerpt_lineage.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_image_read.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_media.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_memory_backup.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_time_query.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_vectors.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_source_video.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_sqlite_connection_ownership.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_supervised_rung.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_surprise.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_sweep_fixes.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_synthesis.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_telemetry_staleness.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_temporal.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_temporal_followups.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_temporal_index.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_test_environment_isolation.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_thinking_phase.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_thought_function_routing.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tick_phase_budget.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tier_endpoints.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_timeline.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_approvals.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_asymmetry.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_context.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_cross_gate.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_eligibility.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_epistemic_guard.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_exposure.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_kill_switch.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_level_coherence.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_leveled.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_levels.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_source_corrections.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_taint.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom2_wiring.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom_event_lineage.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom_extractor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom_p8_arcs.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom_p8_boundary_corpus.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom_p8_fact_adapters.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom_p8_outbound_integration.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom_p8_recipient_audit.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom_p8_recipient_simulator.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom_p8_server_integration.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom_p8_visibility.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom_p8_visibility_store.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tom_source_lineage.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tool_handlers_graph.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tool_provenance.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_tool_surface.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_toolsmith.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_transport_ingress.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_transport_ingress_api.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_trust_configure.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_trust_scopes.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_trust_scopes_p2.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_turn_idempotency_ledger.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_turn_idempotency_v2.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_turn_ner_entities.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_turn_source_erasure.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_turn_source_evidence.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_turn_survivor_delivery.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_validation_sweep_fixes.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_vector_vacuum.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_wizard_autonomy.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_work_ancestry_projection.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_work_control_production_blockers.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_work_control_v1.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_work_orders.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_work_read_surface_authority.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_work_source_coverage.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_worker_handler_boundaries.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_worker_heartbeat_truth.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_worker_http_authority.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_worker_integration.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_worker_lifecycle_durability.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_workers_governor.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_workers_install.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_workspace.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_world_context_query.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_world_entity_reinforcement.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_world_llm_extract.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_world_model_prune.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_world_observations.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_world_populator.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_world_quality.py +0 -0
- {apsimo-1.3.0 → apsimo-1.3.1}/tests/test_world_supervised.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: apsimo
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.1
|
|
4
4
|
Summary: Persistent identity, memory and autonomy for AI agents
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -28,7 +28,7 @@ Requires-Dist: pandas>=2.0; extra == "vectors"
|
|
|
28
28
|
Requires-Dist: pyarrow>=15.0; extra == "vectors"
|
|
29
29
|
Requires-Dist: lancedb>=0.10; extra == "vectors"
|
|
30
30
|
Provides-Extra: hermes
|
|
31
|
-
Requires-Dist: apsimo-hermes<2,>=1.3.
|
|
31
|
+
Requires-Dist: apsimo-hermes<2,>=1.3.1; extra == "hermes"
|
|
32
32
|
Provides-Extra: mcp
|
|
33
33
|
Requires-Dist: mcp[cli]<2,>=1.0; extra == "mcp"
|
|
34
34
|
Provides-Extra: lancedb
|
|
@@ -961,6 +961,7 @@ def compatible_scopes(method: str, path: str) -> frozenset[str]:
|
|
|
961
961
|
if (method.upper(), path) in WORK_READ_SURFACE_V1 or (method.upper(), path) in {
|
|
962
962
|
("POST", "/v1/host/learning/correction"),
|
|
963
963
|
("POST", "/v1/host/response-guard/check"),
|
|
964
|
+
("GET", "/v1/host/contacts/resolve"),
|
|
964
965
|
}:
|
|
965
966
|
return _API_ACCESS_COMPATIBILITY
|
|
966
967
|
return _NO_COMPATIBILITY_SCOPES
|
|
@@ -1105,6 +1106,7 @@ def required_scope(method: str, path: str) -> str:
|
|
|
1105
1106
|
return "charter:approval-decide"
|
|
1106
1107
|
return "api:access"
|
|
1107
1108
|
exact = {
|
|
1109
|
+
("GET", "/v1/host/contacts/resolve"): "turns:resolve-sender",
|
|
1108
1110
|
("GET", "/v1/host/admin/auth/status"): "auth:admin",
|
|
1109
1111
|
("GET", "/v1/host/contact-policy"): "contacts:policy-read",
|
|
1110
1112
|
("POST", "/v1/host/response-guard/check"): "response-guard:check",
|
|
@@ -3907,6 +3907,26 @@ async def forget_turn_sources(body: SourceForgetRequest, request: Request = None
|
|
|
3907
3907
|
"host_reconciliation": "pending_until_each_host_connects"}
|
|
3908
3908
|
|
|
3909
3909
|
|
|
3910
|
+
async def _resolve_scoped_sender_contact(authority, gateway: str, address: str):
|
|
3911
|
+
"""Read one verified handle within the credential's existing grants."""
|
|
3912
|
+
platform = gateway.strip().lower()
|
|
3913
|
+
if (not authority.authenticated or not authority.has_scope('turns:resolve-sender')
|
|
3914
|
+
or platform not in authority.turn_ingress_platforms):
|
|
3915
|
+
raise HTTPException(status_code=403, detail='Sender resolution is outside this transport grant')
|
|
3916
|
+
if _contacts_store is None:
|
|
3917
|
+
raise HTTPException(status_code=503, detail='Contact store not initialized')
|
|
3918
|
+
from apsimo.contacts.identity_links import normalized_handle
|
|
3919
|
+
try:
|
|
3920
|
+
normalized_gateway, normalized_address = normalized_handle(platform, address)
|
|
3921
|
+
contact = await _contacts_store.resolve_verified_handles(
|
|
3922
|
+
normalized_gateway, [normalized_address])
|
|
3923
|
+
except ValueError:
|
|
3924
|
+
raise HTTPException(status_code=400, detail='Invalid sender handle') from None
|
|
3925
|
+
if contact is None or contact.contact_id not in authority.person_ids:
|
|
3926
|
+
raise HTTPException(status_code=404, detail='No enrolled contact for that handle')
|
|
3927
|
+
return contact
|
|
3928
|
+
|
|
3929
|
+
|
|
3910
3930
|
async def _ingest_turn_idempotently(
|
|
3911
3931
|
body: TurnSyncRequest,
|
|
3912
3932
|
request: Request | None = None,
|
|
@@ -3918,9 +3938,23 @@ async def _ingest_turn_idempotently(
|
|
|
3918
3938
|
effects run. This is the server's final defense even when a host retries or
|
|
3919
3939
|
two host integrations accidentally submit the same envelope.
|
|
3920
3940
|
"""
|
|
3941
|
+
resolved_sender_contact_id = None
|
|
3942
|
+
authority = request_authority(request)
|
|
3943
|
+
if (body.sender is not None and not authority.legacy and authority.authenticated
|
|
3944
|
+
and authority.has_scope('turns:resolve-sender')
|
|
3945
|
+
and not (authority.allow_unscoped_api and authority.has_scope('api:access'))
|
|
3946
|
+
and body.sender.platform.strip().lower() not in authority.attested_contact_platforms):
|
|
3947
|
+
# Static transport enrollment cannot inherit the viewer on a failed
|
|
3948
|
+
# lookup, or take the general resolver's canonical-ID/name fallbacks.
|
|
3949
|
+
# Validate before checkpoints, reservations or any source write.
|
|
3950
|
+
contact = await _resolve_scoped_sender_contact(
|
|
3951
|
+
authority, body.sender.platform, body.sender.user_id)
|
|
3952
|
+
resolved_sender_contact_id = contact.contact_id
|
|
3953
|
+
body.context.contact_id = contact.contact_id
|
|
3921
3954
|
turn_id = (body.context.turn_id or "").strip()
|
|
3922
3955
|
if not turn_id:
|
|
3923
|
-
return await _process_turn_sync(body, request=request
|
|
3956
|
+
return await _process_turn_sync(body, request=request,
|
|
3957
|
+
resolved_sender_contact_id=resolved_sender_contact_id), "unkeyed"
|
|
3924
3958
|
if len(turn_id) > 256:
|
|
3925
3959
|
raise HTTPException(
|
|
3926
3960
|
status_code=422,
|
|
@@ -4010,7 +4044,8 @@ async def _ingest_turn_idempotently(
|
|
|
4010
4044
|
), "in_progress"
|
|
4011
4045
|
|
|
4012
4046
|
try:
|
|
4013
|
-
result = await _process_turn_sync(body, request=request
|
|
4047
|
+
result = await _process_turn_sync(body, request=request,
|
|
4048
|
+
resolved_sender_contact_id=resolved_sender_contact_id)
|
|
4014
4049
|
except BaseException as exc:
|
|
4015
4050
|
ledger.mark_ambiguous(turn_id, digest, exc)
|
|
4016
4051
|
raise
|
|
@@ -4177,6 +4212,8 @@ async def turns_sync_v2(
|
|
|
4177
4212
|
async def _process_turn_sync(
|
|
4178
4213
|
body: TurnSyncRequest,
|
|
4179
4214
|
request: Request | None = None,
|
|
4215
|
+
*,
|
|
4216
|
+
resolved_sender_contact_id: str | None = None,
|
|
4180
4217
|
) -> TurnSyncResponse:
|
|
4181
4218
|
# Keep direct blocks for canonical source storage. All existing text-only
|
|
4182
4219
|
# cognition consumers receive only explicit text, never repr(base64/URLs).
|
|
@@ -4221,7 +4258,11 @@ async def _process_turn_sync(
|
|
|
4221
4258
|
from apsimo.identity.participants import (
|
|
4222
4259
|
SYSTEM_CONTACT_ID, ParticipantResolver, is_machine_turn,
|
|
4223
4260
|
)
|
|
4224
|
-
if
|
|
4261
|
+
if resolved_sender_contact_id is not None:
|
|
4262
|
+
body.context.contact_id = resolved_sender_contact_id
|
|
4263
|
+
_resolution_method = "verified_handle"
|
|
4264
|
+
_resolved_human_sender = True
|
|
4265
|
+
elif body.sender is not None and _contacts_store is not None:
|
|
4225
4266
|
_res = await ParticipantResolver(_contacts_store).resolve(
|
|
4226
4267
|
platform=body.sender.platform,
|
|
4227
4268
|
user_id=body.sender.user_id,
|
|
@@ -6282,7 +6323,7 @@ async def capture_introduction(body: ContactIntroRequest) -> ContactIntroRespons
|
|
|
6282
6323
|
|
|
6283
6324
|
|
|
6284
6325
|
@router.get("/contacts/resolve", response_model=ContactResponse)
|
|
6285
|
-
async def resolve_contact_by_handle(gateway: str, address: str, create: bool = False) -> ContactResponse:
|
|
6326
|
+
async def resolve_contact_by_handle(gateway: str, address: str, request: Request, create: bool = False) -> ContactResponse:
|
|
6286
6327
|
"""Resolve a contact from a messaging handle (v0.21.2).
|
|
6287
6328
|
|
|
6288
6329
|
Registered BEFORE /contacts/{contact_id} so it isn't shadowed by the
|
|
@@ -6298,6 +6339,14 @@ async def resolve_contact_by_handle(gateway: str, address: str, create: bool = F
|
|
|
6298
6339
|
if _contacts_store is None:
|
|
6299
6340
|
raise HTTPException(status_code=404, detail="Contact store not initialized")
|
|
6300
6341
|
try:
|
|
6342
|
+
authority = request_authority(request)
|
|
6343
|
+
if not authority.legacy and not (
|
|
6344
|
+
authority.allow_unscoped_api and authority.has_scope('api:access')):
|
|
6345
|
+
# Fresh native profiles resolve only explicitly enrolled accounts.
|
|
6346
|
+
# The memory provider's legacy create=true hint cannot provision a
|
|
6347
|
+
# contact or expand the credential's person/transport grants here.
|
|
6348
|
+
contact = await _resolve_scoped_sender_contact(authority, gateway, address)
|
|
6349
|
+
return ContactResponse(**contact.to_dict())
|
|
6301
6350
|
# Normalized, cross-gateway phone-identity resolution (a number is one contact regardless of
|
|
6302
6351
|
# the transport it arrived on). find_by_handle stays exact-match for dedup callers.
|
|
6303
6352
|
contact = await _contacts_store.resolve_messaging_handle(gateway, address)
|
|
@@ -53,6 +53,7 @@ def main() -> None:
|
|
|
53
53
|
# Backward compatibility
|
|
54
54
|
init_p.add_argument("--host-framework", choices=["openclaw", "hermes", "claude-code", "codex", "crush", "standalone"], help="Host framework (deprecated: use --agent-harness or --mcp-harnesses)")
|
|
55
55
|
init_p.add_argument("--contact-name", help="Contact name for this user")
|
|
56
|
+
init_p.add_argument("--owner-handle", action="append", metavar="CHANNEL=SENDER_ID", help="Enroll your exact Hermes sender ID when creating a private instance; repeat for each account")
|
|
56
57
|
init_p.add_argument("--bind", default="127.0.0.1", help="Sidecar bind address (0.0.0.0 for all interfaces)")
|
|
57
58
|
init_p.add_argument("--port", type=int, default=7777, help="Sidecar port")
|
|
58
59
|
init_p.add_argument("--tier", type=int, choices=range(0, 8), metavar="TIER", help="Embedding tier (0-7)")
|
|
@@ -1947,11 +1947,11 @@ def run_init(root_dir: str | None = None, args=None) -> int:
|
|
|
1947
1947
|
root_dir: Root directory for config files
|
|
1948
1948
|
args: Parsed argparse Namespace for non-interactive mode
|
|
1949
1949
|
"""
|
|
1950
|
-
if (getattr(args, 'preferences_only', False) or getattr(args, 'preview', False)
|
|
1950
|
+
if (getattr(args, 'owner_handle', None) or getattr(args, 'preferences_only', False) or getattr(args, 'preview', False)
|
|
1951
1951
|
or getattr(args, 'whatsapp_read_receipts', None) is not None):
|
|
1952
1952
|
if (getattr(args, 'no_harness', False) or getattr(args, 'mcp_harnesses', None)
|
|
1953
1953
|
or getattr(args, 'host_framework', None) not in (None, 'hermes')):
|
|
1954
|
-
print('Hermes profile
|
|
1954
|
+
print('Hermes profile options cannot be combined with another harness setup.')
|
|
1955
1955
|
return 1
|
|
1956
1956
|
from apsimo.setup_hermes import run
|
|
1957
1957
|
return run(root_dir, args)
|
|
@@ -58,6 +58,33 @@ def _json(value):
|
|
|
58
58
|
return json.dumps(value, indent=2, ensure_ascii=False) + '\n'
|
|
59
59
|
|
|
60
60
|
|
|
61
|
+
def _owner_handles(args, ask, noninteractive):
|
|
62
|
+
"""Local enrollment binds exact accounts; it does not configure channels."""
|
|
63
|
+
from .contacts.identity_links import normalized_handle
|
|
64
|
+
supplied = getattr(args, 'owner_handle', None)
|
|
65
|
+
values = list(supplied or [])
|
|
66
|
+
if not supplied and not noninteractive:
|
|
67
|
+
print('Optionally identify your own messaging accounts using Hermes sender IDs, not display names or group IDs.')
|
|
68
|
+
print('For example: telegram=123456789. Hermes continues to configure and authenticate each channel.')
|
|
69
|
+
while value := ask('Your account CHANNEL=SENDER_ID (blank to finish)'):
|
|
70
|
+
values.append(value)
|
|
71
|
+
handles, platforms = [], set()
|
|
72
|
+
for value in values:
|
|
73
|
+
platform, separator, address = value.partition('=')
|
|
74
|
+
platform, address = platform.strip().lower(), address.strip()
|
|
75
|
+
if (not separator or not re.fullmatch(r'[a-z0-9][a-z0-9_.-]{0,63}', platform)
|
|
76
|
+
or platform in {'cli', 'internal', 'system', 'background_review', 'colony_task'}
|
|
77
|
+
or any(ord(char) < 32 or ord(char) == 127 for char in address)):
|
|
78
|
+
raise ValueError('--owner-handle requires CHANNEL=SENDER_ID for your authenticated messaging account')
|
|
79
|
+
gateway, address = normalized_handle(platform, address)
|
|
80
|
+
if not address or address == '+':
|
|
81
|
+
raise ValueError('--owner-handle requires a nonempty sender ID')
|
|
82
|
+
if (gateway, address) not in handles:
|
|
83
|
+
handles.append((gateway, address))
|
|
84
|
+
platforms.add(platform)
|
|
85
|
+
return handles, sorted(platforms)
|
|
86
|
+
|
|
87
|
+
|
|
61
88
|
def _receipt_preference(config, choice):
|
|
62
89
|
"""Project one native shared key, respecting Hermes' existing YAML layouts.
|
|
63
90
|
|
|
@@ -563,7 +590,7 @@ def run(root_dir=None, args=None):
|
|
|
563
590
|
if root_dir or any(getattr(args, name, None) for name in (
|
|
564
591
|
'start', 'refresh_adapter', 'replace_memory_provider', 'local_work',
|
|
565
592
|
'native_goals', 'native_reviews', 'model_url', 'model', 'adapter_wheel', 'agent_name',
|
|
566
|
-
'agent_values', 'timezone', 'quiet_hours', 'contact_name', 'encrypt',
|
|
593
|
+
'agent_values', 'timezone', 'quiet_hours', 'contact_name', 'owner_handle', 'encrypt',
|
|
567
594
|
'passphrase', 'claim_genesis', 'mcp_harnesses', 'no_harness')) or (
|
|
568
595
|
getattr(args, 'host_framework', None) not in (None, 'hermes')):
|
|
569
596
|
raise ValueError('--preferences-only cannot be combined with instance or setup options')
|
|
@@ -593,6 +620,8 @@ def run(root_dir=None, args=None):
|
|
|
593
620
|
if any((home/name).exists() for name in ('colony-memory.json', 'apsimo-memory.json')):
|
|
594
621
|
raise ValueError('Existing native Apsimo settings need an explicit migration; select a new home')
|
|
595
622
|
if (state/'instance.json').exists():
|
|
623
|
+
if getattr(args, 'owner_handle', None):
|
|
624
|
+
raise ValueError('--owner-handle is for a new private instance; existing owner bindings are retained')
|
|
596
625
|
manifest = json.loads((state/'instance.json').read_text())
|
|
597
626
|
if manifest.get('hermes_home') != str(home):
|
|
598
627
|
raise ValueError('This instance belongs to another Hermes home')
|
|
@@ -652,6 +681,7 @@ def run(root_dir=None, args=None):
|
|
|
652
681
|
_preflight_outbox(home, resources)
|
|
653
682
|
binding = _adapter_binding(python, resources)
|
|
654
683
|
owner_name = ask('Your name', getattr(args, 'contact_name', None) or os.environ.get('USER', 'Owner'), True)
|
|
684
|
+
owner_handles, owner_platforms = _owner_handles(args, ask, noninteractive)
|
|
655
685
|
agent_name = ask('Agent name', getattr(args, 'agent_name', None) or 'Assistant', True)
|
|
656
686
|
agent_preferences = _agent_preferences(ask, args, config)
|
|
657
687
|
endpoint = _endpoint(ask('Local model API root', getattr(args, 'model_url', None), True))
|
|
@@ -726,7 +756,11 @@ def run(root_dir=None, args=None):
|
|
|
726
756
|
store = SQLiteContactStore(ContactsConfig(sqlite_path=str(staged/'contacts.db')))
|
|
727
757
|
await store.connect()
|
|
728
758
|
try:
|
|
729
|
-
|
|
759
|
+
contact_id = await setup.build_owner_contact(store, owner_name)
|
|
760
|
+
for index, (gateway, address) in enumerate(owner_handles):
|
|
761
|
+
await store.add_handle(contact_id, gateway, address,
|
|
762
|
+
is_primary=index == 0, source='wizard', verified=True)
|
|
763
|
+
return contact_id
|
|
730
764
|
finally:
|
|
731
765
|
await store.close()
|
|
732
766
|
owner_id = asyncio.run(owner())
|
|
@@ -750,9 +784,11 @@ def run(root_dir=None, args=None):
|
|
|
750
784
|
values = {('APSIMO_'+key[7:] if key.startswith('COLONY_') else key):value for key,value in values.items()}
|
|
751
785
|
_private_write(staged/'.env', _native_environment(None, values))
|
|
752
786
|
principal = {'principal': 'hermes-local', 'status': 'active', 'viewer_person_id': owner_id,
|
|
753
|
-
'audiences': ['viewer'], 'allow_unscoped_api': False, 'turn_ingress_platforms': ['cli'],
|
|
787
|
+
'audiences': ['viewer'], 'allow_unscoped_api': False, 'turn_ingress_platforms': ['cli', *owner_platforms],
|
|
754
788
|
'scopes': ['context:read', 'memory:read', 'memory:search', 'memory:write', 'turns:write'],
|
|
755
789
|
'credentials': [{'id': 'initial', 'secret': key, 'status': 'active'}]}
|
|
790
|
+
if owner_handles:
|
|
791
|
+
principal['scopes'].append('turns:resolve-sender')
|
|
756
792
|
_private_write(staged/'api-keyring.json', _json({'version': 1, 'principals': [principal]}))
|
|
757
793
|
model_configuration = {'provider': 'local', 'baseUrl': endpoint,
|
|
758
794
|
'apiKey': model_key, 'localHosts': local_hosts,
|
|
@@ -857,6 +893,8 @@ def run(root_dir=None, args=None):
|
|
|
857
893
|
print(f'Private agent configured in {home}; state in {state}.')
|
|
858
894
|
print('Adapter loading: ' + binding['mode'] + ' (canonical artifact bytes verified).')
|
|
859
895
|
print('Canonical memory capture and recollection are enabled for new Hermes sessions.')
|
|
896
|
+
if owner_handles:
|
|
897
|
+
print('Owner accounts enrolled for: ' + ', '.join(owner_platforms) + '. Channel configuration and delivery still belong to Hermes.')
|
|
860
898
|
print('Hermes hook output spill allowance is at least 65536 characters or already disabled; retrieval budgets are unchanged.')
|
|
861
899
|
print('Source memory, temporal claims, contacts, commitments and self state persist without a graph.')
|
|
862
900
|
print('Graph/vector recall and consequential background work are optional and currently disabled.')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: apsimo
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.1
|
|
4
4
|
Summary: Persistent identity, memory and autonomy for AI agents
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -28,7 +28,7 @@ Requires-Dist: pandas>=2.0; extra == "vectors"
|
|
|
28
28
|
Requires-Dist: pyarrow>=15.0; extra == "vectors"
|
|
29
29
|
Requires-Dist: lancedb>=0.10; extra == "vectors"
|
|
30
30
|
Provides-Extra: hermes
|
|
31
|
-
Requires-Dist: apsimo-hermes<2,>=1.3.
|
|
31
|
+
Requires-Dist: apsimo-hermes<2,>=1.3.1; extra == "hermes"
|
|
32
32
|
Provides-Extra: mcp
|
|
33
33
|
Requires-Dist: mcp[cli]<2,>=1.0; extra == "mcp"
|
|
34
34
|
Provides-Extra: lancedb
|
|
@@ -707,6 +707,7 @@ tests/test_doctor.py
|
|
|
707
707
|
tests/test_document_memory_guard.py
|
|
708
708
|
tests/test_duckduckgo_provider.py
|
|
709
709
|
tests/test_embedding_generations.py
|
|
710
|
+
tests/test_enrolled_sender_turns.py
|
|
710
711
|
tests/test_ensure_channel_id.py
|
|
711
712
|
tests/test_env_risk.py
|
|
712
713
|
tests/test_event_broadcasts.py
|
|
@@ -860,6 +861,7 @@ tests/test_router_tiers.py
|
|
|
860
861
|
tests/test_runtime_model_observations.py
|
|
861
862
|
tests/test_sandbox.py
|
|
862
863
|
tests/test_scoped_api_authority.py
|
|
864
|
+
tests/test_scoped_contact_resolution.py
|
|
863
865
|
tests/test_secondary_review_contract.py
|
|
864
866
|
tests/test_seed_retirement.py
|
|
865
867
|
tests/test_selected_autonomy.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "apsimo"
|
|
7
|
-
version = "1.3.
|
|
7
|
+
version = "1.3.1"
|
|
8
8
|
description = "Persistent identity, memory and autonomy for AI agents"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -29,7 +29,7 @@ dependencies = [
|
|
|
29
29
|
graph = ["neo4j>=5.18"]
|
|
30
30
|
neo4j = ["neo4j>=5.18"]
|
|
31
31
|
vectors = ["sentence-transformers>=3.0", "pandas>=2.0", "pyarrow>=15.0", "lancedb>=0.10"]
|
|
32
|
-
hermes = ["apsimo-hermes>=1.3.
|
|
32
|
+
hermes = ["apsimo-hermes>=1.3.1,<2"]
|
|
33
33
|
mcp = ["mcp[cli]>=1.0,<2"]
|
|
34
34
|
lancedb = ["lancedb>=0.6", "pyarrow>=14.0", "pandas>=2.0"]
|
|
35
35
|
postgres = ["asyncpg>=0.29"]
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""Fresh transport grants admit only enrolled senders before source storage."""
|
|
2
|
+
import asyncio
|
|
3
|
+
import json
|
|
4
|
+
import sqlite3
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from fastapi import FastAPI
|
|
8
|
+
import httpx
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
from apsimo import setup
|
|
12
|
+
from apsimo.api.middleware import ApiKeyMiddleware
|
|
13
|
+
from apsimo.api.routers import host
|
|
14
|
+
from apsimo.contacts.config import ContactsConfig
|
|
15
|
+
from apsimo.contacts.store import SQLiteContactStore
|
|
16
|
+
from apsimo.turns import TurnIdempotencyLedger
|
|
17
|
+
from test_native_setup import args, isolated_platform_environment # Shared isolated wizard fixtures.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@pytest.mark.parametrize('version', ['v1', 'v2'])
|
|
21
|
+
def test_enrolled_sender_checked_before_turn_reservation(args, monkeypatch, version):
|
|
22
|
+
args.owner_handle = ['telegram=123456789']
|
|
23
|
+
assert setup.run_init(None, args) == 0
|
|
24
|
+
state = Path(args.hermes_home)/'apsimo'
|
|
25
|
+
principal = json.loads((state/'api-keyring.json').read_text())['principals'][0]
|
|
26
|
+
owner = principal['viewer_person_id']
|
|
27
|
+
monkeypatch.setenv('COLONY_STATE_DIR', str(state))
|
|
28
|
+
monkeypatch.setenv('COLONY_IDENTITY_SHADOW_CONTACTS', 'false')
|
|
29
|
+
for name in ('_graph', '_presence_store', '_context_provenance', '_telemetry', '_p8_runtime'):
|
|
30
|
+
monkeypatch.setattr(host, name, None)
|
|
31
|
+
ledger = TurnIdempotencyLedger(state/'turn-idempotency.db')
|
|
32
|
+
|
|
33
|
+
async def exercise():
|
|
34
|
+
store = SQLiteContactStore(ContactsConfig(sqlite_path=str(state/'contacts.db')))
|
|
35
|
+
await store.connect()
|
|
36
|
+
monkeypatch.setattr(host, '_contacts_store', store)
|
|
37
|
+
try:
|
|
38
|
+
guest = await store.create(display_name='Other account')
|
|
39
|
+
await store.add_handle(guest.contact_id, 'telegram', '987654321', verified=True)
|
|
40
|
+
await store.add_handle(owner, 'telegram', 'unverified', verified=False)
|
|
41
|
+
before_contacts = await store.list()
|
|
42
|
+
app = FastAPI()
|
|
43
|
+
app.include_router(host.router)
|
|
44
|
+
app.include_router(host.v2_router)
|
|
45
|
+
app.add_middleware(ApiKeyMiddleware, keyring_path=str(state/'api-keyring.json'))
|
|
46
|
+
headers = {'Authorization': 'Bearer ' + principal['credentials'][0]['secret']}
|
|
47
|
+
|
|
48
|
+
async def send(client, turn_id, platform, sender):
|
|
49
|
+
body = {'identity': {'host_id': 'fixture'},
|
|
50
|
+
'context': {'contact_id': owner if sender is None else 'body-selected-person',
|
|
51
|
+
'session_id': 'enrolled-source',
|
|
52
|
+
'channel_id': platform + ':fixture', 'turn_id': turn_id}}
|
|
53
|
+
if sender is not None:
|
|
54
|
+
body['sender'] = {'platform': platform, 'user_id': sender}
|
|
55
|
+
message = {'role': 'user', 'content': 'The archive reference is violet.'}
|
|
56
|
+
body.update(user_message=message, source_only=True)
|
|
57
|
+
if version == 'v1':
|
|
58
|
+
return await client.post('/v1/host/turns/sync', json=body)
|
|
59
|
+
return await client.put('/v2/host/turns/' + turn_id, json=body)
|
|
60
|
+
|
|
61
|
+
async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app),
|
|
62
|
+
base_url='http://fixture', headers=headers) as client:
|
|
63
|
+
denied = [('unknown', 'telegram', 'unknown', 404),
|
|
64
|
+
('canonical-id', 'telegram', owner, 404),
|
|
65
|
+
('other-person', 'telegram', '987654321', 404),
|
|
66
|
+
('unverified', 'telegram', 'unverified', 404),
|
|
67
|
+
('wrong-channel', 'whatsapp', '123456789', 403)]
|
|
68
|
+
for turn_id, platform, sender, code in denied:
|
|
69
|
+
response = await send(client, turn_id, platform, sender)
|
|
70
|
+
assert response.status_code == code, (turn_id, response.text)
|
|
71
|
+
with sqlite3.connect(ledger.db_path) as db:
|
|
72
|
+
assert db.execute('SELECT count(*) FROM turn_sources').fetchone()[0] == 0
|
|
73
|
+
assert db.execute('SELECT count(*) FROM turn_ingestion').fetchone()[0] == 0
|
|
74
|
+
assert await store.list() == before_contacts
|
|
75
|
+
response = await send(client, 'known-owner', 'telegram', '123456789')
|
|
76
|
+
assert response.status_code == (200 if version == 'v1' else 201), response.text
|
|
77
|
+
assert response.json()['source_recorded'] is True
|
|
78
|
+
replay = await send(client, 'known-owner', 'telegram', '123456789')
|
|
79
|
+
assert replay.status_code == 200 and replay.json()['source_recorded'] is True
|
|
80
|
+
with sqlite3.connect(ledger.db_path) as db:
|
|
81
|
+
rows = db.execute('SELECT contact_id,messages_json FROM turn_sources').fetchall()
|
|
82
|
+
assert len(rows) == 1 and rows[0][0] == owner
|
|
83
|
+
assert json.loads(rows[0][1])[0]['content'] == 'The archive reference is violet.'
|
|
84
|
+
# Native CLI has no human sender ID. Its exact viewer binding
|
|
85
|
+
# still permits capture without inventing a transport handle.
|
|
86
|
+
response = await send(client, 'senderless-cli', 'cli', None)
|
|
87
|
+
assert response.status_code == (200 if version == 'v1' else 201), response.text
|
|
88
|
+
assert response.json()['source_recorded'] is True
|
|
89
|
+
with sqlite3.connect(ledger.db_path) as db:
|
|
90
|
+
assert db.execute('SELECT contact_id FROM turn_sources WHERE turn_id=?',
|
|
91
|
+
('senderless-cli',)).fetchone() == (owner,)
|
|
92
|
+
finally:
|
|
93
|
+
await store.close()
|
|
94
|
+
asyncio.run(exercise())
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Guided native init preserves profiles and creates one private scoped instance."""
|
|
2
2
|
import json
|
|
3
|
+
import asyncio
|
|
3
4
|
import os
|
|
4
5
|
import socket
|
|
5
6
|
from pathlib import Path
|
|
@@ -152,6 +153,98 @@ def test_new_private_instance_uses_canonical_resources_and_scoped_authority(args
|
|
|
152
153
|
assert before == ((home/'config.yaml').read_bytes(), (state/'api-keyring.json').read_bytes())
|
|
153
154
|
|
|
154
155
|
|
|
156
|
+
def test_enrolled_owner_accounts_resolve_through_the_generated_scoped_api(args, monkeypatch):
|
|
157
|
+
from fastapi import FastAPI
|
|
158
|
+
from apsimo.api.middleware import ApiKeyMiddleware
|
|
159
|
+
from apsimo.api.routers import host
|
|
160
|
+
from apsimo.contacts.config import ContactsConfig
|
|
161
|
+
from apsimo.contacts.store import SQLiteContactStore
|
|
162
|
+
|
|
163
|
+
home = Path(args.hermes_home)
|
|
164
|
+
home.mkdir(mode=0o700)
|
|
165
|
+
channels = {'telegram': {'enabled': True, 'allowed_users': ['123456789']}}
|
|
166
|
+
(home/'config.yaml').write_text(yaml.safe_dump(channels))
|
|
167
|
+
args.owner_handle = ['telegram=123456789', 'sms=+1 (202) 555-0198', 'telegram=123456789']
|
|
168
|
+
assert setup.run_init(None, args) == 0
|
|
169
|
+
state = home/'apsimo'
|
|
170
|
+
config = yaml.safe_load((home/'config.yaml').read_text())
|
|
171
|
+
assert config['telegram'] == channels['telegram']
|
|
172
|
+
assert config['plugins']['apsimo']['attested_system_platforms'] == ['cli']
|
|
173
|
+
principal = json.loads((state/'api-keyring.json').read_text())['principals'][0]
|
|
174
|
+
assert principal['turn_ingress_platforms'] == ['cli', 'sms', 'telegram']
|
|
175
|
+
assert 'turns:resolve-sender' in principal['scopes']
|
|
176
|
+
assert principal['allow_unscoped_api'] is False
|
|
177
|
+
assert 'api:access' not in principal['scopes']
|
|
178
|
+
owner_id = principal['viewer_person_id']
|
|
179
|
+
|
|
180
|
+
async def exercise():
|
|
181
|
+
store = SQLiteContactStore(ContactsConfig(sqlite_path=str(state/'contacts.db')))
|
|
182
|
+
await store.connect()
|
|
183
|
+
monkeypatch.setattr(host, '_contacts_store', store)
|
|
184
|
+
try:
|
|
185
|
+
handles = await store.get_handles(owner_id)
|
|
186
|
+
assert len(handles) == 2 and all(row.verified and row.source == 'wizard' for row in handles)
|
|
187
|
+
guest = await store.create(display_name='Other person')
|
|
188
|
+
await store.add_handle(guest.contact_id, 'telegram', '987654321', verified=True)
|
|
189
|
+
await store.add_handle(owner_id, 'telegram', '111111111', verified=False)
|
|
190
|
+
before = (await store.list(), await store.get_handles(owner_id))
|
|
191
|
+
app = FastAPI()
|
|
192
|
+
app.add_middleware(ApiKeyMiddleware, keyring_path=str(state/'api-keyring.json'))
|
|
193
|
+
app.include_router(host.router)
|
|
194
|
+
headers = {'Authorization': 'Bearer ' + principal['credentials'][0]['secret']}
|
|
195
|
+
async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url='http://setup') as client:
|
|
196
|
+
for gateway, address, create, status in [
|
|
197
|
+
('telegram', '123456789', False, 200),
|
|
198
|
+
('telegram', '123456789', True, 200), # Memory provider's existing read call.
|
|
199
|
+
('sms', '+1 (202) 555-0198', True, 200),
|
|
200
|
+
('telegram', 'unknown', True, 404),
|
|
201
|
+
('telegram', '987654321', False, 404),
|
|
202
|
+
('telegram', '111111111', False, 404),
|
|
203
|
+
('telegram', '+12025550198', False, 404), # No inferred cross-channel authority.
|
|
204
|
+
('whatsapp', '123456789', False, 403),
|
|
205
|
+
]:
|
|
206
|
+
response = await client.get('/v1/host/contacts/resolve', headers=headers,
|
|
207
|
+
params={'gateway': gateway, 'address': address, 'create': str(create).lower()})
|
|
208
|
+
assert response.status_code == status, response.text
|
|
209
|
+
if status == 200:
|
|
210
|
+
assert response.json()['contact_id'] == owner_id
|
|
211
|
+
denied = await client.get('/v1/host/contacts/resolve',
|
|
212
|
+
params={'gateway': 'telegram', 'address': '123456789'})
|
|
213
|
+
assert denied.status_code == 401
|
|
214
|
+
assert before == (await store.list(), await store.get_handles(owner_id))
|
|
215
|
+
finally:
|
|
216
|
+
await store.close()
|
|
217
|
+
asyncio.run(exercise())
|
|
218
|
+
|
|
219
|
+
retained = ((state/'api-keyring.json').read_bytes(), (home/'config.yaml').read_bytes(),
|
|
220
|
+
(state/'contacts.db').read_bytes())
|
|
221
|
+
assert setup.run_init(None, args) == 1 # Enrollment arguments are never silently ignored on rerun.
|
|
222
|
+
assert retained == ((state/'api-keyring.json').read_bytes(), (home/'config.yaml').read_bytes(),
|
|
223
|
+
(state/'contacts.db').read_bytes())
|
|
224
|
+
args.owner_handle = None
|
|
225
|
+
assert setup.run_init(None, args) == 0
|
|
226
|
+
assert retained == ((state/'api-keyring.json').read_bytes(), (home/'config.yaml').read_bytes(),
|
|
227
|
+
(state/'contacts.db').read_bytes())
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
@pytest.mark.parametrize('handle', ['telegram', '=123', 'telegram=', 'sms=letters',
|
|
231
|
+
'cli=owner', 'telegram=abc\n123', 'telegram=' + 'x' * 513])
|
|
232
|
+
def test_bad_owner_enrollment_stops_before_probe_or_state(args, handle, monkeypatch):
|
|
233
|
+
args.owner_handle = [handle]
|
|
234
|
+
probe = Mock(side_effect=AssertionError('Invalid enrollment must precede model probing'))
|
|
235
|
+
monkeypatch.setattr(setup_hermes, '_verify_local_endpoint', probe)
|
|
236
|
+
assert setup.run_init(None, args) == 1
|
|
237
|
+
probe.assert_not_called()
|
|
238
|
+
assert not Path(args.hermes_home).exists()
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def test_guided_owner_enrollment_uses_the_same_normalized_bindings():
|
|
242
|
+
answers = iter(['email=Owner@Example.org', 'rcs=+1 (202) 555-0198', ''])
|
|
243
|
+
handles, platforms = setup_hermes._owner_handles(SimpleNamespace(), lambda *a: next(answers), False)
|
|
244
|
+
assert handles == [('email', 'owner@example.org'), ('sms', '+12025550198')]
|
|
245
|
+
assert platforms == ['email', 'rcs']
|
|
246
|
+
|
|
247
|
+
|
|
155
248
|
def test_writable_ancestor_stops_before_endpoint_probe_or_attachment(args, tmp_path, monkeypatch, capsys):
|
|
156
249
|
shared = tmp_path/'shared-parent'
|
|
157
250
|
shared.mkdir(mode=0o775)
|
|
@@ -545,11 +545,13 @@ async def test_turn_contact_is_validated_before_idempotent_ingestion(tmp_path, g
|
|
|
545
545
|
|
|
546
546
|
|
|
547
547
|
@pytest.mark.asyncio
|
|
548
|
-
async def
|
|
548
|
+
async def test_sender_resolving_adapter_cannot_inherit_viewer_without_contact_store(tmp_path, graph):
|
|
549
549
|
keyring = tmp_path / "keys.json"
|
|
550
|
-
|
|
550
|
+
principal = _principal(scopes=[
|
|
551
551
|
"turns:write", "turns:resolve-sender"
|
|
552
|
-
])
|
|
552
|
+
])
|
|
553
|
+
principal['turn_ingress_platforms'] = ['example-chat']
|
|
554
|
+
_write_keyring(keyring, [principal])
|
|
553
555
|
app = _app(keyring)
|
|
554
556
|
payload = _turn_payload("body-claim", "sender-turn")
|
|
555
557
|
payload["sender"] = {
|
|
@@ -563,10 +565,10 @@ async def test_sender_resolving_adapter_discards_initial_contact_claim(tmp_path,
|
|
|
563
565
|
json=payload,
|
|
564
566
|
)
|
|
565
567
|
|
|
566
|
-
assert response.status_code ==
|
|
567
|
-
#
|
|
568
|
-
#
|
|
569
|
-
assert graph.turn_calls
|
|
568
|
+
assert response.status_code == 503
|
|
569
|
+
# Unavailable identity resolution cannot turn an unknown sender into the
|
|
570
|
+
# credential's default viewer or run ordinary conversation effects.
|
|
571
|
+
assert graph.turn_calls == []
|
|
570
572
|
|
|
571
573
|
|
|
572
574
|
@pytest.mark.asyncio
|
|
@@ -930,8 +932,8 @@ async def test_resolved_sender_in_static_grant_needs_no_dynamic_platform_grant(
|
|
|
930
932
|
from apsimo.events import journal as event_journal
|
|
931
933
|
|
|
932
934
|
class Contacts:
|
|
933
|
-
async def
|
|
934
|
-
assert (platform,
|
|
935
|
+
async def resolve_verified_handles(self, platform, user_ids):
|
|
936
|
+
assert (platform, user_ids) == ("voice", ["owner-voice-handle"])
|
|
935
937
|
return SimpleNamespace(contact_id="contact-owner")
|
|
936
938
|
|
|
937
939
|
async def record_interaction(self, _contact_id):
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""The focused sender resolver preserves explicitly broad legacy clients."""
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
from fastapi import FastAPI
|
|
5
|
+
import httpx
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from apsimo.api.middleware import ApiKeyMiddleware
|
|
9
|
+
from apsimo.api.routers import host
|
|
10
|
+
from apsimo.contacts.config import ContactsConfig
|
|
11
|
+
from apsimo.contacts.store import SQLiteContactStore
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.mark.asyncio
|
|
15
|
+
async def test_legacy_resolver_scope_compatibility_is_explicit(tmp_path, monkeypatch):
|
|
16
|
+
store = SQLiteContactStore(ContactsConfig(sqlite_path=str(tmp_path/'contacts.db')))
|
|
17
|
+
await store.connect()
|
|
18
|
+
monkeypatch.setattr(host, '_contacts_store', store)
|
|
19
|
+
try:
|
|
20
|
+
owner = await store.create(display_name='Owner')
|
|
21
|
+
await store.add_handle(owner.contact_id, 'telegram', '123456789', verified=True)
|
|
22
|
+
keyring = tmp_path/'keyring.json'
|
|
23
|
+
keyring.write_text(json.dumps({'version': 1, 'principals': [{
|
|
24
|
+
'principal': name, 'status': 'active', 'viewer_person_id': owner.contact_id,
|
|
25
|
+
'audiences': ['viewer'], 'allow_unscoped_api': broad, 'scopes': ['api:access'],
|
|
26
|
+
'credentials': [{'id': 'test', 'status': 'active', 'secret': name + '-secret'}],
|
|
27
|
+
} for name, broad in [('broad', True), ('restricted', False)]]}))
|
|
28
|
+
keyring.chmod(0o600)
|
|
29
|
+
app = FastAPI()
|
|
30
|
+
app.add_middleware(ApiKeyMiddleware, keyring_path=str(keyring), api_key='legacy-secret')
|
|
31
|
+
app.include_router(host.router)
|
|
32
|
+
async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url='http://test') as client:
|
|
33
|
+
for secret, status in [('legacy-secret', 200), ('broad-secret', 200), ('restricted-secret', 403)]:
|
|
34
|
+
response = await client.get('/v1/host/contacts/resolve',
|
|
35
|
+
headers={'Authorization': 'Bearer ' + secret},
|
|
36
|
+
params={'gateway': 'telegram', 'address': '123456789'})
|
|
37
|
+
assert response.status_code == status, response.text
|
|
38
|
+
if status == 200:
|
|
39
|
+
assert response.json()['contact_id'] == owner.contact_id
|
|
40
|
+
# Retain the previously explicit broad provisioning behavior.
|
|
41
|
+
response = await client.get('/v1/host/contacts/resolve',
|
|
42
|
+
headers={'Authorization': 'Bearer broad-secret'},
|
|
43
|
+
params={'gateway': 'telegram', 'address': '987654321', 'create': 'true'})
|
|
44
|
+
assert response.status_code == 200, response.text
|
|
45
|
+
assert response.json()['contact_id'] != owner.contact_id
|
|
46
|
+
assert response.json()['interaction_allowed'] is False
|
|
47
|
+
finally:
|
|
48
|
+
await store.close()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|