apsimo 1.3.0__py3-none-any.whl
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/__init__.py +38 -0
- apsimo/__main__.py +6 -0
- apsimo/agent/__init__.py +6 -0
- apsimo/agent/client.py +276 -0
- apsimo/agent/models.py +46 -0
- apsimo/agents/__init__.py +20 -0
- apsimo/agents/models.py +264 -0
- apsimo/agents/store.py +861 -0
- apsimo/agents/websocket.py +522 -0
- apsimo/api/__init__.py +1 -0
- apsimo/api/auth_telemetry.py +287 -0
- apsimo/api/authority.py +1203 -0
- apsimo/api/contact_grants.py +347 -0
- apsimo/api/middleware.py +483 -0
- apsimo/api/routers/__init__.py +1 -0
- apsimo/api/routers/commitment_work.py +265 -0
- apsimo/api/routers/context_gate.py +123 -0
- apsimo/api/routers/executions.py +140 -0
- apsimo/api/routers/followup_plans.py +147 -0
- apsimo/api/routers/governed_actions.py +162 -0
- apsimo/api/routers/host.py +14473 -0
- apsimo/api/routers/initiative_work.py +115 -0
- apsimo/api/routers/mining.py +104 -0
- apsimo/api/routers/observations.py +110 -0
- apsimo/api/routers/social_state.py +225 -0
- apsimo/api/routers/task_queue.py +2715 -0
- apsimo/api/routers/temporal_followups.py +251 -0
- apsimo/api/routers/transport.py +110 -0
- apsimo/api/routers/transport_ingress_api.py +240 -0
- apsimo/api/schemas/__init__.py +1 -0
- apsimo/api/schemas/host.py +1949 -0
- apsimo/autonomy/cli.py +110 -0
- apsimo/autonomy/condition_worker.py +437 -0
- apsimo/autonomy/config.py +424 -0
- apsimo/autonomy/loop.py +4316 -0
- apsimo/autonomy/registry.py +339 -0
- apsimo/autonomy/scheduler.py +1822 -0
- apsimo/autonomy/synthesis.py +449 -0
- apsimo/backup.py +962 -0
- apsimo/beliefs/__init__.py +23 -0
- apsimo/beliefs/contradictions.py +109 -0
- apsimo/beliefs/decay.py +61 -0
- apsimo/beliefs/engine.py +479 -0
- apsimo/beliefs/models.py +67 -0
- apsimo/beliefs/promotion.py +41 -0
- apsimo/beliefs/resolve.py +58 -0
- apsimo/beliefs/source_claims.py +690 -0
- apsimo/beliefs/source_projection.py +883 -0
- apsimo/beliefs/source_time.py +208 -0
- apsimo/beliefs/store.py +133 -0
- apsimo/briefings/aggregators.py +824 -0
- apsimo/briefings/composer.py +420 -0
- apsimo/briefings/config.py +55 -0
- apsimo/briefings/delivery.py +439 -0
- apsimo/briefings/engagement.py +97 -0
- apsimo/briefings/engine.py +274 -0
- apsimo/briefings/enhancer.py +99 -0
- apsimo/briefings/models.py +183 -0
- apsimo/briefings/scheduler.py +382 -0
- apsimo/briefings/store.py +435 -0
- apsimo/chain/__init__.py +48 -0
- apsimo/chain/block.py +100 -0
- apsimo/chain/cli.py +704 -0
- apsimo/chain/genesis.py +443 -0
- apsimo/chain/identity.py +416 -0
- apsimo/chain/keys.py +1025 -0
- apsimo/chain/local_keys.py +187 -0
- apsimo/chain/manager.py +290 -0
- apsimo/chain/node.py +163 -0
- apsimo/chain/plugin_transactions.py +371 -0
- apsimo/chain/protocol.py +220 -0
- apsimo/chain/state_machine.py +676 -0
- apsimo/chain/storage.py +503 -0
- apsimo/chain/transactions.py +250 -0
- apsimo/chain/validation.py +397 -0
- apsimo/channels/__init__.py +1 -0
- apsimo/channels/manifest.py +31 -0
- apsimo/channels/migrations/001_channels_schema.sql +12 -0
- apsimo/channels/phone_gateways.py +42 -0
- apsimo/channels/presence.py +188 -0
- apsimo/channels/router.py +235 -0
- apsimo/channels/store.py +231 -0
- apsimo/cli.py +2688 -0
- apsimo/cognition/__init__.py +11 -0
- apsimo/cognition/charter.py +398 -0
- apsimo/cognition/drive_governance.py +3530 -0
- apsimo/cognition/evidence_pipeline.py +1627 -0
- apsimo/cognition/external_events.py +932 -0
- apsimo/cognition/goal_spine.py +3488 -0
- apsimo/cognition/introspection.py +214 -0
- apsimo/cognition/prompt.py +150 -0
- apsimo/cognition/runtime.py +108 -0
- apsimo/cognition/trigger.py +154 -0
- apsimo/commitments/__init__.py +18 -0
- apsimo/commitments/local_work.py +355 -0
- apsimo/commitments/store.py +1052 -0
- apsimo/commitments/work.py +91 -0
- apsimo/compat.py +53 -0
- apsimo/compression/__init__.py +467 -0
- apsimo/connectors/__init__.py +21 -0
- apsimo/connectors/base.py +152 -0
- apsimo/connectors/caldav_calendar.py +125 -0
- apsimo/connectors/fs_documents.py +85 -0
- apsimo/connectors/imap_email.py +138 -0
- apsimo/connectors/manager.py +218 -0
- apsimo/connectors/webhook_pull.py +88 -0
- apsimo/contacts/__init__.py +33 -0
- apsimo/contacts/comms.py +357 -0
- apsimo/contacts/config.py +79 -0
- apsimo/contacts/exporters/__init__.py +1 -0
- apsimo/contacts/exporters/vcard.py +71 -0
- apsimo/contacts/identity_links.py +251 -0
- apsimo/contacts/importer.py +280 -0
- apsimo/contacts/importers/__init__.py +1 -0
- apsimo/contacts/importers/batch.py +43 -0
- apsimo/contacts/importers/macos_contacts.py +101 -0
- apsimo/contacts/migrations/001_contacts_schema.sql +141 -0
- apsimo/contacts/migrations/002_trust_scopes.sql +36 -0
- apsimo/contacts/migrations/003_open_gateway_enum.sql +32 -0
- apsimo/contacts/migrations/004_contact_provision_operations.sql +18 -0
- apsimo/contacts/migrations/005_identity_links.sql +27 -0
- apsimo/contacts/models.py +308 -0
- apsimo/contacts/scoring.py +16 -0
- apsimo/contacts/store.py +1623 -0
- apsimo/contacts/transport_ingress.py +252 -0
- apsimo/contacts/world_bridge.py +314 -0
- apsimo/contextgate/__init__.py +69 -0
- apsimo/contextgate/chunker.py +169 -0
- apsimo/contextgate/estimate.py +54 -0
- apsimo/contextgate/gate.py +313 -0
- apsimo/contextgate/retrieve.py +115 -0
- apsimo/delivery/__init__.py +16 -0
- apsimo/delivery/bridge.py +1260 -0
- apsimo/delivery/channels.py +526 -0
- apsimo/delivery/classification.py +50 -0
- apsimo/delivery/rate_limiter.py +268 -0
- apsimo/delivery/reachout_policy.py +206 -0
- apsimo/directed/__init__.py +22 -0
- apsimo/directed/audit.py +167 -0
- apsimo/directed/intake.py +95 -0
- apsimo/directed/models.py +191 -0
- apsimo/directed/service.py +509 -0
- apsimo/directives/__init__.py +25 -0
- apsimo/directives/evidence.py +87 -0
- apsimo/directives/extractor.py +188 -0
- apsimo/directives/guard.py +364 -0
- apsimo/directives/models.py +206 -0
- apsimo/directives/service.py +372 -0
- apsimo/directives/store.py +167 -0
- apsimo/doctor.py +2173 -0
- apsimo/environment.py +43 -0
- apsimo/events/__init__.py +33 -0
- apsimo/events/broadcaster.py +98 -0
- apsimo/events/bus.py +217 -0
- apsimo/events/journal.py +863 -0
- apsimo/events/stream.py +131 -0
- apsimo/events/types.py +150 -0
- apsimo/execution_results.py +357 -0
- apsimo/feedback/__init__.py +5 -0
- apsimo/feedback/store.py +76 -0
- apsimo/feeds/__init__.py +19 -0
- apsimo/feeds/cli.py +84 -0
- apsimo/feeds/engine.py +437 -0
- apsimo/feeds/example-feed.yaml +77 -0
- apsimo/feeds/hermes_cron.py +126 -0
- apsimo/feeds/manager.py +235 -0
- apsimo/feeds/spec.py +250 -0
- apsimo/feeds/template.py +202 -0
- apsimo/gate/__init__.py +18 -0
- apsimo/gate/audit.py +61 -0
- apsimo/gate/communication_policy.py +166 -0
- apsimo/gate/config.py +72 -0
- apsimo/gate/context_provenance.py +170 -0
- apsimo/gate/env_risk.py +226 -0
- apsimo/gate/guard_audit.py +353 -0
- apsimo/gate/layers/__init__.py +1 -0
- apsimo/gate/layers/base.py +15 -0
- apsimo/gate/layers/l1_recipient.py +66 -0
- apsimo/gate/layers/l2_pii.py +134 -0
- apsimo/gate/layers/l3_cross_context.py +50 -0
- apsimo/gate/layers/l4_trust_tier.py +78 -0
- apsimo/gate/layers/l5_injection.py +199 -0
- apsimo/gate/layers/l6_review.py +86 -0
- apsimo/gate/layers/l7_delay.py +100 -0
- apsimo/gate/layers/tom2_epistemic.py +185 -0
- apsimo/gate/models.py +64 -0
- apsimo/gate/pending_dispatch.py +5 -0
- apsimo/gate/pipeline.py +206 -0
- apsimo/gate/rejection.py +259 -0
- apsimo/gate/response_guard.py +700 -0
- apsimo/gate/rulesets/injection_v1.yaml +51 -0
- apsimo/gate/surface_policy.py +189 -0
- apsimo/gate/taint.py +226 -0
- apsimo/genesis.json +9 -0
- apsimo/goals/__init__.py +100 -0
- apsimo/goals/config.py +38 -0
- apsimo/goals/decomposer.py +421 -0
- apsimo/goals/engine.py +617 -0
- apsimo/goals/inference.py +354 -0
- apsimo/goals/models.py +302 -0
- apsimo/goals/priority.py +270 -0
- apsimo/goals/queue_bridge.py +149 -0
- apsimo/goals/replan.py +450 -0
- apsimo/goals/schema.sql +89 -0
- apsimo/goals/store.py +692 -0
- apsimo/governed_actions.py +1708 -0
- apsimo/harness_integration/__init__.py +45 -0
- apsimo/harness_integration/context.py +41 -0
- apsimo/harness_integration/skills.py +231 -0
- apsimo/identity/__init__.py +26 -0
- apsimo/identity/participants.py +181 -0
- apsimo/identity/resolver.py +329 -0
- apsimo/identity_bootstrap/__init__.py +5 -0
- apsimo/identity_bootstrap/builder.py +208 -0
- apsimo/identity_bootstrap/corpus.py +443 -0
- apsimo/identity_bootstrap/models.py +54 -0
- apsimo/identity_bootstrap/runner.py +353 -0
- apsimo/identity_bootstrap/seeders/__init__.py +25 -0
- apsimo/identity_bootstrap/seeders/briefings.py +109 -0
- apsimo/identity_bootstrap/seeders/chain.py +57 -0
- apsimo/identity_bootstrap/seeders/goals.py +128 -0
- apsimo/identity_bootstrap/seeders/memory.py +191 -0
- apsimo/identity_bootstrap/seeders/neo4j_cognition.py +79 -0
- apsimo/identity_bootstrap/seeders/relationship.py +152 -0
- apsimo/identity_bootstrap/seeders/sessions.py +67 -0
- apsimo/identity_bootstrap/seeders/skills.py +92 -0
- apsimo/identity_bootstrap/seeders/task_queue.py +72 -0
- apsimo/identity_bootstrap/seeders/world_model.py +143 -0
- apsimo/identity_bootstrap/self_query.py +92 -0
- apsimo/identity_bootstrap/self_reflection.py +155 -0
- apsimo/identity_bootstrap/skill.py +37 -0
- apsimo/identity_bootstrap/verifier.py +436 -0
- apsimo/initiatives/__init__.py +20 -0
- apsimo/initiatives/action_registry.py +454 -0
- apsimo/initiatives/approval_authority.py +2105 -0
- apsimo/initiatives/approval_policy.py +123 -0
- apsimo/initiatives/assignment.py +263 -0
- apsimo/initiatives/backup_evidence.py +100 -0
- apsimo/initiatives/context_freshness.py +103 -0
- apsimo/initiatives/models.py +318 -0
- apsimo/initiatives/native_work.py +270 -0
- apsimo/initiatives/standing_approvals.py +232 -0
- apsimo/initiatives/store.py +1081 -0
- apsimo/initiatives/temporal_followup.py +410 -0
- apsimo/intelligence/__init__.py +1 -0
- apsimo/intelligence/cognition/__init__.py +24 -0
- apsimo/intelligence/cognition/gap_detector.py +148 -0
- apsimo/intelligence/cognition/metalearner.py +547 -0
- apsimo/intelligence/cognition/metrics_collector.py +217 -0
- apsimo/intelligence/cognition/performance_index.py +299 -0
- apsimo/intelligence/cognition/registry.py +192 -0
- apsimo/intelligence/cognition/strategy_adjuster.py +222 -0
- apsimo/intelligence/cognition/types.py +16 -0
- apsimo/intelligence/components/__init__.py +66 -0
- apsimo/intelligence/components/anomaly_detector.py +413 -0
- apsimo/intelligence/components/initiative_engine.py +2643 -0
- apsimo/intelligence/components/preference_learner.py +521 -0
- apsimo/intelligence/components/research_orchestrator.py +358 -0
- apsimo/intelligence/components/self_directed_thinker.py +221 -0
- apsimo/intelligence/components/self_reflector.py +252 -0
- apsimo/intelligence/components/session_continuity.py +154 -0
- apsimo/intelligence/components/task_planner.py +320 -0
- apsimo/intelligence/components/tool_learner.py +217 -0
- apsimo/intelligence/graph/__init__.py +79 -0
- apsimo/intelligence/graph/client.py +2483 -0
- apsimo/intelligence/graph/consolidator.py +405 -0
- apsimo/intelligence/graph/distiller.py +312 -0
- apsimo/intelligence/graph/migrations.py +129 -0
- apsimo/intelligence/graph/queries.py +248 -0
- apsimo/intelligence/graph/recall.py +281 -0
- apsimo/intelligence/graph/reconciler.py +144 -0
- apsimo/intelligence/graph/schema.py +337 -0
- apsimo/intelligence/graph/selection.py +252 -0
- apsimo/intelligence/learning/__init__.py +17 -0
- apsimo/intelligence/learning/continuous_learner.py +245 -0
- apsimo/intelligence/learning/feedback_store.py +321 -0
- apsimo/intelligence/mind_model/__init__.py +1 -0
- apsimo/intelligence/mind_model/graph_baseline.py +136 -0
- apsimo/intelligence/mind_model/signal_collector.py +361 -0
- apsimo/intelligence/relationships/__init__.py +11 -0
- apsimo/intelligence/relationships/profiler.py +389 -0
- apsimo/intelligence/relationships/scorer.py +560 -0
- apsimo/intelligence/relationships/signal_floor.py +66 -0
- apsimo/intelligence/relationships/trust_tiers.py +300 -0
- apsimo/intelligence/synthesis/__init__.py +40 -0
- apsimo/intelligence/synthesis/connection_discoverer.py +379 -0
- apsimo/intelligence/synthesis/cross_domain_analyzer.py +287 -0
- apsimo/intelligence/synthesis/insight_deliverer.py +171 -0
- apsimo/intelligence/synthesis/insight_store.py +79 -0
- apsimo/intelligence/synthesis/insight_validator.py +183 -0
- apsimo/intelligence/synthesis/novelty_scorer.py +267 -0
- apsimo/intelligence/turn_middleware/__init__.py +15 -0
- apsimo/intelligence/turn_middleware/memory_sync.py +119 -0
- apsimo/mcp/__init__.py +41 -0
- apsimo/mcp/__main__.py +6 -0
- apsimo/mcp/config.py +287 -0
- apsimo/mcp/server.py +501 -0
- apsimo/migrations.py +187 -0
- apsimo/mining/__init__.py +27 -0
- apsimo/mining/corpus.py +239 -0
- apsimo/mining/escalations.py +289 -0
- apsimo/mining/models.py +169 -0
- apsimo/mining/store.py +210 -0
- apsimo/models/__init__.py +30 -0
- apsimo/models/memory.py +80 -0
- apsimo/models/mesh.py +72 -0
- apsimo/models/person.py +104 -0
- apsimo/models/signal.py +108 -0
- apsimo/observations/__init__.py +15 -0
- apsimo/observations/store.py +277 -0
- apsimo/patterns/__init__.py +6 -0
- apsimo/patterns/extract.py +187 -0
- apsimo/patterns/store.py +227 -0
- apsimo/persona/__init__.py +1 -0
- apsimo/persona/engine.py +611 -0
- apsimo/persona/manifest.py +140 -0
- apsimo/projects/__init__.py +28 -0
- apsimo/projects/engine.py +1681 -0
- apsimo/projects/event_outbox.py +188 -0
- apsimo/projects/models.py +216 -0
- apsimo/projects/planner.py +181 -0
- apsimo/projects/store.py +1446 -0
- apsimo/proposals/__init__.py +12 -0
- apsimo/proposals/engine.py +114 -0
- apsimo/proposals/models.py +207 -0
- apsimo/qualification/__init__.py +1 -0
- apsimo/qualification/cases.py +75 -0
- apsimo/qualification/cli.py +51 -0
- apsimo/qualification/memory_cases.py +209 -0
- apsimo/qualification/records.py +92 -0
- apsimo/qualification/report.py +87 -0
- apsimo/qualification/runner.py +311 -0
- apsimo/qualification/structured_cases.py +131 -0
- apsimo/reasoning/__init__.py +13 -0
- apsimo/reasoning/executor.py +506 -0
- apsimo/reasoning/loop.py +373 -0
- apsimo/reasoning/native_tools/__init__.py +16 -0
- apsimo/reasoning/native_tools/calculate.py +141 -0
- apsimo/reasoning/native_tools/file_ops.py +150 -0
- apsimo/reasoning/native_tools/web_search.py +49 -0
- apsimo/reasoning/tool_policy.py +182 -0
- apsimo/redact/__init__.py +176 -0
- apsimo/repos/__init__.py +5 -0
- apsimo/repos/mirrors.py +204 -0
- apsimo/research/__init__.py +41 -0
- apsimo/research/artifact.py +482 -0
- apsimo/research/gatherer.py +387 -0
- apsimo/research/pipeline.py +513 -0
- apsimo/research/search/__init__.py +7 -0
- apsimo/research/search/base.py +41 -0
- apsimo/research/search/brave.py +59 -0
- apsimo/research/search/cache.py +51 -0
- apsimo/research/search/duckduckgo.py +103 -0
- apsimo/research/search/orchestrator.py +119 -0
- apsimo/research/search/serpapi.py +59 -0
- apsimo/research/search/tavily.py +59 -0
- apsimo/research/synthesizer.py +309 -0
- apsimo/router/__init__.py +30 -0
- apsimo/router/complexity_scorer.py +148 -0
- apsimo/router/endpoints.py +153 -0
- apsimo/router/fallback.py +58 -0
- apsimo/router/functions.py +243 -0
- apsimo/router/native_policy.py +52 -0
- apsimo/router/router.py +762 -0
- apsimo/router/self_learning.py +174 -0
- apsimo/router/tiers.py +677 -0
- apsimo/sandbox/__init__.py +21 -0
- apsimo/sandbox/backend.py +195 -0
- apsimo/sandbox/manager.py +173 -0
- apsimo/scope_bounds.py +7 -0
- apsimo/secrets/__init__.py +6 -0
- apsimo/secrets/backends/__init__.py +8 -0
- apsimo/secrets/backends/base.py +42 -0
- apsimo/secrets/backends/env.py +110 -0
- apsimo/secrets/backends/keyring.py +72 -0
- apsimo/secrets/backends/onepassword.py +232 -0
- apsimo/secrets/cli.py +191 -0
- apsimo/secrets/manager.py +160 -0
- apsimo/secrets/migration.py +101 -0
- apsimo/secrets/types.py +98 -0
- apsimo/seed.py +41 -0
- apsimo/self_model/__init__.py +37 -0
- apsimo/self_model/appraisals.py +673 -0
- apsimo/self_model/benchmark.py +1314 -0
- apsimo/self_model/brief.py +40 -0
- apsimo/self_model/event_concerns.py +1128 -0
- apsimo/self_model/execution_forecasts.py +353 -0
- apsimo/self_model/expectations.py +1595 -0
- apsimo/self_model/experiments.py +1150 -0
- apsimo/self_model/journal.py +148 -0
- apsimo/self_model/judgments.py +705 -0
- apsimo/self_model/native_outcomes.py +55 -0
- apsimo/self_model/params.py +220 -0
- apsimo/self_model/perspective.py +246 -0
- apsimo/self_model/reconcile.py +183 -0
- apsimo/self_model/reply_forecasts.py +381 -0
- apsimo/self_model/runtime_forecasts.py +296 -0
- apsimo/self_model/runtime_models.py +67 -0
- apsimo/self_model/settlement.py +207 -0
- apsimo/self_model/situation.py +1731 -0
- apsimo/self_model/store.py +883 -0
- apsimo/self_model/supervised.py +137 -0
- apsimo/self_model/thinker.py +99 -0
- apsimo/self_model/trust.py +388 -0
- apsimo/self_model/workspace.py +2388 -0
- apsimo/server.py +4197 -0
- apsimo/services/__init__.py +1 -0
- apsimo/services/agent_bridge.py +474 -0
- apsimo/services/initiative_executor.py +914 -0
- apsimo/services/instance.py +297 -0
- apsimo/sessions/__init__.py +22 -0
- apsimo/sessions/config.py +13 -0
- apsimo/sessions/context_loader.py +88 -0
- apsimo/sessions/federation_session.py +75 -0
- apsimo/sessions/isolated_session.py +98 -0
- apsimo/sessions/reports.py +84 -0
- apsimo/sessions/store.py +148 -0
- apsimo/setup.py +2818 -0
- apsimo/setup_hermes.py +879 -0
- apsimo/setup_local_work.py +218 -0
- apsimo/setup_native_goals.py +134 -0
- apsimo/setup_native_reviews.py +115 -0
- apsimo/skills/__init__.py +10 -0
- apsimo/skills/base.py +108 -0
- apsimo/skills/budget.py +28 -0
- apsimo/skills/executor.py +493 -0
- apsimo/skills/executors/__init__.py +1 -0
- apsimo/skills/executors/behavioral_correction.py +75 -0
- apsimo/skills/executors/capability_gap.py +38 -0
- apsimo/skills/executors/data_quality.py +163 -0
- apsimo/skills/executors/knowledge_acquisition.py +41 -0
- apsimo/skills/executors/operational_hygiene.py +185 -0
- apsimo/skills/executors/subsystem_health.py +169 -0
- apsimo/skills/hermes_export.py +431 -0
- apsimo/skills/index.py +123 -0
- apsimo/skills/learning/__init__.py +21 -0
- apsimo/skills/learning/novelty_detector.py +206 -0
- apsimo/skills/learning/pattern_extractor.py +199 -0
- apsimo/skills/learning/triggers.py +159 -0
- apsimo/skills/loader.py +246 -0
- apsimo/skills/migrations/002_progressive_loading.sql +6 -0
- apsimo/skills/migrations/backfill_triggers.py +20 -0
- apsimo/skills/models.py +202 -0
- apsimo/skills/packager.py +128 -0
- apsimo/skills/protocols.py +70 -0
- apsimo/skills/registry.py +191 -0
- apsimo/skills/runtime.py +58 -0
- apsimo/skills/sandbox_runner.py +229 -0
- apsimo/skills/scheduler.py +129 -0
- apsimo/skills/schema.py +79 -0
- apsimo/skills/security/__init__.py +12 -0
- apsimo/skills/security/guards.py +53 -0
- apsimo/skills/security/scanner.py +223 -0
- apsimo/skills_memory/__init__.py +26 -0
- apsimo/skills_memory/distill.py +159 -0
- apsimo/skills_memory/models.py +85 -0
- apsimo/skills_memory/retrieve.py +62 -0
- apsimo/skills_memory/store.py +172 -0
- apsimo/surprise/__init__.py +6 -0
- apsimo/surprise/accumulation.py +57 -0
- apsimo/surprise/scorer.py +102 -0
- apsimo/surprise/store.py +203 -0
- apsimo/task_queue/__init__.py +69 -0
- apsimo/task_queue/action_receipts.py +148 -0
- apsimo/task_queue/approval_relay_canary.py +108 -0
- apsimo/task_queue/config.py +85 -0
- apsimo/task_queue/contract.py +361 -0
- apsimo/task_queue/events.py +130 -0
- apsimo/task_queue/governor.py +1031 -0
- apsimo/task_queue/handlers/__init__.py +16 -0
- apsimo/task_queue/handlers/base.py +37 -0
- apsimo/task_queue/handlers/inference.py +640 -0
- apsimo/task_queue/handlers/monitoring.py +116 -0
- apsimo/task_queue/handlers/registry.py +75 -0
- apsimo/task_queue/handlers/subtask_handler.py +173 -0
- apsimo/task_queue/handlers/system_maintenance.py +147 -0
- apsimo/task_queue/mesh_integration.py +111 -0
- apsimo/task_queue/models.py +317 -0
- apsimo/task_queue/queue_manager.py +8286 -0
- apsimo/task_queue/routing.py +287 -0
- apsimo/task_queue/scheduler.py +252 -0
- apsimo/task_queue/schema.sql +197 -0
- apsimo/task_queue/work_control.py +342 -0
- apsimo/task_queue/worker.py +993 -0
- apsimo/telemetry.py +145 -0
- apsimo/tom/__init__.py +6 -0
- apsimo/tom/affect.py +387 -0
- apsimo/tom/approvals.py +171 -0
- apsimo/tom/arcs.py +896 -0
- apsimo/tom/asymmetry.py +131 -0
- apsimo/tom/eligibility.py +248 -0
- apsimo/tom/engagement.py +214 -0
- apsimo/tom/exposure.py +214 -0
- apsimo/tom/extractor.py +306 -0
- apsimo/tom/fact_adapters.py +144 -0
- apsimo/tom/facts.py +326 -0
- apsimo/tom/integration.py +592 -0
- apsimo/tom/leveled.py +118 -0
- apsimo/tom/levels.py +247 -0
- apsimo/tom/recipient_audit.py +995 -0
- apsimo/tom/recipient_simulator.py +593 -0
- apsimo/tom/source_lineage.py +93 -0
- apsimo/tom/tom2.py +277 -0
- apsimo/tom/visibility.py +559 -0
- apsimo/tom/visibility_store.py +414 -0
- apsimo/tools/__init__.py +0 -0
- apsimo/tools/definitions.py +740 -0
- apsimo/tools/handlers.py +943 -0
- apsimo/toolsmith/__init__.py +26 -0
- apsimo/toolsmith/authority.py +166 -0
- apsimo/toolsmith/engine.py +559 -0
- apsimo/toolsmith/integrity.py +100 -0
- apsimo/toolsmith/miner.py +145 -0
- apsimo/toolsmith/policy.py +110 -0
- apsimo/toolsmith/registry.py +635 -0
- apsimo/turns/__init__.py +17 -0
- apsimo/turns/audio.py +134 -0
- apsimo/turns/documents.py +235 -0
- apsimo/turns/executions.py +486 -0
- apsimo/turns/hermes_history.py +245 -0
- apsimo/turns/hermes_kanban.py +268 -0
- apsimo/turns/hermes_work.py +96 -0
- apsimo/turns/idempotency.py +752 -0
- apsimo/turns/local_work.py +115 -0
- apsimo/turns/media.py +581 -0
- apsimo/turns/reported_workers.py +196 -0
- apsimo/turns/source_annotations.py +283 -0
- apsimo/turns/source_attribution.py +154 -0
- apsimo/turns/source_read.py +351 -0
- apsimo/turns/source_vectors.py +263 -0
- apsimo/turns/video.py +210 -0
- apsimo/util/autonomy_preset.py +220 -0
- apsimo/util/instance.py +92 -0
- apsimo/util/model_output.py +25 -0
- apsimo/util/quiet_hours.py +27 -0
- apsimo/util/session_safety.py +37 -0
- apsimo/util/temporal.py +343 -0
- apsimo/vector/__init__.py +75 -0
- apsimo/vector/backfill.py +171 -0
- apsimo/vector/caption.py +114 -0
- apsimo/vector/collections.py +51 -0
- apsimo/vector/config.py +102 -0
- apsimo/vector/embedder.py +670 -0
- apsimo/vector/image_preprocess.py +406 -0
- apsimo/vector/image_store.py +296 -0
- apsimo/vector/indexes.py +162 -0
- apsimo/vector/migrate.py +334 -0
- apsimo/vector/multimodal_provider.py +417 -0
- apsimo/vector/multimodal_types.py +87 -0
- apsimo/vector/openai_provider.py +119 -0
- apsimo/vector/query.py +49 -0
- apsimo/vector/reranker.py +565 -0
- apsimo/vector/safety_image.py +159 -0
- apsimo/vector/scanner.py +197 -0
- apsimo/vector/setup.py +289 -0
- apsimo/vector/store.py +533 -0
- apsimo/vector/tiers.py +263 -0
- apsimo/work_orders.py +925 -0
- apsimo/workers/__init__.py +21 -0
- apsimo/workers/agent_bridge.py +640 -0
- apsimo/workers/colony_worker.py +382 -0
- apsimo/workers/queue_worker.py +441 -0
- apsimo/workers/skills_sync.py +152 -0
- apsimo/world_model/__init__.py +71 -0
- apsimo/world_model/causal_maintenance.py +131 -0
- apsimo/world_model/causal_policy.py +43 -0
- apsimo/world_model/causal_query.py +125 -0
- apsimo/world_model/confidence.py +54 -0
- apsimo/world_model/config.py +64 -0
- apsimo/world_model/constants.py +97 -0
- apsimo/world_model/entities.py +145 -0
- apsimo/world_model/expectation_resolvers.py +177 -0
- apsimo/world_model/extraction/__init__.py +7 -0
- apsimo/world_model/extraction/base.py +62 -0
- apsimo/world_model/extraction/conversation_extractor.py +262 -0
- apsimo/world_model/extraction/detector.py +74 -0
- apsimo/world_model/extraction/document_extractor.py +78 -0
- apsimo/world_model/extraction/formats/__init__.py +24 -0
- apsimo/world_model/extraction/formats/csv_fmt.py +68 -0
- apsimo/world_model/extraction/formats/html_fmt.py +72 -0
- apsimo/world_model/extraction/formats/json_fmt.py +68 -0
- apsimo/world_model/extraction/formats/pdf.py +43 -0
- apsimo/world_model/extraction/formats/text.py +27 -0
- apsimo/world_model/extraction/llm_extractor.py +164 -0
- apsimo/world_model/extraction/pipeline.py +73 -0
- apsimo/world_model/integrations/__init__.py +5 -0
- apsimo/world_model/integrations/mind_model_bridge.py +115 -0
- apsimo/world_model/integrations/social_intel_bridge.py +120 -0
- apsimo/world_model/jobs/__init__.py +4 -0
- apsimo/world_model/jobs/extraction_job.py +168 -0
- apsimo/world_model/llm_extract.py +572 -0
- apsimo/world_model/neo4j/__init__.py +5 -0
- apsimo/world_model/neo4j/backend.py +654 -0
- apsimo/world_model/observations.py +155 -0
- apsimo/world_model/populator.py +307 -0
- apsimo/world_model/postgres/__init__.py +1 -0
- apsimo/world_model/postgres/backend.py +683 -0
- apsimo/world_model/relationships.py +25 -0
- apsimo/world_model/resolution/__init__.py +13 -0
- apsimo/world_model/resolution/entity_resolver.py +232 -0
- apsimo/world_model/resolution/merge_audit.py +16 -0
- apsimo/world_model/resolution/merge_workflow.py +117 -0
- apsimo/world_model/source_reports.py +121 -0
- apsimo/world_model/sqlite/__init__.py +4 -0
- apsimo/world_model/sqlite/backend.py +855 -0
- apsimo/world_model/sqlite/schema.sql +132 -0
- apsimo/world_model/store.py +545 -0
- apsimo-1.3.0.dist-info/METADATA +78 -0
- apsimo-1.3.0.dist-info/RECORD +614 -0
- apsimo-1.3.0.dist-info/WHEEL +5 -0
- apsimo-1.3.0.dist-info/entry_points.txt +11 -0
- apsimo-1.3.0.dist-info/licenses/LICENSE +21 -0
- apsimo-1.3.0.dist-info/top_level.txt +2 -0
- colony_sidecar/__init__.py +4 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
-- colony/contacts/migrations/001_contacts_schema.sql
|
|
2
|
+
|
|
3
|
+
-- ─── Contacts ────────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
CREATE TABLE IF NOT EXISTS contacts (
|
|
6
|
+
contact_id TEXT PRIMARY KEY, -- cid-<timestamp_ms>-<random7>
|
|
7
|
+
display_name TEXT,
|
|
8
|
+
given_name TEXT,
|
|
9
|
+
family_name TEXT,
|
|
10
|
+
organization TEXT,
|
|
11
|
+
relationship_score REAL NOT NULL DEFAULT 0.0
|
|
12
|
+
CHECK(relationship_score >= 0.0 AND relationship_score <= 1.0),
|
|
13
|
+
trust_tier TEXT NOT NULL DEFAULT 'unknown'
|
|
14
|
+
CHECK(trust_tier IN ('inner_circle','trusted','regular',
|
|
15
|
+
'peripheral','silenced','acquaintance','unknown')),
|
|
16
|
+
interaction_allowed INTEGER NOT NULL DEFAULT 1
|
|
17
|
+
CHECK(interaction_allowed IN (0,1)),
|
|
18
|
+
tags_json TEXT NOT NULL DEFAULT '[]', -- JSON array of strings
|
|
19
|
+
privacy_level TEXT NOT NULL DEFAULT 'private'
|
|
20
|
+
CHECK(privacy_level IN ('public','private','restricted')),
|
|
21
|
+
person_node_id TEXT,
|
|
22
|
+
notes TEXT,
|
|
23
|
+
import_source TEXT NOT NULL DEFAULT 'manual',
|
|
24
|
+
first_seen_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
|
|
25
|
+
last_interaction_at TEXT,
|
|
26
|
+
interaction_count INTEGER NOT NULL DEFAULT 0,
|
|
27
|
+
enrichment_source TEXT NOT NULL DEFAULT '[]', -- JSON array
|
|
28
|
+
enrichment_last_at TEXT,
|
|
29
|
+
deleted_at TEXT, -- NULL until soft-deleted
|
|
30
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
|
|
31
|
+
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
|
|
32
|
+
timezone TEXT -- IANA tz for this contact (v0.21.0), editable
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_contacts_tier
|
|
36
|
+
ON contacts(trust_tier) WHERE deleted_at IS NULL;
|
|
37
|
+
|
|
38
|
+
CREATE INDEX IF NOT EXISTS idx_contacts_person_node
|
|
39
|
+
ON contacts(person_node_id) WHERE person_node_id IS NOT NULL;
|
|
40
|
+
|
|
41
|
+
-- ─── Contact Handles ─────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
CREATE TABLE IF NOT EXISTS contact_handles (
|
|
44
|
+
handle_id TEXT PRIMARY KEY, -- hdl-<timestamp_ms>-<random7>
|
|
45
|
+
contact_id TEXT NOT NULL REFERENCES contacts(contact_id) ON DELETE CASCADE,
|
|
46
|
+
-- Keep in sync with the delivery channel set (delivery/channels.py):
|
|
47
|
+
-- whatsapp/discord/slack were deliverable but unstorable before v0.17.
|
|
48
|
+
gateway TEXT NOT NULL
|
|
49
|
+
CHECK(gateway IN ('imessage','telegram','whatsapp','discord',
|
|
50
|
+
'slack','email','sms','signal','custom')),
|
|
51
|
+
address TEXT NOT NULL,
|
|
52
|
+
is_primary INTEGER NOT NULL DEFAULT 0
|
|
53
|
+
CHECK(is_primary IN (0,1)),
|
|
54
|
+
verified INTEGER NOT NULL DEFAULT 0
|
|
55
|
+
CHECK(verified IN (0,1)),
|
|
56
|
+
confidence REAL NOT NULL DEFAULT 1.0
|
|
57
|
+
CHECK(confidence >= 0.0 AND confidence <= 1.0),
|
|
58
|
+
source TEXT NOT NULL DEFAULT 'manual',
|
|
59
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
|
|
60
|
+
UNIQUE(gateway, address)
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
CREATE INDEX IF NOT EXISTS idx_handles_contact
|
|
64
|
+
ON contact_handles(contact_id);
|
|
65
|
+
|
|
66
|
+
CREATE INDEX IF NOT EXISTS idx_handles_gateway_address
|
|
67
|
+
ON contact_handles(gateway, address);
|
|
68
|
+
|
|
69
|
+
-- ─── Contact Audit ────────────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
CREATE TABLE IF NOT EXISTS contact_audit (
|
|
72
|
+
id TEXT PRIMARY KEY, -- cau-<timestamp_ms>-<random7>
|
|
73
|
+
contact_id TEXT NOT NULL,
|
|
74
|
+
action TEXT NOT NULL,
|
|
75
|
+
-- created, handle_added, tier_changed, interaction_toggled,
|
|
76
|
+
-- enriched, soft_deleted, hard_deleted, blocked, unblocked
|
|
77
|
+
detail TEXT, -- JSON object with action-specific fields
|
|
78
|
+
performed_by TEXT NOT NULL DEFAULT 'system', -- 'operator', 'system', 'auto'
|
|
79
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
CREATE INDEX IF NOT EXISTS idx_contact_audit_contact
|
|
83
|
+
ON contact_audit(contact_id, created_at DESC);
|
|
84
|
+
|
|
85
|
+
-- ─── Merge Proposals ─────────────────────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
CREATE TABLE IF NOT EXISTS contact_merge_proposals (
|
|
88
|
+
id TEXT PRIMARY KEY, -- cmp-<timestamp_ms>-<random7>
|
|
89
|
+
contact_id_a TEXT NOT NULL REFERENCES contacts(contact_id),
|
|
90
|
+
contact_id_b TEXT NOT NULL REFERENCES contacts(contact_id),
|
|
91
|
+
confidence REAL NOT NULL,
|
|
92
|
+
reason TEXT NOT NULL,
|
|
93
|
+
status TEXT NOT NULL DEFAULT 'pending'
|
|
94
|
+
CHECK(status IN ('pending','approved','rejected','auto_merged')),
|
|
95
|
+
proposed_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
|
|
96
|
+
resolved_at TEXT,
|
|
97
|
+
UNIQUE(contact_id_a, contact_id_b)
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
CREATE INDEX IF NOT EXISTS idx_merge_proposals_pending
|
|
101
|
+
ON contact_merge_proposals(status)
|
|
102
|
+
WHERE status = 'pending';
|
|
103
|
+
|
|
104
|
+
-- ─── Merge Audit ─────────────────────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
CREATE TABLE IF NOT EXISTS contact_merge_audit (
|
|
107
|
+
id TEXT PRIMARY KEY, -- cma-<timestamp_ms>-<random7>
|
|
108
|
+
canonical_id TEXT NOT NULL,
|
|
109
|
+
absorbed_id TEXT NOT NULL,
|
|
110
|
+
confidence REAL NOT NULL,
|
|
111
|
+
merge_reason TEXT NOT NULL,
|
|
112
|
+
triggered_by TEXT NOT NULL, -- 'auto' | 'manual'
|
|
113
|
+
contact_a_snapshot TEXT NOT NULL, -- JSON snapshot of canonical before merge
|
|
114
|
+
contact_b_snapshot TEXT NOT NULL, -- JSON snapshot of absorbed before merge
|
|
115
|
+
merged_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
-- ─── Blocklist ───────────────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
CREATE TABLE IF NOT EXISTS contact_blocklist (
|
|
121
|
+
contact_id TEXT PRIMARY KEY REFERENCES contacts(contact_id),
|
|
122
|
+
reason TEXT,
|
|
123
|
+
blocked_by TEXT NOT NULL DEFAULT 'operator',
|
|
124
|
+
blocked_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
|
|
125
|
+
unblocked_at TEXT
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
CREATE INDEX IF NOT EXISTS idx_blocklist_active
|
|
129
|
+
ON contact_blocklist(contact_id)
|
|
130
|
+
WHERE unblocked_at IS NULL;
|
|
131
|
+
|
|
132
|
+
-- ─── Confirmed Distinct Pairs ────────────────────────────────────────────────
|
|
133
|
+
-- Prevents re-proposing merges that have been explicitly rejected.
|
|
134
|
+
|
|
135
|
+
CREATE TABLE IF NOT EXISTS contact_confirmed_distinct (
|
|
136
|
+
id TEXT PRIMARY KEY,
|
|
137
|
+
contact_id_a TEXT NOT NULL,
|
|
138
|
+
contact_id_b TEXT NOT NULL,
|
|
139
|
+
confirmed_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
|
|
140
|
+
UNIQUE(contact_id_a, contact_id_b)
|
|
141
|
+
);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
-- 002_trust_scopes.sql — context-scoped trust (group chats, households, project rooms).
|
|
2
|
+
--
|
|
3
|
+
-- A trust_scope grants its members a tier of trust that applies ONLY inside the
|
|
4
|
+
-- scope. Membership never confers global 1:1 rights (the member's contacts row is
|
|
5
|
+
-- untouched). This is Colony's generic "trusted in this room, not in my DMs" primitive.
|
|
6
|
+
|
|
7
|
+
CREATE TABLE IF NOT EXISTS trust_scopes (
|
|
8
|
+
scope_id TEXT PRIMARY KEY, -- ts-<ts>-<rand>
|
|
9
|
+
scope_type TEXT NOT NULL DEFAULT 'group'
|
|
10
|
+
CHECK(scope_type IN ('group','household','project','event','custom')),
|
|
11
|
+
platform TEXT, -- e.g. 'rcs'; NULL for abstract scopes
|
|
12
|
+
external_id TEXT, -- platform conversation/group id
|
|
13
|
+
label TEXT,
|
|
14
|
+
granted_tier TEXT NOT NULL DEFAULT 'group_guest'
|
|
15
|
+
CHECK(granted_tier IN ('inner_circle','trusted','regular','group_guest','peripheral','silenced','acquaintance','unknown')),
|
|
16
|
+
created_by TEXT NOT NULL DEFAULT 'agent',
|
|
17
|
+
active INTEGER NOT NULL DEFAULT 1 CHECK(active IN (0,1)),
|
|
18
|
+
created_at TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now')),
|
|
19
|
+
updated_at TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now')),
|
|
20
|
+
UNIQUE(platform, external_id)
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
CREATE INDEX IF NOT EXISTS idx_trust_scopes_extid
|
|
24
|
+
ON trust_scopes(platform, external_id) WHERE active = 1;
|
|
25
|
+
|
|
26
|
+
CREATE TABLE IF NOT EXISTS scope_members (
|
|
27
|
+
scope_id TEXT NOT NULL REFERENCES trust_scopes(scope_id) ON DELETE CASCADE,
|
|
28
|
+
contact_id TEXT NOT NULL REFERENCES contacts(contact_id) ON DELETE CASCADE,
|
|
29
|
+
role TEXT NOT NULL DEFAULT 'member' CHECK(role IN ('owner','member','observer')),
|
|
30
|
+
joined_at TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ','now')),
|
|
31
|
+
left_at TEXT, -- NULL = current member
|
|
32
|
+
PRIMARY KEY (scope_id, contact_id)
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_scope_members_contact
|
|
36
|
+
ON scope_members(contact_id) WHERE left_at IS NULL;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
-- Remove the hardcoded gateway CHECK constraint from contact_handles.
|
|
2
|
+
-- SQLite has no ALTER TABLE DROP CONSTRAINT, so we rebuild the table.
|
|
3
|
+
-- All existing data is preserved; the only change is that gateway now
|
|
4
|
+
-- accepts any string, validated at the application layer.
|
|
5
|
+
|
|
6
|
+
CREATE TABLE IF NOT EXISTS contact_handles_new (
|
|
7
|
+
handle_id TEXT PRIMARY KEY,
|
|
8
|
+
contact_id TEXT NOT NULL REFERENCES contacts(contact_id) ON DELETE CASCADE,
|
|
9
|
+
gateway TEXT NOT NULL,
|
|
10
|
+
address TEXT NOT NULL,
|
|
11
|
+
is_primary INTEGER NOT NULL DEFAULT 0
|
|
12
|
+
CHECK(is_primary IN (0,1)),
|
|
13
|
+
verified INTEGER NOT NULL DEFAULT 0
|
|
14
|
+
CHECK(verified IN (0,1)),
|
|
15
|
+
confidence REAL NOT NULL DEFAULT 1.0
|
|
16
|
+
CHECK(confidence >= 0.0 AND confidence <= 1.0),
|
|
17
|
+
source TEXT NOT NULL DEFAULT 'manual',
|
|
18
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
|
|
19
|
+
UNIQUE(gateway, address)
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
INSERT OR IGNORE INTO contact_handles_new
|
|
23
|
+
SELECT handle_id, contact_id, gateway, address,
|
|
24
|
+
is_primary, verified, confidence, source, created_at
|
|
25
|
+
FROM contact_handles;
|
|
26
|
+
|
|
27
|
+
DROP TABLE IF EXISTS contact_handles;
|
|
28
|
+
|
|
29
|
+
ALTER TABLE contact_handles_new RENAME TO contact_handles;
|
|
30
|
+
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_handles_contact
|
|
32
|
+
ON contact_handles(contact_id);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
-- Durable idempotency receipts for owner-operated contact provisioning.
|
|
2
|
+
--
|
|
3
|
+
-- The contact, exact handle, audit rows, and this receipt are committed in one
|
|
4
|
+
-- SQLite transaction by SQLiteContactStore.provision_verified_handle(). A
|
|
5
|
+
-- retry after a lost response therefore returns the original result without
|
|
6
|
+
-- creating a second contact or handle.
|
|
7
|
+
|
|
8
|
+
CREATE TABLE IF NOT EXISTS contact_provision_operations (
|
|
9
|
+
operation_id TEXT PRIMARY KEY,
|
|
10
|
+
request_sha256 TEXT NOT NULL,
|
|
11
|
+
performed_by TEXT NOT NULL,
|
|
12
|
+
contact_id TEXT NOT NULL,
|
|
13
|
+
result_json TEXT NOT NULL,
|
|
14
|
+
created_at TEXT NOT NULL
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
CREATE INDEX IF NOT EXISTS idx_contact_provision_operations_contact
|
|
18
|
+
ON contact_provision_operations(contact_id, created_at DESC);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-- Candidate associations never participate in message attribution.
|
|
2
|
+
CREATE TABLE IF NOT EXISTS contact_identity_candidates (
|
|
3
|
+
candidate_id TEXT PRIMARY KEY,
|
|
4
|
+
contact_id TEXT NOT NULL REFERENCES contacts(contact_id),
|
|
5
|
+
gateway TEXT NOT NULL,
|
|
6
|
+
address TEXT NOT NULL,
|
|
7
|
+
source TEXT NOT NULL,
|
|
8
|
+
evidence_refs_json TEXT NOT NULL,
|
|
9
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','confirmed','rejected')),
|
|
10
|
+
created_at TEXT NOT NULL,
|
|
11
|
+
resolved_at TEXT,
|
|
12
|
+
UNIQUE(contact_id,gateway,address)
|
|
13
|
+
);
|
|
14
|
+
CREATE TABLE IF NOT EXISTS contact_identity_operations (
|
|
15
|
+
operation_id TEXT PRIMARY KEY,
|
|
16
|
+
request_sha256 TEXT NOT NULL,
|
|
17
|
+
result_json TEXT NOT NULL,
|
|
18
|
+
created_at TEXT NOT NULL
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
-- Retain historical name guesses as candidates rather than usable handles.
|
|
22
|
+
-- Source conversations are not moved or erased by this migration.
|
|
23
|
+
INSERT OR IGNORE INTO contact_identity_candidates
|
|
24
|
+
(candidate_id,contact_id,gateway,address,source,evidence_refs_json,created_at)
|
|
25
|
+
SELECT 'identity-candidate:' || handle_id,contact_id,gateway,address,source,'[]',created_at
|
|
26
|
+
FROM contact_handles WHERE source='auto:scoped-name' AND verified=0;
|
|
27
|
+
DELETE FROM contact_handles WHERE source='auto:scoped-name' AND verified=0;
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"""Colony Contacts — data model dataclasses."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from datetime import datetime, timezone
|
|
8
|
+
from typing import Any, Dict, List, Optional
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# ── Trust tiers ──────────────────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
# "group_guest" is a *scoped* tier: it is the trust a person is granted WITHIN a
|
|
14
|
+
# trust_scope (e.g. a group chat) — converse in-context, but no 1:1 DM rights and
|
|
15
|
+
# no proactive reach-out. A contact's global trust_tier is unaffected by it.
|
|
16
|
+
TRUST_TIERS = ("inner_circle", "trusted", "regular", "group_guest", "peripheral", "silenced", "acquaintance", "unknown")
|
|
17
|
+
|
|
18
|
+
# Higher index = more permissive
|
|
19
|
+
_TIER_RANK = {t: i for i, t in enumerate(("unknown", "acquaintance", "silenced", "peripheral", "group_guest", "regular", "trusted", "inner_circle"))}
|
|
20
|
+
|
|
21
|
+
PRIVACY_LEVELS = ("public", "private", "restricted")
|
|
22
|
+
GATEWAYS = ("imessage", "telegram", "email", "sms", "signal", "custom", "internal")
|
|
23
|
+
|
|
24
|
+
# Default interaction_allowed per trust tier (spec §8.1).
|
|
25
|
+
# group_guest is False here because that flag governs *global* (1:1) interaction;
|
|
26
|
+
# in-scope interaction is authorized by the trust_scope, not this flag.
|
|
27
|
+
TIER_DEFAULT_INTERACTION: Dict[str, bool] = {
|
|
28
|
+
"inner_circle": True,
|
|
29
|
+
"trusted": True,
|
|
30
|
+
"regular": True,
|
|
31
|
+
"group_guest": False,
|
|
32
|
+
"peripheral": False,
|
|
33
|
+
"silenced": False,
|
|
34
|
+
"acquaintance": False,
|
|
35
|
+
"unknown": True,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def more_permissive_tier(a: str, b: str) -> str:
|
|
40
|
+
"""Return the more permissive (higher-ranked) trust tier."""
|
|
41
|
+
return a if _TIER_RANK.get(a, 0) >= _TIER_RANK.get(b, 0) else b
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def more_restrictive_privacy(a: str, b: str) -> str:
|
|
45
|
+
"""Return the more restrictive privacy level."""
|
|
46
|
+
rank = {"public": 0, "private": 1, "restricted": 2}
|
|
47
|
+
return a if rank.get(a, 1) >= rank.get(b, 1) else b
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# ── Core entities ─────────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class Contact:
|
|
54
|
+
"""A person known to Colony."""
|
|
55
|
+
contact_id: str
|
|
56
|
+
display_name: Optional[str]
|
|
57
|
+
given_name: Optional[str]
|
|
58
|
+
family_name: Optional[str]
|
|
59
|
+
organization: Optional[str]
|
|
60
|
+
relationship_score: float
|
|
61
|
+
trust_tier: str
|
|
62
|
+
interaction_allowed: bool
|
|
63
|
+
tags: List[str]
|
|
64
|
+
privacy_level: str
|
|
65
|
+
person_node_id: Optional[str]
|
|
66
|
+
notes: Optional[str]
|
|
67
|
+
import_source: str
|
|
68
|
+
first_seen_at: str
|
|
69
|
+
last_interaction_at: Optional[str]
|
|
70
|
+
interaction_count: int
|
|
71
|
+
enrichment_source: List[str]
|
|
72
|
+
enrichment_last_at: Optional[str]
|
|
73
|
+
deleted_at: Optional[str]
|
|
74
|
+
created_at: str
|
|
75
|
+
updated_at: str
|
|
76
|
+
timezone: Optional[str] = None # IANA tz for this contact (v0.21.0), editable
|
|
77
|
+
# Introduction provenance (social-graph autonomy): the contact_id of whoever
|
|
78
|
+
# introduced this person, and a met_via dict ({channel, scope_id, ...}) for
|
|
79
|
+
# how/where the agent met them. None for contacts not created via an intro.
|
|
80
|
+
introduced_by: Optional[str] = None
|
|
81
|
+
met_via: Optional[Dict[str, Any]] = None
|
|
82
|
+
|
|
83
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
84
|
+
return {
|
|
85
|
+
"contact_id": self.contact_id,
|
|
86
|
+
"display_name": self.display_name,
|
|
87
|
+
"given_name": self.given_name,
|
|
88
|
+
"family_name": self.family_name,
|
|
89
|
+
"organization": self.organization,
|
|
90
|
+
"relationship_score": self.relationship_score,
|
|
91
|
+
"trust_tier": self.trust_tier,
|
|
92
|
+
"interaction_allowed": self.interaction_allowed,
|
|
93
|
+
"tags": self.tags,
|
|
94
|
+
"privacy_level": self.privacy_level,
|
|
95
|
+
"person_node_id": self.person_node_id,
|
|
96
|
+
"notes": self.notes,
|
|
97
|
+
"import_source": self.import_source,
|
|
98
|
+
"first_seen_at": self.first_seen_at,
|
|
99
|
+
"last_interaction_at": self.last_interaction_at,
|
|
100
|
+
"interaction_count": self.interaction_count,
|
|
101
|
+
"enrichment_source": self.enrichment_source,
|
|
102
|
+
"enrichment_last_at": self.enrichment_last_at,
|
|
103
|
+
"deleted_at": self.deleted_at,
|
|
104
|
+
"created_at": self.created_at,
|
|
105
|
+
"updated_at": self.updated_at,
|
|
106
|
+
"timezone": self.timezone,
|
|
107
|
+
"introduced_by": self.introduced_by,
|
|
108
|
+
"met_via": self.met_via,
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@classmethod
|
|
112
|
+
def from_row(cls, row: Dict[str, Any]) -> "Contact":
|
|
113
|
+
tags_json = row.get("tags_json", "[]")
|
|
114
|
+
tags = json.loads(tags_json) if isinstance(tags_json, str) else (tags_json or [])
|
|
115
|
+
enrichment_source_json = row.get("enrichment_source", "[]")
|
|
116
|
+
enrichment_source = (
|
|
117
|
+
json.loads(enrichment_source_json)
|
|
118
|
+
if isinstance(enrichment_source_json, str)
|
|
119
|
+
else (enrichment_source_json or [])
|
|
120
|
+
)
|
|
121
|
+
met_via_raw = row.get("met_via_json")
|
|
122
|
+
met_via = json.loads(met_via_raw) if isinstance(met_via_raw, str) and met_via_raw else None
|
|
123
|
+
return cls(
|
|
124
|
+
contact_id=row["contact_id"],
|
|
125
|
+
display_name=row.get("display_name"),
|
|
126
|
+
given_name=row.get("given_name"),
|
|
127
|
+
family_name=row.get("family_name"),
|
|
128
|
+
organization=row.get("organization"),
|
|
129
|
+
relationship_score=float(row.get("relationship_score", 0.0)),
|
|
130
|
+
trust_tier=row.get("trust_tier", "unknown"),
|
|
131
|
+
interaction_allowed=bool(row.get("interaction_allowed", 1)),
|
|
132
|
+
tags=tags,
|
|
133
|
+
privacy_level=row.get("privacy_level", "private"),
|
|
134
|
+
person_node_id=row.get("person_node_id"),
|
|
135
|
+
notes=row.get("notes"),
|
|
136
|
+
import_source=row.get("import_source", "manual"),
|
|
137
|
+
first_seen_at=row.get("first_seen_at", ""),
|
|
138
|
+
last_interaction_at=row.get("last_interaction_at"),
|
|
139
|
+
interaction_count=int(row.get("interaction_count", 0)),
|
|
140
|
+
enrichment_source=enrichment_source,
|
|
141
|
+
enrichment_last_at=row.get("enrichment_last_at"),
|
|
142
|
+
deleted_at=row.get("deleted_at"),
|
|
143
|
+
created_at=row.get("created_at", ""),
|
|
144
|
+
updated_at=row.get("updated_at", ""),
|
|
145
|
+
timezone=row.get("timezone"),
|
|
146
|
+
introduced_by=row.get("introduced_by"),
|
|
147
|
+
met_via=met_via,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@dataclass
|
|
152
|
+
class ContactHandle:
|
|
153
|
+
"""A gateway-specific address for a contact."""
|
|
154
|
+
handle_id: str
|
|
155
|
+
contact_id: str
|
|
156
|
+
gateway: str
|
|
157
|
+
address: str
|
|
158
|
+
is_primary: bool
|
|
159
|
+
verified: bool
|
|
160
|
+
confidence: float
|
|
161
|
+
source: str
|
|
162
|
+
created_at: str
|
|
163
|
+
|
|
164
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
165
|
+
return {
|
|
166
|
+
"handle_id": self.handle_id,
|
|
167
|
+
"contact_id": self.contact_id,
|
|
168
|
+
"gateway": self.gateway,
|
|
169
|
+
"address": self.address,
|
|
170
|
+
"is_primary": self.is_primary,
|
|
171
|
+
"verified": self.verified,
|
|
172
|
+
"confidence": self.confidence,
|
|
173
|
+
"source": self.source,
|
|
174
|
+
"created_at": self.created_at,
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@classmethod
|
|
178
|
+
def from_row(cls, row: Dict[str, Any]) -> "ContactHandle":
|
|
179
|
+
return cls(
|
|
180
|
+
handle_id=row["handle_id"],
|
|
181
|
+
contact_id=row["contact_id"],
|
|
182
|
+
gateway=row["gateway"],
|
|
183
|
+
address=row["address"],
|
|
184
|
+
is_primary=bool(row.get("is_primary", 0)),
|
|
185
|
+
verified=bool(row.get("verified", 0)),
|
|
186
|
+
confidence=float(row.get("confidence", 1.0)),
|
|
187
|
+
source=row.get("source", "manual"),
|
|
188
|
+
created_at=row.get("created_at", ""),
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@dataclass
|
|
193
|
+
class MergeProposal:
|
|
194
|
+
"""A pending or resolved merge proposal."""
|
|
195
|
+
id: str
|
|
196
|
+
contact_id_a: str
|
|
197
|
+
contact_id_b: str
|
|
198
|
+
confidence: float
|
|
199
|
+
reason: str
|
|
200
|
+
status: str # pending, approved, rejected, auto_merged
|
|
201
|
+
proposed_at: str
|
|
202
|
+
resolved_at: Optional[str]
|
|
203
|
+
|
|
204
|
+
@classmethod
|
|
205
|
+
def from_row(cls, row: Dict[str, Any]) -> "MergeProposal":
|
|
206
|
+
return cls(
|
|
207
|
+
id=row["id"],
|
|
208
|
+
contact_id_a=row["contact_id_a"],
|
|
209
|
+
contact_id_b=row["contact_id_b"],
|
|
210
|
+
confidence=float(row["confidence"]),
|
|
211
|
+
reason=row["reason"],
|
|
212
|
+
status=row["status"],
|
|
213
|
+
proposed_at=row["proposed_at"],
|
|
214
|
+
resolved_at=row.get("resolved_at"),
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
@dataclass
|
|
219
|
+
class MergeAuditRecord:
|
|
220
|
+
"""Immutable record of a completed merge operation."""
|
|
221
|
+
audit_id: str
|
|
222
|
+
canonical_id: str
|
|
223
|
+
absorbed_id: str
|
|
224
|
+
confidence: float
|
|
225
|
+
merge_reason: str
|
|
226
|
+
triggered_by: str
|
|
227
|
+
contact_a_snapshot: Dict[str, Any]
|
|
228
|
+
contact_b_snapshot: Dict[str, Any]
|
|
229
|
+
merged_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
230
|
+
|
|
231
|
+
def __post_init__(self):
|
|
232
|
+
if self.merged_at is None:
|
|
233
|
+
self.merged_at = datetime.now(timezone.utc)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
# ── Trust scopes (context-scoped trust: group chats, households, project rooms) ──
|
|
237
|
+
#
|
|
238
|
+
# A trust_scope grants its members a trust tier that applies ONLY inside the scope
|
|
239
|
+
# (e.g. a specific group conversation). Membership never confers global 1:1 rights —
|
|
240
|
+
# a member's contact.trust_tier / interaction_allowed are independent. This is the
|
|
241
|
+
# generic primitive any agent uses to say "trusted in this room, not in my DMs".
|
|
242
|
+
|
|
243
|
+
SCOPE_TYPES = ("group", "household", "project", "event", "custom")
|
|
244
|
+
SCOPE_MEMBER_ROLES = ("owner", "member", "observer")
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
@dataclass
|
|
248
|
+
class TrustScope:
|
|
249
|
+
"""A context that grants its members a tier of trust scoped to itself."""
|
|
250
|
+
scope_id: str
|
|
251
|
+
scope_type: str # one of SCOPE_TYPES
|
|
252
|
+
platform: Optional[str] # e.g. "rcs"; NULL for abstract scopes
|
|
253
|
+
external_id: Optional[str] # platform conversation/group id (relay conv_id, etc.)
|
|
254
|
+
label: Optional[str] # human name (e.g. a group's display name)
|
|
255
|
+
granted_tier: str # tier members get WITHIN this scope (default group_guest)
|
|
256
|
+
created_by: str # "owner" | "agent" | contact_id
|
|
257
|
+
active: bool
|
|
258
|
+
created_at: str
|
|
259
|
+
updated_at: str
|
|
260
|
+
|
|
261
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
262
|
+
return {
|
|
263
|
+
"scope_id": self.scope_id,
|
|
264
|
+
"scope_type": self.scope_type,
|
|
265
|
+
"platform": self.platform,
|
|
266
|
+
"external_id": self.external_id,
|
|
267
|
+
"label": self.label,
|
|
268
|
+
"granted_tier": self.granted_tier,
|
|
269
|
+
"created_by": self.created_by,
|
|
270
|
+
"active": self.active,
|
|
271
|
+
"created_at": self.created_at,
|
|
272
|
+
"updated_at": self.updated_at,
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
@classmethod
|
|
276
|
+
def from_row(cls, row: Dict[str, Any]) -> "TrustScope":
|
|
277
|
+
return cls(
|
|
278
|
+
scope_id=row["scope_id"],
|
|
279
|
+
scope_type=row["scope_type"],
|
|
280
|
+
platform=row.get("platform"),
|
|
281
|
+
external_id=row.get("external_id"),
|
|
282
|
+
label=row.get("label"),
|
|
283
|
+
granted_tier=row.get("granted_tier", "group_guest"),
|
|
284
|
+
created_by=row.get("created_by", "agent"),
|
|
285
|
+
active=bool(row.get("active", 1)),
|
|
286
|
+
created_at=row.get("created_at", ""),
|
|
287
|
+
updated_at=row.get("updated_at", ""),
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
@dataclass
|
|
292
|
+
class ScopeMember:
|
|
293
|
+
"""A contact's membership in a trust scope (current while left_at is None)."""
|
|
294
|
+
scope_id: str
|
|
295
|
+
contact_id: str
|
|
296
|
+
role: str # one of SCOPE_MEMBER_ROLES
|
|
297
|
+
joined_at: str
|
|
298
|
+
left_at: Optional[str]
|
|
299
|
+
|
|
300
|
+
@classmethod
|
|
301
|
+
def from_row(cls, row: Dict[str, Any]) -> "ScopeMember":
|
|
302
|
+
return cls(
|
|
303
|
+
scope_id=row["scope_id"],
|
|
304
|
+
contact_id=row["contact_id"],
|
|
305
|
+
role=row.get("role", "member"),
|
|
306
|
+
joined_at=row.get("joined_at", ""),
|
|
307
|
+
left_at=row.get("left_at"),
|
|
308
|
+
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Compatibility for retired composite closeness; historical contact values remain.
|
|
2
|
+
|
|
3
|
+
Standing, frequency, recency and a contact's affect are not one relationship
|
|
4
|
+
quality. New behavior uses attributed preferences and scoped AppraisalStore views.
|
|
5
|
+
"""
|
|
6
|
+
from typing import Any, Optional
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def compute_relationship_score(contact: Any, affect_state: Optional[dict] = None, now=None) -> None:
|
|
10
|
+
"""No meaningful scalar is computed. Do not write this into contact storage."""
|
|
11
|
+
return None
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def closeness_label(score) -> str:
|
|
15
|
+
"""Old stored values carry no supported psychological interpretation."""
|
|
16
|
+
return 'legacy score; relationship interpretation unavailable'
|