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,55 @@
|
|
|
1
|
+
"""Prospective runtime observations for the existing working-judgment queue.
|
|
2
|
+
|
|
3
|
+
Called only after the server rereads an owned native task. No model report,
|
|
4
|
+
tool result prose, caller-supplied outcome or imported history is evidence here.
|
|
5
|
+
"""
|
|
6
|
+
from contextlib import closing
|
|
7
|
+
from datetime import datetime, timezone
|
|
8
|
+
import hashlib
|
|
9
|
+
import json
|
|
10
|
+
import math
|
|
11
|
+
|
|
12
|
+
VERSION = 'native-runtime-observation-v1'
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def retain_outcome(review, native, state, owner):
|
|
16
|
+
binding = review.get('native_work') or {}
|
|
17
|
+
selection = binding.get('outcome_learning') or {}
|
|
18
|
+
observed = state.get('runtime_observation')
|
|
19
|
+
if selection.get('version') != VERSION or not observed:
|
|
20
|
+
return
|
|
21
|
+
started, ended = observed['started_at'], observed['ended_at']
|
|
22
|
+
if not all(type(value) in (int, float) and math.isfinite(value) for value in (started, ended)):
|
|
23
|
+
return
|
|
24
|
+
# Native run timestamps have whole-second precision. The binding marker
|
|
25
|
+
# is only set while this newly bound task has no runs.
|
|
26
|
+
if ended < started or started < math.floor(datetime.fromisoformat(selection['bound_at']).timestamp()):
|
|
27
|
+
return
|
|
28
|
+
if observed['outcome'] not in {'crashed', 'timed_out', 'spawn_failed', 'gave_up'}:
|
|
29
|
+
return
|
|
30
|
+
identity = {**native, 'native_run_id': state['native_run_id']}
|
|
31
|
+
source_id = 'native-runtime:' + hashlib.sha256(json.dumps(identity, sort_keys=True).encode()).hexdigest()
|
|
32
|
+
facts = {**observed, 'duration_seconds': ended-started, 'identity': identity,
|
|
33
|
+
'registered_action': review['review']['action']}
|
|
34
|
+
message = {'role': 'assistant', '_native_runtime_observation': VERSION,
|
|
35
|
+
'content': 'Runtime-owned internal review execution observation. '
|
|
36
|
+
'This records lifecycle and elapsed time, not the accuracy of any output. '
|
|
37
|
+
'Requested model configuration does not identify the serving processor.\n'
|
|
38
|
+
+ json.dumps(facts, sort_keys=True)}
|
|
39
|
+
from apsimo.turns import get_turn_idempotency_ledger
|
|
40
|
+
from apsimo import get_state_dir
|
|
41
|
+
from apsimo.turns.idempotency import SourceErased
|
|
42
|
+
ledger = get_turn_idempotency_ledger(get_state_dir())
|
|
43
|
+
# Retain the first observation unchanged. Native task overrides can change
|
|
44
|
+
# after a run; observing it again must not rewrite that earlier evidence.
|
|
45
|
+
with closing(ledger._connect()) as conn:
|
|
46
|
+
if conn.execute('SELECT 1 FROM turn_sources WHERE turn_id=?', (source_id,)).fetchone():
|
|
47
|
+
return
|
|
48
|
+
try:
|
|
49
|
+
ledger.record_source(source_id, contact_id=owner,
|
|
50
|
+
session_id='native-runtime:'+native['native_task_id'], messages=[message],
|
|
51
|
+
occurred_at=datetime.fromtimestamp(ended, timezone.utc).isoformat(),
|
|
52
|
+
derive_claims=False, runtime_judgment=True)
|
|
53
|
+
except SourceErased:
|
|
54
|
+
# Normal observation replay must not resurrect an erased experience.
|
|
55
|
+
return
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"""AdaptiveParamStore -- bounded, journaled runtime parameters.
|
|
2
|
+
|
|
3
|
+
The meta-learning loop (CognitionPipeline -> StrategyAdjuster) needs a place
|
|
4
|
+
to write tuning adjustments that running subsystems actually READ BACK. This
|
|
5
|
+
store is that place: a small SQLite table of named float parameters, each
|
|
6
|
+
registered by its consumer with a default and hard bounds. Every write is
|
|
7
|
+
clamped to the registered bounds and journaled through the ActionJournal
|
|
8
|
+
(domain "meta_learning"), so a bad self-adjustment is visible, attributable,
|
|
9
|
+
and bounded -- never a silent behavior shift.
|
|
10
|
+
|
|
11
|
+
Consumers read at use-time (no restart needed). Writers (the strategy
|
|
12
|
+
adjuster, tools, or the owner via API) go through ``set()`` and never bypass
|
|
13
|
+
the clamp.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import logging
|
|
19
|
+
import sqlite3
|
|
20
|
+
import threading
|
|
21
|
+
import time
|
|
22
|
+
from typing import Any, Dict, List, Optional
|
|
23
|
+
|
|
24
|
+
from apsimo.self_model.benchmark import cognition_p4_mode
|
|
25
|
+
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AdaptiveParamStore:
|
|
30
|
+
"""SQLite-backed named float parameters with hard bounds + journaling."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, db_path: Optional[str] = None,
|
|
33
|
+
journal: Any = None) -> None:
|
|
34
|
+
self._lock = threading.RLock()
|
|
35
|
+
self._journal = journal
|
|
36
|
+
self._experiment_writer_id: Optional[str] = None
|
|
37
|
+
self._experiment_writer_token: Any = None
|
|
38
|
+
self._conn = sqlite3.connect(str(db_path) if db_path else ":memory:",
|
|
39
|
+
check_same_thread=False)
|
|
40
|
+
self._conn.row_factory = sqlite3.Row
|
|
41
|
+
with self._lock:
|
|
42
|
+
self._conn.execute(
|
|
43
|
+
"""CREATE TABLE IF NOT EXISTS adaptive_params (
|
|
44
|
+
name TEXT PRIMARY KEY,
|
|
45
|
+
value REAL,
|
|
46
|
+
default_value REAL NOT NULL,
|
|
47
|
+
lo REAL NOT NULL,
|
|
48
|
+
hi REAL NOT NULL,
|
|
49
|
+
description TEXT,
|
|
50
|
+
reason TEXT,
|
|
51
|
+
source TEXT,
|
|
52
|
+
updated_at REAL
|
|
53
|
+
)""")
|
|
54
|
+
self._conn.commit()
|
|
55
|
+
|
|
56
|
+
def set_journal(self, journal: Any) -> None:
|
|
57
|
+
"""Attach the ActionJournal after boot (it is created later than
|
|
58
|
+
this store in the server lifespan)."""
|
|
59
|
+
self._journal = journal
|
|
60
|
+
|
|
61
|
+
def claim_experiment_writer(self, writer_id: str) -> Any:
|
|
62
|
+
"""Claim the one in-process capability that may mutate P4 knobs.
|
|
63
|
+
|
|
64
|
+
The object token is intentionally not serializable. The database still
|
|
65
|
+
records every mutation; this capability prevents legacy components
|
|
66
|
+
from racing the canonical ExperimentEngine inside one sidecar.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
normalized = (writer_id or "").strip()
|
|
70
|
+
if not normalized:
|
|
71
|
+
raise ValueError("experiment writer id is required")
|
|
72
|
+
with self._lock:
|
|
73
|
+
if self._experiment_writer_id is None:
|
|
74
|
+
self._experiment_writer_id = normalized
|
|
75
|
+
self._experiment_writer_token = object()
|
|
76
|
+
elif self._experiment_writer_id != normalized:
|
|
77
|
+
raise RuntimeError(
|
|
78
|
+
"AdaptiveParamStore already has an ExperimentEngine writer")
|
|
79
|
+
return self._experiment_writer_token
|
|
80
|
+
|
|
81
|
+
def _assert_writer(self, writer_token: Any) -> None:
|
|
82
|
+
if cognition_p4_mode() == "off":
|
|
83
|
+
return
|
|
84
|
+
if (self._experiment_writer_token is None
|
|
85
|
+
or writer_token is not self._experiment_writer_token):
|
|
86
|
+
raise PermissionError(
|
|
87
|
+
"ExperimentEngine is the sole adaptive-parameter writer "
|
|
88
|
+
"while COLONY_COGNITION_P4_MODE is enabled")
|
|
89
|
+
|
|
90
|
+
# -- registration (consumers declare their knob + safe range) ---------
|
|
91
|
+
def register(self, name: str, default: float, lo: float, hi: float,
|
|
92
|
+
description: str = "") -> None:
|
|
93
|
+
"""Idempotently declare a parameter. Bounds/default/description are
|
|
94
|
+
refreshed on re-registration; a previously set value is kept (but
|
|
95
|
+
re-clamped if the new bounds exclude it)."""
|
|
96
|
+
name = (name or "").strip()
|
|
97
|
+
if not name:
|
|
98
|
+
return
|
|
99
|
+
if lo > hi:
|
|
100
|
+
lo, hi = hi, lo
|
|
101
|
+
default = min(max(float(default), lo), hi)
|
|
102
|
+
with self._lock:
|
|
103
|
+
row = self._conn.execute(
|
|
104
|
+
"SELECT value FROM adaptive_params WHERE name=?",
|
|
105
|
+
(name,)).fetchone()
|
|
106
|
+
value = row["value"] if row is not None else None
|
|
107
|
+
if value is not None:
|
|
108
|
+
value = min(max(float(value), lo), hi)
|
|
109
|
+
self._conn.execute(
|
|
110
|
+
"""INSERT INTO adaptive_params
|
|
111
|
+
(name, value, default_value, lo, hi, description, updated_at)
|
|
112
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
113
|
+
ON CONFLICT(name) DO UPDATE SET
|
|
114
|
+
value=?, default_value=?, lo=?, hi=?, description=?""",
|
|
115
|
+
(name, value, default, lo, hi, description, time.time(),
|
|
116
|
+
value, default, lo, hi, description))
|
|
117
|
+
self._conn.commit()
|
|
118
|
+
|
|
119
|
+
# -- reads -------------------------------------------------------------
|
|
120
|
+
def get(self, name: str, default: Optional[float] = None) -> float:
|
|
121
|
+
"""Current value: the set value if any, else the registered default,
|
|
122
|
+
else the caller-supplied fallback (0.0 if none)."""
|
|
123
|
+
with self._lock:
|
|
124
|
+
row = self._conn.execute(
|
|
125
|
+
"SELECT value, default_value FROM adaptive_params WHERE name=?",
|
|
126
|
+
((name or "").strip(),)).fetchone()
|
|
127
|
+
if row is None:
|
|
128
|
+
return float(default) if default is not None else 0.0
|
|
129
|
+
if row["value"] is not None:
|
|
130
|
+
return float(row["value"])
|
|
131
|
+
return float(row["default_value"])
|
|
132
|
+
|
|
133
|
+
# -- writes (clamped + journaled) ---------------------------------------
|
|
134
|
+
def set(self, name: str, value: float, *, reason: str = "",
|
|
135
|
+
source: str = "", writer_token: Any = None) -> Optional[float]:
|
|
136
|
+
"""Set a parameter. Returns the APPLIED (clamped) value, or None if
|
|
137
|
+
the parameter was never registered (unknown knobs are refused --
|
|
138
|
+
a writer cannot invent parameters no consumer reads)."""
|
|
139
|
+
self._assert_writer(writer_token)
|
|
140
|
+
name = (name or "").strip()
|
|
141
|
+
with self._lock:
|
|
142
|
+
row = self._conn.execute(
|
|
143
|
+
"SELECT lo, hi, value FROM adaptive_params WHERE name=?",
|
|
144
|
+
(name,)).fetchone()
|
|
145
|
+
if row is None:
|
|
146
|
+
logger.warning("AdaptiveParamStore: refusing unregistered "
|
|
147
|
+
"param %r", name)
|
|
148
|
+
return None
|
|
149
|
+
applied = min(max(float(value), row["lo"]), row["hi"])
|
|
150
|
+
prior = row["value"]
|
|
151
|
+
self._conn.execute(
|
|
152
|
+
"""UPDATE adaptive_params
|
|
153
|
+
SET value=?, reason=?, source=?, updated_at=?
|
|
154
|
+
WHERE name=?""",
|
|
155
|
+
(applied, reason, source, time.time(), name))
|
|
156
|
+
self._conn.commit()
|
|
157
|
+
clamped = abs(applied - float(value)) > 1e-9
|
|
158
|
+
logger.info("AdaptiveParamStore: %s %s -> %s%s (%s)", name,
|
|
159
|
+
prior, applied, " [clamped]" if clamped else "",
|
|
160
|
+
reason or source or "unattributed")
|
|
161
|
+
if self._journal is not None:
|
|
162
|
+
try:
|
|
163
|
+
self._journal.record(
|
|
164
|
+
"meta_learning",
|
|
165
|
+
f"adaptive param {name}: {prior} -> {applied}"
|
|
166
|
+
+ (" (clamped)" if clamped else ""),
|
|
167
|
+
reasoning=reason, decision="acted",
|
|
168
|
+
outcome="applied", ref=source or "adaptive_params")
|
|
169
|
+
except Exception:
|
|
170
|
+
logger.debug("param journal write failed", exc_info=True)
|
|
171
|
+
return applied
|
|
172
|
+
|
|
173
|
+
def reset(self, name: str, *, reason: str = "", source: str = "",
|
|
174
|
+
writer_token: Any = None) -> None:
|
|
175
|
+
"""Clear a set value so the registered default applies again."""
|
|
176
|
+
self._assert_writer(writer_token)
|
|
177
|
+
with self._lock:
|
|
178
|
+
self._conn.execute(
|
|
179
|
+
"UPDATE adaptive_params SET value=NULL, reason=?, source=?, "
|
|
180
|
+
"updated_at=? WHERE name=?",
|
|
181
|
+
(reason, source, time.time(), (name or "").strip()))
|
|
182
|
+
self._conn.commit()
|
|
183
|
+
|
|
184
|
+
def snapshot(self) -> List[Dict[str, Any]]:
|
|
185
|
+
with self._lock:
|
|
186
|
+
rows = self._conn.execute(
|
|
187
|
+
"SELECT * FROM adaptive_params ORDER BY name").fetchall()
|
|
188
|
+
out = []
|
|
189
|
+
for r in rows:
|
|
190
|
+
d = dict(r)
|
|
191
|
+
d["effective"] = (float(d["value"]) if d["value"] is not None
|
|
192
|
+
else float(d["default_value"]))
|
|
193
|
+
out.append(d)
|
|
194
|
+
return out
|
|
195
|
+
|
|
196
|
+
def close(self) -> None:
|
|
197
|
+
with self._lock:
|
|
198
|
+
try:
|
|
199
|
+
self._conn.close()
|
|
200
|
+
except Exception:
|
|
201
|
+
pass
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
# Canonical parameter names (registered at boot; consumers read these).
|
|
205
|
+
PARAM_CONSOLIDATION_THRESHOLD = "consolidation.similarity_threshold"
|
|
206
|
+
PARAM_RECALL_MIN_RELEVANCE = "recall.min_relevance"
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def register_core_params(store: AdaptiveParamStore) -> None:
|
|
210
|
+
"""Register the parameters core subsystems consume."""
|
|
211
|
+
store.register(
|
|
212
|
+
PARAM_CONSOLIDATION_THRESHOLD, default=0.92, lo=0.85, hi=0.98,
|
|
213
|
+
description="MemoryConsolidator merge threshold: pairs at or above "
|
|
214
|
+
"this similarity are deduplicated. Hard floor 0.85 so a "
|
|
215
|
+
"self-adjustment can never mass-merge distinct memories.")
|
|
216
|
+
store.register(
|
|
217
|
+
PARAM_RECALL_MIN_RELEVANCE, default=0.0, lo=0.0, hi=0.5,
|
|
218
|
+
description="ColonyGraph.recall drops vector hits scoring below "
|
|
219
|
+
"this. 0 = no filter; capped at 0.5 so retrieval can "
|
|
220
|
+
"never be starved by a self-adjustment.")
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"""Source-backed preferences and inspectable attention.
|
|
2
|
+
|
|
3
|
+
This is a portable working perspective, not feelings, a worldview or authority.
|
|
4
|
+
Original owner words stay in the canonical source ledger. Only explicit owner
|
|
5
|
+
preferences adjust optional research priority; prior automatic weights are history.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from contextlib import closing
|
|
10
|
+
from copy import copy
|
|
11
|
+
from datetime import datetime, timezone
|
|
12
|
+
import json
|
|
13
|
+
import re
|
|
14
|
+
import time
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
DOMAINS = frozenset({'research', 'knowledge_acquisition'})
|
|
18
|
+
VERSION = 'owner-directed-perspective-v2'
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def initialize(conn):
|
|
22
|
+
conn.execute('''CREATE TABLE IF NOT EXISTS self_preference_events (
|
|
23
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT, owner_id TEXT NOT NULL,
|
|
24
|
+
pref_key TEXT NOT NULL, value_json TEXT NOT NULL,
|
|
25
|
+
source_turn_id TEXT NOT NULL, message_hash TEXT NOT NULL,
|
|
26
|
+
source_at TEXT NOT NULL, supersedes INTEGER,
|
|
27
|
+
UNIQUE(owner_id,pref_key,source_turn_id,message_hash))''')
|
|
28
|
+
# A value-free marker prevents erased sourced corrections from revealing
|
|
29
|
+
# an older unprovenanced cache value for the same preference.
|
|
30
|
+
conn.execute('''CREATE TABLE IF NOT EXISTS self_preference_keys (
|
|
31
|
+
owner_id TEXT NOT NULL,pref_key TEXT NOT NULL,latest_event_id INTEGER,latest_source_at TEXT NOT NULL,
|
|
32
|
+
PRIMARY KEY(owner_id,pref_key))''')
|
|
33
|
+
conn.execute('''CREATE TABLE IF NOT EXISTS self_opinion_revisions (
|
|
34
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT, domain TEXT NOT NULL,
|
|
35
|
+
weight REAL NOT NULL, basis_json TEXT NOT NULL, basis_digest TEXT NOT NULL,
|
|
36
|
+
reason TEXT NOT NULL, updated_at REAL NOT NULL, version TEXT NOT NULL)''')
|
|
37
|
+
conn.execute('''CREATE TABLE IF NOT EXISTS self_attention (
|
|
38
|
+
slot INTEGER PRIMARY KEY CHECK(slot=1), snapshot_json TEXT NOT NULL,
|
|
39
|
+
observed_at REAL NOT NULL)''')
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def erase_removed(conn, turn_id, session_id, retained):
|
|
43
|
+
from apsimo.turns.idempotency import source_message_hash
|
|
44
|
+
if not conn.execute("SELECT 1 FROM sqlite_master WHERE name='self_preference_events'").fetchone():
|
|
45
|
+
return
|
|
46
|
+
hashes = {source_message_hash(session_id, message) for message in retained}
|
|
47
|
+
rows = conn.execute('SELECT id,message_hash FROM self_preference_events WHERE source_turn_id=?', (turn_id,)).fetchall()
|
|
48
|
+
for row in rows:
|
|
49
|
+
if row['message_hash'] not in hashes:
|
|
50
|
+
conn.execute('DELETE FROM self_preference_events WHERE id=?', (row['id'],))
|
|
51
|
+
# Attention contains correction references/weights; do not retain a stale
|
|
52
|
+
# derived snapshot after deleting its source. The next decision rebuilds it.
|
|
53
|
+
conn.execute('DELETE FROM self_attention')
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _json(value):
|
|
57
|
+
return json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=True)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class SelfPerspective:
|
|
61
|
+
def __init__(self, ledger, *, owner_id, clock=time.time):
|
|
62
|
+
self.ledger = ledger
|
|
63
|
+
self.owner_id = str(owner_id or '')
|
|
64
|
+
self.clock = clock
|
|
65
|
+
with closing(ledger._connect()) as conn, conn:
|
|
66
|
+
initialize(conn)
|
|
67
|
+
from apsimo.self_model.judgments import SelfJudgments
|
|
68
|
+
self.judgments = SelfJudgments(ledger, owner_id=self.owner_id, clock=clock)
|
|
69
|
+
from apsimo.self_model.appraisals import AppraisalStore
|
|
70
|
+
self.appraisals = AppraisalStore(ledger, owner_id=self.owner_id, clock=clock)
|
|
71
|
+
|
|
72
|
+
def observe_source(self, turn_id, learner):
|
|
73
|
+
"""Learn only direct, attributed owner words; replay does not add votes."""
|
|
74
|
+
from apsimo.turns.idempotency import source_message_hash
|
|
75
|
+
if not self.owner_id:
|
|
76
|
+
return []
|
|
77
|
+
learned = []
|
|
78
|
+
with closing(self.ledger._connect()) as conn, conn:
|
|
79
|
+
conn.execute('BEGIN IMMEDIATE')
|
|
80
|
+
source = conn.execute("SELECT * FROM turn_sources WHERE turn_id=? AND contact_id=? AND scope='person'", (turn_id, self.owner_id)).fetchone()
|
|
81
|
+
if source is None:
|
|
82
|
+
return []
|
|
83
|
+
for message in json.loads(source['messages_json']):
|
|
84
|
+
if message.get('role') != 'user':
|
|
85
|
+
continue
|
|
86
|
+
text = message.get('content', '')
|
|
87
|
+
if isinstance(text, list):
|
|
88
|
+
text = '\n'.join(p.get('text', '') for p in text if p.get('type') in {'text', 'input_text'})
|
|
89
|
+
if not isinstance(text, str):
|
|
90
|
+
continue
|
|
91
|
+
updates = self._directives(text, learner)
|
|
92
|
+
for key, value in updates:
|
|
93
|
+
source_at = datetime.fromisoformat(source['occurred_at'] or source['ingested_at']).astimezone(timezone.utc).isoformat()
|
|
94
|
+
previous = conn.execute('SELECT id FROM self_preference_events WHERE owner_id=? AND pref_key=? AND source_at<=? ORDER BY source_at DESC,id DESC LIMIT 1', (self.owner_id, key, source_at)).fetchone()
|
|
95
|
+
cur = conn.execute('''INSERT OR IGNORE INTO self_preference_events
|
|
96
|
+
(owner_id,pref_key,value_json,source_turn_id,message_hash,source_at,supersedes)
|
|
97
|
+
VALUES (?,?,?,?,?,?,?)''', (self.owner_id, key, _json(value), turn_id,
|
|
98
|
+
source_message_hash(source['session_id'], message),
|
|
99
|
+
source_at, previous['id'] if previous else None))
|
|
100
|
+
if cur.rowcount:
|
|
101
|
+
conn.execute('''INSERT INTO self_preference_keys VALUES (?,?,?,?)
|
|
102
|
+
ON CONFLICT(owner_id,pref_key) DO UPDATE SET latest_event_id=excluded.latest_event_id,
|
|
103
|
+
latest_source_at=excluded.latest_source_at WHERE excluded.latest_source_at>=self_preference_keys.latest_source_at''',
|
|
104
|
+
(self.owner_id, key, cur.lastrowid, source_at))
|
|
105
|
+
learned.append((key, value))
|
|
106
|
+
return learned
|
|
107
|
+
|
|
108
|
+
@staticmethod
|
|
109
|
+
def _directives(text, learner):
|
|
110
|
+
raw = text.strip()
|
|
111
|
+
# Conservative direct-address subset. Quotation, questions, reports
|
|
112
|
+
# about another person and ambiguous negation remain raw evidence.
|
|
113
|
+
if len(raw.split()) > 40 or any(c in raw for c in ('"', '“', '”', '?', '`', '\n')):
|
|
114
|
+
return []
|
|
115
|
+
operational = re.fullmatch(r'(?:please\s+)?(prefer|deprioritize|use normal priority for)\s+(research|knowledge acquisition)\s+initiatives[.!]?', raw, re.I)
|
|
116
|
+
if operational:
|
|
117
|
+
weight = {'prefer': 1.2, 'deprioritize': 0.8, 'use normal priority for': 1.0}[operational[1].lower()]
|
|
118
|
+
return [('initiative.' + operational[2].lower().replace(' ', '_'), weight)]
|
|
119
|
+
prefix = re.match(r'^(?:(?:please|actually|from now on|going forward)[,:]?\s+)*(?:be\b|keep\b|use\b|stop\b|skip\b|avoid\b|don.t\b|do not\b|no emoji\b|no emojis\b|i prefer\b|i want\b)', raw, re.I)
|
|
120
|
+
if not prefix:
|
|
121
|
+
return []
|
|
122
|
+
# Reuse existing style vocabulary, but do not guess the direction of
|
|
123
|
+
# a negated or comparative request from bag-of-words keyword order.
|
|
124
|
+
polarity = re.sub(r'\b(?:stop\s+(?:using\s+|with\s+)?|skip\s+(?:the\s+)?|avoid\s+(?:the\s+)?|no\s+|don.t\s+use\s+|do\s+not\s+use\s+)emojis?\b', '', raw, flags=re.I)
|
|
125
|
+
if re.search(r'\b(not|never|rather|instead|than|except|without|don.t|stop|skip|avoid|no)\b', polarity, re.I):
|
|
126
|
+
return []
|
|
127
|
+
from apsimo.intelligence.components import preference_learner as vocabulary
|
|
128
|
+
words = set(re.findall(r'\b\w+\b', raw.lower()))
|
|
129
|
+
if re.search(r'\bi (?:prefer|want)$', prefix[0], re.I):
|
|
130
|
+
# First-person corrections must name general communication:
|
|
131
|
+
# "I prefer/want <style> replies/responses/answers". Artifact
|
|
132
|
+
# requests ("I want a code example") remain ordinary evidence.
|
|
133
|
+
general = re.fullmatch(r'(.+?)\s+(?:replies|responses|answers)[.!]?', raw[prefix.end():].strip(), re.I)
|
|
134
|
+
if general is None or set(re.findall(r'\b\w+\b', general[1].lower())) - (vocabulary._STYLE_KEYWORDS | {'and', 'more'}):
|
|
135
|
+
return []
|
|
136
|
+
words.discard('i')
|
|
137
|
+
style_words = vocabulary._STYLE_KEYWORDS | vocabulary._DIRECTIVE_CUES | vocabulary._NEGATION | {'and', 'the', 't', 'a', 'an', 'of', 'with', 'so', 'being', 'all', 'future', 'my', 'me', 'actually'}
|
|
138
|
+
if words - style_words:
|
|
139
|
+
return [] # Content/task-specific instructions are not standing style corrections.
|
|
140
|
+
for alternatives in ((vocabulary._LENGTH_SHORT, vocabulary._LENGTH_LONG, vocabulary._LENGTH_MEDIUM),
|
|
141
|
+
(vocabulary._FORMAT_BULLETS, vocabulary._FORMAT_PROSE, vocabulary._FORMAT_TABLE),
|
|
142
|
+
(vocabulary._STYLE_FORMAL, vocabulary._STYLE_CASUAL)):
|
|
143
|
+
if sum(bool(words & option) for option in alternatives) > 1:
|
|
144
|
+
return []
|
|
145
|
+
if not learner.detect_directive(raw):
|
|
146
|
+
return []
|
|
147
|
+
return [('communication_style.' + key, value) for key, value in learner._parse_all(raw)]
|
|
148
|
+
|
|
149
|
+
def preferences(self, *, history=False):
|
|
150
|
+
from apsimo.turns.idempotency import source_message_hash
|
|
151
|
+
with closing(self.ledger._connect()) as conn:
|
|
152
|
+
heads = {r[0]: r[1] for r in conn.execute('SELECT pref_key,latest_event_id FROM self_preference_keys WHERE owner_id=?', (self.owner_id,))}
|
|
153
|
+
query = '''SELECT p.*,s.session_id,s.messages_json FROM self_preference_events p
|
|
154
|
+
JOIN turn_sources s ON s.turn_id=p.source_turn_id
|
|
155
|
+
WHERE p.owner_id=? AND s.contact_id=? AND s.scope='person' '''
|
|
156
|
+
if not history:
|
|
157
|
+
query += 'AND p.id IN (SELECT latest_event_id FROM self_preference_keys WHERE owner_id=p.owner_id) '
|
|
158
|
+
query += 'ORDER BY p.source_at DESC,p.id DESC'
|
|
159
|
+
if history:
|
|
160
|
+
query += ' LIMIT 100'
|
|
161
|
+
rows = conn.execute(query, (self.owner_id, self.owner_id)).fetchall()
|
|
162
|
+
result, seen = [], set()
|
|
163
|
+
for row in rows:
|
|
164
|
+
if row['message_hash'] not in {source_message_hash(row['session_id'], m) for m in json.loads(row['messages_json'])}:
|
|
165
|
+
continue
|
|
166
|
+
if not history and (row['pref_key'] in seen or row['id'] != heads.get(row['pref_key'])):
|
|
167
|
+
continue
|
|
168
|
+
seen.add(row['pref_key'])
|
|
169
|
+
result.append({key: row[key] for key in ('id', 'pref_key', 'source_turn_id', 'message_hash', 'source_at', 'supersedes')} | {'value': json.loads(row['value_json']), 'basis': 'owner_correction'})
|
|
170
|
+
return result
|
|
171
|
+
|
|
172
|
+
def tracked_keys(self):
|
|
173
|
+
with closing(self.ledger._connect()) as conn:
|
|
174
|
+
return {r[0] for r in conn.execute('SELECT pref_key FROM self_preference_keys WHERE owner_id=?', (self.owner_id,))}
|
|
175
|
+
|
|
176
|
+
def opinions(self, *, history=False):
|
|
177
|
+
"""Retained automatic revisions are inspectable, never governing."""
|
|
178
|
+
with closing(self.ledger._connect()) as conn:
|
|
179
|
+
query = ('SELECT * FROM self_opinion_revisions ORDER BY id DESC LIMIT 100' if history else
|
|
180
|
+
'SELECT * FROM self_opinion_revisions WHERE id IN (SELECT max(id) FROM self_opinion_revisions GROUP BY domain) ORDER BY domain')
|
|
181
|
+
rows = conn.execute(query).fetchall()
|
|
182
|
+
return [dict(row) | {'basis': json.loads(row['basis_json']),
|
|
183
|
+
'status': 'legacy_non_governing', 'governing': False} for row in rows]
|
|
184
|
+
|
|
185
|
+
def rank(self, initiatives, *, competence=None, load=None):
|
|
186
|
+
# competence is retained as a call-compatibility argument, never consumed.
|
|
187
|
+
initiatives = [copy(item) for item in initiatives] # no compounding on cached engine candidates
|
|
188
|
+
with closing(self.ledger._connect()) as conn, conn:
|
|
189
|
+
conn.execute('BEGIN IMMEDIATE')
|
|
190
|
+
overrides = {row['pref_key'].removeprefix('initiative.'): row for row in self.preferences() if row['pref_key'].startswith('initiative.')}
|
|
191
|
+
decisions = []
|
|
192
|
+
for item in initiatives:
|
|
193
|
+
domain = getattr(item.type, 'value', str(item.type))
|
|
194
|
+
original = float(item.priority)
|
|
195
|
+
override = overrides.get(domain)
|
|
196
|
+
weight = float(override['value']) if override else 1.0
|
|
197
|
+
# Due/urgent and non-research work keeps its existing urgency.
|
|
198
|
+
applied = override is not None and domain in DOMAINS and original < 0.9
|
|
199
|
+
item.priority = round(max(0.0, min(0.89, original * weight)), 4) if applied else original
|
|
200
|
+
decisions.append({'initiative_id': str(item.id), 'domain': domain, 'original_priority': original,
|
|
201
|
+
'description': str(getattr(item, 'description', '') or '')[:500],
|
|
202
|
+
'priority': item.priority, 'weight': weight if applied else 1.0,
|
|
203
|
+
'basis': 'owner_correction' if override and applied else 'unchanged',
|
|
204
|
+
'correction_id': override['id'] if override and applied else None,
|
|
205
|
+
'opinion_revision': None})
|
|
206
|
+
ranked = sorted(initiatives, key=lambda item: -item.priority)
|
|
207
|
+
snapshot = {'version': VERSION, 'load': dict(load or {}), 'decisions': decisions,
|
|
208
|
+
'ordered_ids': [str(item.id) for item in ranked], 'authority_changed': False,
|
|
209
|
+
'load_coverage': 'existing initiative/project/queue probes; missing sources are not proven idle'}
|
|
210
|
+
conn.execute('INSERT OR REPLACE INTO self_attention VALUES (1,?,?)', (_json(snapshot), self.clock()))
|
|
211
|
+
return ranked
|
|
212
|
+
|
|
213
|
+
def status(self):
|
|
214
|
+
with closing(self.ledger._connect()) as conn:
|
|
215
|
+
row = conn.execute('SELECT * FROM self_attention WHERE slot=1').fetchone()
|
|
216
|
+
attention = None
|
|
217
|
+
if row is not None:
|
|
218
|
+
snapshot = json.loads(row['snapshot_json'])
|
|
219
|
+
attention = snapshot | {'observed_at': row['observed_at'],
|
|
220
|
+
'age_seconds': max(0, round(self.clock() - row['observed_at'], 1)),
|
|
221
|
+
'historical_only': snapshot.get('version') != VERSION}
|
|
222
|
+
return {'kind': 'operational_working_perspective', 'preferences': self.preferences(),
|
|
223
|
+
'corrections': self.preferences(history=True), 'opinions': self.opinions(),
|
|
224
|
+
'judgments_enabled': self.judgments.enabled,
|
|
225
|
+
'judgments': self.judgments.revisions(), 'judgment_history': self.judgments.revisions(history=True),
|
|
226
|
+
'judgment_processing': self.judgments.processing(),
|
|
227
|
+
'appraisals': self.appraisals.view(self.owner_id, viewer_contact_id=self.owner_id,
|
|
228
|
+
history=True, limit=10),
|
|
229
|
+
'opinion_history': self.opinions(history=True), 'automatic_weighting': 'retired', 'attention': attention}
|
|
230
|
+
|
|
231
|
+
def brief(self, query='', *, source_ids=None):
|
|
232
|
+
lines = []
|
|
233
|
+
for pref in self.preferences():
|
|
234
|
+
if pref['pref_key'].startswith('initiative.'):
|
|
235
|
+
lines.append(f"Owner correction: {pref['pref_key']} priority weight {pref['value']:.2f}; source turn:{pref['source_turn_id']}; applies only to optional research ordering.")
|
|
236
|
+
if source_ids is not None:
|
|
237
|
+
source_ids.append(pref['source_turn_id'])
|
|
238
|
+
state = self.status()['attention']
|
|
239
|
+
if state is not None and not state['historical_only']:
|
|
240
|
+
lines.append(f"Last initiative ranking, {state['age_seconds']:g}s ago: " + ', '.join(state['ordered_ids'][:8]) + '. This is a decision snapshot, not current liveness.')
|
|
241
|
+
if lines:
|
|
242
|
+
lines.append('Only explicit owner preferences adjust these priorities. Runtime history establishes neither output quality nor the competence of the current model; it grants no authority.')
|
|
243
|
+
judgments = self.judgments.brief(query, source_ids=source_ids)
|
|
244
|
+
if judgments:
|
|
245
|
+
lines.append(judgments)
|
|
246
|
+
return '\n'.join(lines)
|