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,486 @@
|
|
|
1
|
+
"""Scoped execution observations in the existing turn ledger.
|
|
2
|
+
|
|
3
|
+
This is a view of host observations, never an execution lock or authority grant.
|
|
4
|
+
Expired leases mean unknown liveness. Operational storage contains no transcript
|
|
5
|
+
text. A fresh scoped read can associate a root execution with its admitted input.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from contextlib import closing
|
|
10
|
+
import sqlite3
|
|
11
|
+
import json
|
|
12
|
+
import time
|
|
13
|
+
|
|
14
|
+
from apsimo import get_state_dir
|
|
15
|
+
from apsimo.turns import get_turn_idempotency_ledger
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ExecutionRegistry:
|
|
19
|
+
def __init__(self, ledger, *, clock=time.time):
|
|
20
|
+
self.ledger = ledger
|
|
21
|
+
self.clock = clock
|
|
22
|
+
with closing(ledger._connect()) as conn, conn:
|
|
23
|
+
conn.execute("""CREATE TABLE IF NOT EXISTS execution_observations (
|
|
24
|
+
execution_id TEXT PRIMARY KEY,
|
|
25
|
+
principal_id TEXT NOT NULL,
|
|
26
|
+
contact_id TEXT NOT NULL,
|
|
27
|
+
session_id TEXT NOT NULL,
|
|
28
|
+
turn_id TEXT NOT NULL,
|
|
29
|
+
parent_execution_id TEXT NOT NULL,
|
|
30
|
+
platform TEXT NOT NULL,
|
|
31
|
+
state TEXT NOT NULL,
|
|
32
|
+
phase TEXT NOT NULL,
|
|
33
|
+
tool_name TEXT NOT NULL,
|
|
34
|
+
sequence INTEGER NOT NULL,
|
|
35
|
+
first_observed_at REAL NOT NULL,
|
|
36
|
+
last_observed_at REAL NOT NULL,
|
|
37
|
+
lease_until REAL NOT NULL
|
|
38
|
+
)""")
|
|
39
|
+
conn.execute("CREATE INDEX IF NOT EXISTS executions_contact_state ON execution_observations(contact_id, state, last_observed_at)")
|
|
40
|
+
|
|
41
|
+
# An adjunct keeps the predecessor's positional INSERT compatible
|
|
42
|
+
# during rollback. Request metadata expires with operational rows.
|
|
43
|
+
conn.execute("""CREATE TABLE IF NOT EXISTS execution_runtime_observations (
|
|
44
|
+
execution_id TEXT PRIMARY KEY, metadata_json TEXT NOT NULL
|
|
45
|
+
)""")
|
|
46
|
+
|
|
47
|
+
def observe(self, value: dict, *, principal_id: str, contact_id: str) -> dict:
|
|
48
|
+
from apsimo.self_model.execution_forecasts import safe_reconcile
|
|
49
|
+
safe_reconcile(self, contact_id)
|
|
50
|
+
now = self.clock()
|
|
51
|
+
immutable = (principal_id, contact_id, value["session_id"], value["turn_id"], value["parent_execution_id"], value["platform"])
|
|
52
|
+
with closing(self.ledger._connect()) as conn, conn:
|
|
53
|
+
conn.execute("BEGIN IMMEDIATE")
|
|
54
|
+
previous = conn.execute("SELECT * FROM execution_observations WHERE execution_id=?", (value["execution_id"],)).fetchone()
|
|
55
|
+
if previous:
|
|
56
|
+
actual = tuple(previous[key] for key in ("principal_id", "contact_id", "session_id", "turn_id", "parent_execution_id", "platform"))
|
|
57
|
+
if actual != immutable:
|
|
58
|
+
raise ValueError("execution_scope_conflict")
|
|
59
|
+
# A late API/tool callback cannot reopen a completed execution.
|
|
60
|
+
if previous["state"] != "observed" or value["sequence"] <= previous["sequence"]:
|
|
61
|
+
return {"accepted": False, "reason": "superseded_observation"}
|
|
62
|
+
elif value["parent_execution_id"]:
|
|
63
|
+
parent = conn.execute("SELECT principal_id, contact_id FROM execution_observations WHERE execution_id=?", (value["parent_execution_id"],)).fetchone()
|
|
64
|
+
if not parent or tuple(parent) != (principal_id, contact_id):
|
|
65
|
+
raise ValueError("parent_scope_unavailable")
|
|
66
|
+
conn.execute("""INSERT INTO execution_observations VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
67
|
+
ON CONFLICT(execution_id) DO UPDATE SET
|
|
68
|
+
state=excluded.state, phase=excluded.phase, tool_name=excluded.tool_name,
|
|
69
|
+
sequence=excluded.sequence, last_observed_at=excluded.last_observed_at,
|
|
70
|
+
lease_until=excluded.lease_until""",
|
|
71
|
+
(value["execution_id"], *immutable, value["state"], value["phase"], value["tool_name"], value["sequence"], now, now, now + 120.0))
|
|
72
|
+
from apsimo.self_model.execution_forecasts import accumulate
|
|
73
|
+
old_runtime = conn.execute('SELECT metadata_json FROM execution_runtime_observations WHERE execution_id=?',
|
|
74
|
+
(value['execution_id'],)).fetchone()
|
|
75
|
+
metadata = accumulate(json.loads(old_runtime[0]) if old_runtime else None,
|
|
76
|
+
value, previous, now)
|
|
77
|
+
inputs = value.get('input_refs')
|
|
78
|
+
if inputs:
|
|
79
|
+
if value['parent_execution_id'] or value['platform'] in {'cron', 'background_review'}:
|
|
80
|
+
raise ValueError('root_execution_input_required')
|
|
81
|
+
if previous:
|
|
82
|
+
if metadata.get('input_refs') != inputs:
|
|
83
|
+
raise ValueError('execution_input_binding_conflict')
|
|
84
|
+
else:
|
|
85
|
+
self.ledger._resolve_input_dependencies(conn, contact_id, value['session_id'], inputs)
|
|
86
|
+
# References expire with these operational observations.
|
|
87
|
+
# Source text remains only in the canonical source store.
|
|
88
|
+
metadata['input_refs'] = inputs
|
|
89
|
+
conn.execute('INSERT OR REPLACE INTO execution_runtime_observations VALUES (?,?)',
|
|
90
|
+
(value['execution_id'], json.dumps(metadata, separators=(',', ':'))))
|
|
91
|
+
# Metadata is operational and bounded in time, not another memory archive.
|
|
92
|
+
conn.execute("DELETE FROM execution_observations WHERE last_observed_at < ?", (now - 7 * 86400,))
|
|
93
|
+
conn.execute('DELETE FROM execution_runtime_observations WHERE execution_id NOT IN (SELECT execution_id FROM execution_observations)')
|
|
94
|
+
from apsimo.self_model.execution_forecasts import safe_observe
|
|
95
|
+
forecast = safe_observe(self, value['execution_id'], contact_id)
|
|
96
|
+
return {"accepted": True, "lease_seconds": 120, **({'forecast': forecast} if forecast else {})}
|
|
97
|
+
|
|
98
|
+
def view(self, *, contact_id: str, owner: bool = False, session_id: str = "", limit: int = 20,
|
|
99
|
+
include_ancestors: bool = False, include_inputs: bool = True) -> dict:
|
|
100
|
+
if owner:
|
|
101
|
+
from apsimo.self_model.execution_forecasts import safe_reconcile
|
|
102
|
+
safe_reconcile(self, contact_id)
|
|
103
|
+
now = self.clock()
|
|
104
|
+
clauses = ["state='observed'", "last_observed_at >= ?"]
|
|
105
|
+
args: list = [now - 7 * 86400]
|
|
106
|
+
if not owner:
|
|
107
|
+
# Guest context is conversation scoped until cross-surface visibility
|
|
108
|
+
# is separately attested. Knowing a contact ID is not such evidence.
|
|
109
|
+
clauses.extend(["contact_id=?", "session_id=?"])
|
|
110
|
+
args.extend([contact_id, session_id])
|
|
111
|
+
where = " AND ".join(clauses)
|
|
112
|
+
columns = ("execution_id, contact_id, session_id, turn_id, parent_execution_id, platform, phase, tool_name, last_observed_at, lease_until, "
|
|
113
|
+
"(SELECT metadata_json FROM execution_runtime_observations r WHERE r.execution_id=execution_observations.execution_id) metadata_json")
|
|
114
|
+
with closing(self.ledger._connect()) as conn:
|
|
115
|
+
conn.execute("BEGIN")
|
|
116
|
+
total = conn.execute("SELECT count(*) FROM execution_observations WHERE " + where, args).fetchone()[0]
|
|
117
|
+
rows = conn.execute("SELECT " + columns + " FROM execution_observations WHERE " + where + " ORDER BY last_observed_at DESC, execution_id LIMIT ?", [*args, limit]).fetchall()
|
|
118
|
+
if owner and include_ancestors:
|
|
119
|
+
# Fetch ancestors from the same scoped snapshot before the final
|
|
120
|
+
# prompt budget. A quiet parent may precede many active siblings.
|
|
121
|
+
# Each row has one parent; a family longer than eight cannot fit.
|
|
122
|
+
seen = {row["execution_id"] for row in rows}
|
|
123
|
+
frontier = rows
|
|
124
|
+
for _ in range(min(limit, 8)):
|
|
125
|
+
missing = {row["parent_execution_id"] for row in frontier
|
|
126
|
+
if row["parent_execution_id"] and row["parent_execution_id"] not in seen}
|
|
127
|
+
if not missing:
|
|
128
|
+
break
|
|
129
|
+
seen.update(missing)
|
|
130
|
+
placeholders = ",".join("?" for _ in missing)
|
|
131
|
+
frontier = conn.execute("SELECT " + columns + " FROM execution_observations WHERE "
|
|
132
|
+
+ where + " AND execution_id IN (" + placeholders + ")",
|
|
133
|
+
[*args, *sorted(missing)]).fetchall()
|
|
134
|
+
rows.extend(frontier)
|
|
135
|
+
items = []
|
|
136
|
+
for row in rows:
|
|
137
|
+
item = dict(row)
|
|
138
|
+
subject = item.pop('contact_id')
|
|
139
|
+
metadata = json.loads(item.pop('metadata_json') or '{}')
|
|
140
|
+
item['request_input'] = {'status': 'unbound'}
|
|
141
|
+
if include_inputs and metadata.get('input_refs'):
|
|
142
|
+
item['request_input'] = {'status': 'unavailable_in_viewer_scope'}
|
|
143
|
+
if subject == contact_id:
|
|
144
|
+
try:
|
|
145
|
+
from apsimo.turns.source_read import input_excerpt
|
|
146
|
+
item['request_input'] = input_excerpt(self.ledger, contact_id=contact_id,
|
|
147
|
+
session_id=session_id, refs=metadata['input_refs'])
|
|
148
|
+
except (ValueError, OSError, sqlite3.Error):
|
|
149
|
+
item['request_input'] = {'status': 'source_unavailable_or_changed'}
|
|
150
|
+
item["observation_age_seconds"] = round(max(0.0, now - item["last_observed_at"]), 1)
|
|
151
|
+
item["liveness"] = "recently_observed" if item.pop("lease_until") > now else "unknown"
|
|
152
|
+
if owner:
|
|
153
|
+
from apsimo.self_model.execution_forecasts import project
|
|
154
|
+
item['forecast'] = project(self, item['execution_id'], contact_id)
|
|
155
|
+
items.append(item)
|
|
156
|
+
return {"schema": "ColonyExecutionViewV1", "items": items, "total": total,
|
|
157
|
+
"truncated": total > len(items), "coverage": "registered Hermes turns only",
|
|
158
|
+
"commitments_enforced": False, "complete": False, "observed_at": now}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def registry() -> ExecutionRegistry:
|
|
162
|
+
return ExecutionRegistry(get_turn_idempotency_ledger(get_state_dir()))
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _work_groups(view):
|
|
166
|
+
return [('local_work', view.get('local_work', {})),
|
|
167
|
+
('native_kanban', view.get('native_kanban', {})),
|
|
168
|
+
('reported_worker', view.get('reported_worker', {})),
|
|
169
|
+
('execution', view), ('worker_work', view.get('worker_work', {})),
|
|
170
|
+
('native_cron', view.get('native_cron', {}))]
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def work_source_coverage(view):
|
|
174
|
+
"""Coverage of selected readers, never a count of distinct undertakings.
|
|
175
|
+
|
|
176
|
+
The same native task can appear in an initiative association and a board.
|
|
177
|
+
Totals must not be summed; absent readers do not establish idle workers.
|
|
178
|
+
"""
|
|
179
|
+
result = {}
|
|
180
|
+
for source, group in _work_groups(view):
|
|
181
|
+
if not group:
|
|
182
|
+
result[source] = {'status': 'not_observed', 'items_returned': 0,
|
|
183
|
+
'recent_returned': 0}
|
|
184
|
+
continue
|
|
185
|
+
unavailable = group.get('available') is False or group.get('unavailable') is True
|
|
186
|
+
partial = bool(group.get('partial') or any(row.get('available') is False
|
|
187
|
+
for row in group.get('items', [])))
|
|
188
|
+
coverage = {'status': 'unavailable' if unavailable else 'partial' if partial else 'observed',
|
|
189
|
+
'items_returned': len(group.get('items', [])),
|
|
190
|
+
'recent_returned': len(group.get('recent', [])),
|
|
191
|
+
'truncated': bool(group.get('truncated')),
|
|
192
|
+
'recent_truncated': bool(group.get('recent_truncated'))}
|
|
193
|
+
for key in ('total', 'recent_total'):
|
|
194
|
+
if type(group.get(key)) is int and group[key] >= 0:
|
|
195
|
+
coverage[key] = group[key]
|
|
196
|
+
for key in ('reason', 'source_home_id', 'selection', 'observed_at'):
|
|
197
|
+
if key in group:
|
|
198
|
+
coverage[key] = group[key]
|
|
199
|
+
if isinstance(group.get('state_counts'), dict):
|
|
200
|
+
coverage['state_counts'] = {state: count for state, count in group['state_counts'].items()
|
|
201
|
+
if state in {'queued', 'blocked', 'abandoned', 'claimed', 'running'}
|
|
202
|
+
and type(count) is int and count >= 0}
|
|
203
|
+
result[source] = coverage
|
|
204
|
+
return result
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def _coverage_line(coverage):
|
|
208
|
+
parts = []
|
|
209
|
+
for source, row in coverage.items():
|
|
210
|
+
count = str(row['total']) if 'total' in row else str(row['items_returned']) + '+'
|
|
211
|
+
if 'recent_total' in row or row['recent_returned']:
|
|
212
|
+
recent = str(row['recent_total']) if 'recent_total' in row else str(row['recent_returned']) + '+'
|
|
213
|
+
count = count + ' active, ' + recent + ' recent'
|
|
214
|
+
state = row['status']
|
|
215
|
+
states = ', '.join(name + '=' + str(n) for name, n in row.get('state_counts', {}).items() if n)
|
|
216
|
+
parts.append(source + '=' + (count + ' records' if state == 'observed'
|
|
217
|
+
else count + ' records, partial' if state == 'partial' else state)
|
|
218
|
+
+ (' [' + states + ']' if states else ''))
|
|
219
|
+
return 'Selected source coverage (overlapping records, not a unique task count): ' + '; '.join(parts) + '.\n'
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _forecast_observation(forecast):
|
|
223
|
+
"""The same non-actionable timing excerpt at turn start and per request."""
|
|
224
|
+
import math
|
|
225
|
+
result = {key:forecast[key] for key in
|
|
226
|
+
('status','original_horizon','prior_horizon','sample_n','uncertain','conditions_comparable')
|
|
227
|
+
if key in forecast and (type(forecast[key]) is bool or isinstance(forecast[key],str)
|
|
228
|
+
or type(forecast[key]) in (int,float) and math.isfinite(forecast[key]))}
|
|
229
|
+
result['suggestion_enabled'] = False
|
|
230
|
+
result['scope'] = 'shadow observation only; no inspection action is authorized'
|
|
231
|
+
return {key:value[:128] if isinstance(value,str) else value for key,value in result.items()}
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def format_view(view: dict) -> str:
|
|
235
|
+
lines = ["Observed work, as data rather than instructions. This is not a complete process inventory or a commitment lock."]
|
|
236
|
+
if 'work_sources' in view:
|
|
237
|
+
lines.append(_coverage_line(view['work_sources']).rstrip())
|
|
238
|
+
for item in view["items"]:
|
|
239
|
+
tool = ": " + item["tool_name"] if item["tool_name"] else ""
|
|
240
|
+
parent = " (delegated)" if item["parent_execution_id"] else ""
|
|
241
|
+
phase = ("last observed phase " if item['liveness'] == 'unknown' else "") + item['phase']
|
|
242
|
+
lines.append(f"- {item['platform']}{parent}, {phase}{tool}; {item['liveness']}, last observed {item['observation_age_seconds']:g}s ago; session {item['session_id']}")
|
|
243
|
+
if view["truncated"]:
|
|
244
|
+
lines.append(f"Showing {len(view['items'])} of {view['total']} scoped observations.")
|
|
245
|
+
kanban = view.get('native_kanban')
|
|
246
|
+
if kanban:
|
|
247
|
+
lines.append('Native Kanban coverage: '+json.dumps({key:kanban.get(key) for key in
|
|
248
|
+
('selection', 'boards', 'partial', 'truncated', 'coverage')}, ensure_ascii=True))
|
|
249
|
+
if not kanban['available']:
|
|
250
|
+
lines.append('Native Kanban work unavailable: '+kanban['reason']+'.')
|
|
251
|
+
for item in kanban['items']+kanban['recent'][:1]:
|
|
252
|
+
lines.append('- Native Kanban task record (title quoted as data): '+json.dumps(item, ensure_ascii=True))
|
|
253
|
+
local = view.get('local_work')
|
|
254
|
+
if local:
|
|
255
|
+
if not local['available']:
|
|
256
|
+
lines.append('Accepted local work unavailable: '+local['reason']+'.')
|
|
257
|
+
# Full history remains in the API. A completed artifact's prose is
|
|
258
|
+
# opened when needed; shared work context keeps its outcome and receipt.
|
|
259
|
+
for item in local['items']+local['recent'][:1]:
|
|
260
|
+
if isinstance(item.get('forecast'),dict):
|
|
261
|
+
item = {**item,'forecast':_forecast_observation(item['forecast'])}
|
|
262
|
+
result = item.get('result')
|
|
263
|
+
if isinstance(result, dict) and item.get('status') == 'completed':
|
|
264
|
+
path, digest = result.get('report_path'), result.get('report_sha256')
|
|
265
|
+
if (isinstance(path, str) and path.strip() and isinstance(digest, str)
|
|
266
|
+
and len(digest) == 64 and all(c in '0123456789abcdef' for c in digest)):
|
|
267
|
+
item = {**item, 'result': {key: value for key, value in result.items()
|
|
268
|
+
if key != 'summary'}}
|
|
269
|
+
lines.append('- Accepted local work and unverified draft: '+json.dumps(item, ensure_ascii=True))
|
|
270
|
+
for item in view.get('worker_work', {}).get('items', []):
|
|
271
|
+
lines.append('- Worker work: ' + json.dumps(item, ensure_ascii=True))
|
|
272
|
+
if view.get('worker_work', {}).get('unavailable'):
|
|
273
|
+
lines.append('Canonical worker work is temporarily unavailable.')
|
|
274
|
+
reported = view.get('reported_worker')
|
|
275
|
+
if reported:
|
|
276
|
+
lines.append('Local worker reports; process liveness and external effects are unverified.')
|
|
277
|
+
if not reported['available']:
|
|
278
|
+
lines.append('Local worker reports unavailable: '+reported['reason']+'.')
|
|
279
|
+
for item in reported['items']:
|
|
280
|
+
lines.append('- Reported worker status: '+json.dumps(item,ensure_ascii=True))
|
|
281
|
+
cron = view.get('native_cron')
|
|
282
|
+
if cron:
|
|
283
|
+
if not cron['available']:
|
|
284
|
+
lines.append('Native cron coverage unavailable: ' + cron['reason'] + '.')
|
|
285
|
+
else:
|
|
286
|
+
lines.append('Native cron records from selected profile ' + cron['source_home_id'] + '; process liveness and external effects unverified.')
|
|
287
|
+
for item in cron['items']:
|
|
288
|
+
lines.append('- Native cron work: ' + json.dumps(item, ensure_ascii=True))
|
|
289
|
+
for item in cron['recent']:
|
|
290
|
+
lines.append('- Recent native cron outcome: ' + json.dumps(item, ensure_ascii=True))
|
|
291
|
+
if cron['truncated']:
|
|
292
|
+
lines.append(f"Showing {len(cron['items'])} of {cron['total']} native active records.")
|
|
293
|
+
return "\n".join(lines)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def request_work_context(view: dict, *, limit: int = 8, max_chars: int = 4000,
|
|
297
|
+
session_id: str = '') -> dict:
|
|
298
|
+
"""Fresh work records with optional scoped excerpts of admitted input."""
|
|
299
|
+
import json
|
|
300
|
+
import math
|
|
301
|
+
from itertools import zip_longest
|
|
302
|
+
|
|
303
|
+
def line_for(row):
|
|
304
|
+
# JSON still decodes to the exact quote. A literal close marker inside
|
|
305
|
+
# source text must not terminate the adapter's outer instruction block.
|
|
306
|
+
return json.dumps(row, sort_keys=True, ensure_ascii=True).replace(
|
|
307
|
+
'[/colony-work-request-v1]', r'\u005b/colony-work-request-v1\u005d') + '\n'
|
|
308
|
+
|
|
309
|
+
groups = _work_groups(view)
|
|
310
|
+
coverage = work_source_coverage(view)
|
|
311
|
+
keys = ('initiative_id', 'commitment_id', 'native_job_id', 'native_execution_id',
|
|
312
|
+
'execution_backend', 'native_board', 'native_task_id', 'native_run_id', 'native_status', 'attempt_count',
|
|
313
|
+
'native_run_status', 'goal_mode', 'goal_max_turns', 'heartbeat_age_seconds', 'assignee',
|
|
314
|
+
'terminal_record_at',
|
|
315
|
+
'execution_id', 'parent_execution_id', 'session_id', 'turn_id',
|
|
316
|
+
'job_id', 'job_type', 'worker_id', 'claim_attempt_id', 'claim_expires_at', 'claim_unexpired',
|
|
317
|
+
'task_id', 'parent_task_id', 'id', 'kind', 'task_class', 'label', 'name', 'platform',
|
|
318
|
+
'status', 'state', 'phase', 'tool_name', 'liveness', 'freshness',
|
|
319
|
+
'status_sha256',
|
|
320
|
+
'observation_age_seconds', 'record_age_seconds', 'age_seconds')
|
|
321
|
+
grouped_rows = []
|
|
322
|
+
grouped_recent = []
|
|
323
|
+
stale_executions = []
|
|
324
|
+
unavailable = []
|
|
325
|
+
truncated = False
|
|
326
|
+
for source, group in groups:
|
|
327
|
+
rows = []
|
|
328
|
+
recent = []
|
|
329
|
+
if group.get('available') is False or group.get('unavailable') is True:
|
|
330
|
+
unavailable.append(source)
|
|
331
|
+
truncated |= bool(group.get('truncated') or group.get('recent_truncated')
|
|
332
|
+
or len(group.get('recent', [])) > 1)
|
|
333
|
+
for is_recent, row in [(False, row) for row in group.get('items', [])] + [
|
|
334
|
+
(True, row) for row in group.get('recent', [])[:1]]:
|
|
335
|
+
is_recent |= source == 'reported_worker' and row.get('record_kind') == 'terminal_report'
|
|
336
|
+
item = {'source': source}
|
|
337
|
+
if type(row.get('available')) is bool:
|
|
338
|
+
item['available'] = row['available']
|
|
339
|
+
for key in keys:
|
|
340
|
+
value = row.get(key)
|
|
341
|
+
if isinstance(value, str) and value:
|
|
342
|
+
item[key] = value[:256 if key.endswith('_id') else 128]
|
|
343
|
+
elif key in {'goal_mode', 'claim_unexpired'} and type(value) is bool:
|
|
344
|
+
item[key] = value
|
|
345
|
+
elif type(value) in (int, float) and math.isfinite(value):
|
|
346
|
+
item[key] = value
|
|
347
|
+
home_id = row.get('source_home_id') or group.get('source_home_id')
|
|
348
|
+
if isinstance(home_id, str) and len(home_id) == 64 and all(c in '0123456789abcdef' for c in home_id):
|
|
349
|
+
item['source_home_id'] = home_id
|
|
350
|
+
if source == 'reported_worker':
|
|
351
|
+
from apsimo.turns.reported_workers import work_details
|
|
352
|
+
item.update(work_details(row))
|
|
353
|
+
if row.get('record_kind') in {'terminal_report', 'progress_report'}:
|
|
354
|
+
item['record_kind'] = row['record_kind']
|
|
355
|
+
result = row.get('result')
|
|
356
|
+
if isinstance(result, dict):
|
|
357
|
+
digest = result.get('report_sha256')
|
|
358
|
+
if isinstance(digest, str) and len(digest) == 64 and all(c in '0123456789abcdef' for c in digest):
|
|
359
|
+
item['report_sha256'] = digest
|
|
360
|
+
assessment = row.get('semantic_review')
|
|
361
|
+
if isinstance(assessment,dict):
|
|
362
|
+
item['semantic_review'] = {key:assessment[key] for key in
|
|
363
|
+
('status','assessment_sha256','finding_count','detection','quality_credit','warning')
|
|
364
|
+
if key in assessment and (assessment[key] is None or type(assessment[key]) in (str,int,bool))}
|
|
365
|
+
for key,value in item['semantic_review'].items():
|
|
366
|
+
if isinstance(value,str):
|
|
367
|
+
item['semantic_review'][key] = value[:256]
|
|
368
|
+
forecast = row.get('forecast')
|
|
369
|
+
if isinstance(forecast,dict):
|
|
370
|
+
# Keep shadow timing observational. Raw source revisions, model
|
|
371
|
+
# configuration, evaluation criteria and counterfactual scores
|
|
372
|
+
# remain in the owner API, not in ordinary model requests.
|
|
373
|
+
item['forecast'] = _forecast_observation(forecast)
|
|
374
|
+
if source == 'execution' and item.get('liveness') == 'unknown':
|
|
375
|
+
# An expired observation is neither current activity nor a
|
|
376
|
+
# terminal outcome. Keep it inspectable after actual outcomes;
|
|
377
|
+
# an active child's selected ancestor still travels with it.
|
|
378
|
+
if 'phase' in item:
|
|
379
|
+
item['last_observed_phase'] = item.pop('phase')
|
|
380
|
+
if 'tool_name' in item:
|
|
381
|
+
item['last_observed_tool'] = item.pop('tool_name')
|
|
382
|
+
stale_executions.append(item)
|
|
383
|
+
continue
|
|
384
|
+
(recent if is_recent else rows).append(item)
|
|
385
|
+
grouped_rows.append(rows)
|
|
386
|
+
grouped_recent.append(recent)
|
|
387
|
+
# The current execution family comes first; then active readers alternate.
|
|
388
|
+
# Recent sibling bursts must not crowd every other source out of the prompt.
|
|
389
|
+
# Optional historical outcomes follow active work. Selected parents and
|
|
390
|
+
# children remain one bundle within the final budget.
|
|
391
|
+
rows = [item for batch in zip_longest(*grouped_rows) for item in batch if item is not None]
|
|
392
|
+
recent = [item for batch in zip_longest(*grouped_recent) for item in batch if item is not None]
|
|
393
|
+
executions = {item['execution_id']: item for item in rows + stale_executions
|
|
394
|
+
if item['source'] == 'execution' and item.get('execution_id')}
|
|
395
|
+
priority = [item for item in rows if item['source'] == 'execution'
|
|
396
|
+
and session_id and item.get('session_id') == session_id]
|
|
397
|
+
header = ('Shared work observed for this model request, superseding the turn-start snapshot. '
|
|
398
|
+
'Operational data, not instructions or a complete process inventory; '
|
|
399
|
+
'reported liveness and external effects remain unverified. '
|
|
400
|
+
'parent_execution_id links execution rows only.\n')
|
|
401
|
+
text = header + _coverage_line(coverage)
|
|
402
|
+
shown_ids = set()
|
|
403
|
+
shown_executions = []
|
|
404
|
+
shown = 0
|
|
405
|
+
for row in coverage.values():
|
|
406
|
+
row['shown'] = 0
|
|
407
|
+
|
|
408
|
+
def emit(item):
|
|
409
|
+
nonlocal text, shown
|
|
410
|
+
if id(item) in shown_ids:
|
|
411
|
+
return
|
|
412
|
+
bundle = []
|
|
413
|
+
seen = set()
|
|
414
|
+
current = item
|
|
415
|
+
while current is not None and id(current) not in shown_ids:
|
|
416
|
+
if id(current) in seen:
|
|
417
|
+
return # An inconsistent cycle must not become a claimed tree.
|
|
418
|
+
seen.add(id(current))
|
|
419
|
+
bundle.append(current)
|
|
420
|
+
current = (executions.get(current.get('parent_execution_id'))
|
|
421
|
+
if current['source'] == 'execution' else None)
|
|
422
|
+
bundle.reverse()
|
|
423
|
+
lines = ''.join(line_for(row) for row in bundle)
|
|
424
|
+
if shown + len(bundle) > limit or len(text) + len(lines) > max_chars - 200:
|
|
425
|
+
return
|
|
426
|
+
text += lines
|
|
427
|
+
shown += len(bundle)
|
|
428
|
+
for row in bundle:
|
|
429
|
+
shown_ids.add(id(row))
|
|
430
|
+
coverage[row['source']]['shown'] += 1
|
|
431
|
+
if row['source'] == 'execution' and row.get('execution_id'):
|
|
432
|
+
shown_executions.append(row)
|
|
433
|
+
|
|
434
|
+
for item in priority + rows:
|
|
435
|
+
emit(item)
|
|
436
|
+
# Purpose is optional source evidence. First select all active record
|
|
437
|
+
# families with the existing fair budget so long input cannot hide a queue.
|
|
438
|
+
originals = {item['execution_id']: item for item in view.get('items', []) if item.get('execution_id')}
|
|
439
|
+
provenance = [row.get('request_input', {}).get('_provenance', {}) for row in originals.values()
|
|
440
|
+
if row.get('request_input', {}).get('status') == 'admitted_input_excerpt']
|
|
441
|
+
source_scope = {(row.get('contact_id'), row.get('watermark')) for row in provenance}
|
|
442
|
+
input_sources = {}
|
|
443
|
+
input_guards = {}
|
|
444
|
+
input_note = ('Input excerpts identify original requests, not performance or child assignments; '
|
|
445
|
+
'partial excerpts can omit task conditions.\n')
|
|
446
|
+
for item in shown_executions:
|
|
447
|
+
supplied = originals[item['execution_id']].get('request_input', {})
|
|
448
|
+
if supplied.get('status') != 'admitted_input_excerpt' or len(source_scope) != 1:
|
|
449
|
+
continue
|
|
450
|
+
old = line_for(item)
|
|
451
|
+
line = line_for({**item, 'request_input': {key: value for key, value in supplied.items()
|
|
452
|
+
if key != '_provenance'}})
|
|
453
|
+
note = '' if input_sources else input_note
|
|
454
|
+
if len(text) + len(line) - len(old) + len(note) <= max_chars - 200:
|
|
455
|
+
text = text.replace(old, line, 1)
|
|
456
|
+
text += note
|
|
457
|
+
for ref in supplied['_provenance']['source_refs']:
|
|
458
|
+
input_sources[(ref['source_id'], ref['source_version'])] = ref
|
|
459
|
+
for ref in supplied['_provenance']['unannotated_input_refs']:
|
|
460
|
+
input_guards[(ref['source_id'], ref['input_message_hash'])] = ref
|
|
461
|
+
else:
|
|
462
|
+
truncated = True
|
|
463
|
+
kanban = view.get('native_kanban')
|
|
464
|
+
if kanban:
|
|
465
|
+
board_coverage = {'source': 'native_kanban_coverage', 'selection': kanban.get('selection'),
|
|
466
|
+
'partial': kanban.get('partial'), 'complete': False,
|
|
467
|
+
'boards': [{k:board[k] for k in ('board','available','reason') if k in board}
|
|
468
|
+
for board in kanban.get('boards', [])]}
|
|
469
|
+
line = line_for(board_coverage)
|
|
470
|
+
if len(text)+len(line) <= max_chars-200:
|
|
471
|
+
text += line
|
|
472
|
+
else:
|
|
473
|
+
truncated = True
|
|
474
|
+
for item in recent + stale_executions:
|
|
475
|
+
emit(item)
|
|
476
|
+
truncated |= shown < len(rows) + len(recent) + len(stale_executions)
|
|
477
|
+
if unavailable:
|
|
478
|
+
text += 'Unavailable sources: ' + ', '.join(unavailable) + '.\n'
|
|
479
|
+
if truncated:
|
|
480
|
+
text += 'Additional operational records omitted.\n'
|
|
481
|
+
return {'schema': 'ColonyRequestWorkV1', 'observed_at': time.time(),
|
|
482
|
+
'text': text, 'truncated': truncated, 'work_sources': coverage,
|
|
483
|
+
'complete': False, **({'input_provenance': {
|
|
484
|
+
'contact_id': next(iter(source_scope))[0], 'watermark': next(iter(source_scope))[1],
|
|
485
|
+
'source_refs': list(input_sources.values()),
|
|
486
|
+
'unannotated_input_refs': list(input_guards.values())}} if input_sources else {})}
|