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,317 @@
|
|
|
1
|
+
"""Distributed Task Queue — core data models.
|
|
2
|
+
|
|
3
|
+
Defines the Job lifecycle, WorkerCapabilities, and supporting types
|
|
4
|
+
for the Colony hardware-aware distributed job scheduler.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import re
|
|
10
|
+
import uuid
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from datetime import datetime, timezone
|
|
13
|
+
from enum import Enum
|
|
14
|
+
from typing import Any, Dict, List, Optional
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
CANONICAL_JOB_ID_PATTERN = r"^[A-Za-z0-9][A-Za-z0-9_.:@/-]{0,191}$"
|
|
18
|
+
_CANONICAL_JOB_ID_RE = re.compile(CANONICAL_JOB_ID_PATTERN)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def is_canonical_job_id(value: Any) -> bool:
|
|
22
|
+
"""Return whether *value* is safe across queue/API/router runtimes."""
|
|
23
|
+
|
|
24
|
+
return isinstance(value, str) and bool(_CANONICAL_JOB_ID_RE.fullmatch(value))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class JobPriority(int, Enum):
|
|
28
|
+
"""Job scheduling priority. Higher value = higher priority."""
|
|
29
|
+
|
|
30
|
+
BACKGROUND = 0 # Maintenance, archival, non-urgent analysis
|
|
31
|
+
LOW = 10 # Research, exploration, long-running batch
|
|
32
|
+
NORMAL = 50 # Default priority
|
|
33
|
+
HIGH = 80 # User-initiated tasks, time-sensitive analysis
|
|
34
|
+
CRITICAL = 100 # System health, monitoring, security responses
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class JobStatus(str, Enum):
|
|
38
|
+
"""Job lifecycle states."""
|
|
39
|
+
|
|
40
|
+
QUEUED = "queued" # Waiting to be claimed
|
|
41
|
+
CLAIMED = "claimed" # Reserved by a worker, not yet started
|
|
42
|
+
RUNNING = "running" # Actively executing
|
|
43
|
+
COMPLETED = "completed" # Finished successfully
|
|
44
|
+
NEUTRAL = "neutral" # Finished without verified success/failure
|
|
45
|
+
FAILED = "failed" # Finished with error, may be retried
|
|
46
|
+
ABANDONED = "abandoned" # Worker died; eligible for redistribution
|
|
47
|
+
CANCELLED = "cancelled" # Explicitly cancelled
|
|
48
|
+
BLOCKED = "blocked" # Typed dependency/approval/boundary/governor hold
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class JobType(str, Enum):
|
|
52
|
+
"""Built-in job type categories."""
|
|
53
|
+
|
|
54
|
+
INFERENCE = "inference"
|
|
55
|
+
TRAINING = "training"
|
|
56
|
+
DATA_PROCESSING = "data_processing"
|
|
57
|
+
SYSTEM_MAINTENANCE = "system_maintenance"
|
|
58
|
+
RESEARCH = "research"
|
|
59
|
+
MONITORING = "monitoring"
|
|
60
|
+
SYNTHESIS = "synthesis"
|
|
61
|
+
THOUGHT = "thought" # bounded, read-only ThoughtJobV1 inference
|
|
62
|
+
DESKTOP = "desktop"
|
|
63
|
+
BROWSER = "browser"
|
|
64
|
+
CUSTOM = "custom"
|
|
65
|
+
AGENT_ACTION = "agent_action" # NEW: Hermes agent-executable initiatives (v0.13.0)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass
|
|
69
|
+
class JobCapabilityRequirement:
|
|
70
|
+
"""A single capability requirement for job assignment.
|
|
71
|
+
|
|
72
|
+
Attributes:
|
|
73
|
+
name: Capability name (e.g., "gpu", "cuda", "apple_silicon").
|
|
74
|
+
minimum: Optional minimum numeric threshold (e.g., min VRAM GB).
|
|
75
|
+
preferred: If True, prefer workers with this capability but don't
|
|
76
|
+
require it.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
name: str
|
|
80
|
+
minimum: Optional[float] = None
|
|
81
|
+
preferred: bool = False
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@dataclass
|
|
85
|
+
class JobResult:
|
|
86
|
+
"""Output produced by a completed job."""
|
|
87
|
+
|
|
88
|
+
job_id: str
|
|
89
|
+
worker_node_id: str
|
|
90
|
+
status: JobStatus
|
|
91
|
+
output: Dict[str, Any] = field(default_factory=dict)
|
|
92
|
+
error: Optional[str] = None
|
|
93
|
+
started_at: Optional[datetime] = None
|
|
94
|
+
completed_at: Optional[datetime] = None
|
|
95
|
+
duration_seconds: Optional[float] = None
|
|
96
|
+
claim_attempt_id: Optional[str] = None
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def succeeded(self) -> bool:
|
|
100
|
+
return self.status == JobStatus.COMPLETED
|
|
101
|
+
|
|
102
|
+
def elapsed(self) -> Optional[float]:
|
|
103
|
+
if self.started_at and self.completed_at:
|
|
104
|
+
return (self.completed_at - self.started_at).total_seconds()
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@dataclass
|
|
109
|
+
class Job:
|
|
110
|
+
"""A unit of work in the distributed task queue.
|
|
111
|
+
|
|
112
|
+
Attributes:
|
|
113
|
+
job_id: Globally unique identifier.
|
|
114
|
+
job_type: High-level category for routing and monitoring.
|
|
115
|
+
payload: Arbitrary job-specific parameters.
|
|
116
|
+
priority: Scheduling priority (higher = sooner).
|
|
117
|
+
capabilities: Hardware/software requirements for assignment.
|
|
118
|
+
deadline: Optional absolute deadline; jobs past deadline are
|
|
119
|
+
moved to FAILED without retry.
|
|
120
|
+
max_retries: Maximum number of FAILED → QUEUED re-queues.
|
|
121
|
+
retry_count: Current retry attempt number.
|
|
122
|
+
timeout_secs: Maximum wall-clock execution time.
|
|
123
|
+
depends_on: List of job_ids that must be COMPLETED first.
|
|
124
|
+
posted_by: node_id of the posting node.
|
|
125
|
+
posted_at: Timestamp when the job entered the queue.
|
|
126
|
+
status: Current job lifecycle state.
|
|
127
|
+
claimed_by: node_id of the worker that has claimed this job.
|
|
128
|
+
claimed_at: Timestamp of the most recent claim.
|
|
129
|
+
claim_attempt_id: Server-minted identity of the current/last claim.
|
|
130
|
+
claim_expires_at: Latest time the claim may enter RUNNING.
|
|
131
|
+
last_heartbeat: Timestamp of the worker's most recent heartbeat.
|
|
132
|
+
result: Final result (populated on completion or failure).
|
|
133
|
+
tags: Arbitrary key-value metadata for filtering.
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
job_id: str = field(default_factory=lambda: str(uuid.uuid4()))
|
|
137
|
+
job_type: JobType = JobType.CUSTOM
|
|
138
|
+
payload: Dict[str, Any] = field(default_factory=dict)
|
|
139
|
+
priority: JobPriority = JobPriority.NORMAL
|
|
140
|
+
capabilities: List[JobCapabilityRequirement] = field(default_factory=list)
|
|
141
|
+
deadline: Optional[datetime] = None
|
|
142
|
+
max_retries: int = 3
|
|
143
|
+
retry_count: int = 0
|
|
144
|
+
timeout_secs: float = 3600.0
|
|
145
|
+
depends_on: List[str] = field(default_factory=list)
|
|
146
|
+
posted_by: str = ""
|
|
147
|
+
posted_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
148
|
+
status: JobStatus = JobStatus.QUEUED
|
|
149
|
+
claimed_by: Optional[str] = None
|
|
150
|
+
claimed_at: Optional[datetime] = None
|
|
151
|
+
claim_attempt_id: Optional[str] = None
|
|
152
|
+
claim_expires_at: Optional[datetime] = None
|
|
153
|
+
last_heartbeat: Optional[datetime] = None
|
|
154
|
+
result: Optional[JobResult] = None
|
|
155
|
+
tags: Dict[str, str] = field(default_factory=dict)
|
|
156
|
+
|
|
157
|
+
def is_terminal(self) -> bool:
|
|
158
|
+
return self.status in {
|
|
159
|
+
JobStatus.COMPLETED,
|
|
160
|
+
JobStatus.NEUTRAL,
|
|
161
|
+
JobStatus.FAILED,
|
|
162
|
+
JobStatus.CANCELLED,
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
def is_expired(self) -> bool:
|
|
166
|
+
if self.deadline is None:
|
|
167
|
+
return False
|
|
168
|
+
return datetime.now(timezone.utc) > self.deadline
|
|
169
|
+
|
|
170
|
+
def can_retry(self) -> bool:
|
|
171
|
+
return (
|
|
172
|
+
self.status in {JobStatus.FAILED, JobStatus.ABANDONED}
|
|
173
|
+
and self.retry_count < self.max_retries
|
|
174
|
+
and not self.is_expired()
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
def required_capabilities(self) -> List[str]:
|
|
178
|
+
return [r.name for r in self.capabilities if not r.preferred]
|
|
179
|
+
|
|
180
|
+
def preferred_capabilities(self) -> List[str]:
|
|
181
|
+
return [r.name for r in self.capabilities if r.preferred]
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@dataclass
|
|
185
|
+
class WorkerCapabilities:
|
|
186
|
+
"""Hardware and software capabilities advertised by a worker node.
|
|
187
|
+
|
|
188
|
+
Attributes:
|
|
189
|
+
node_id: Mesh node identifier.
|
|
190
|
+
capabilities: Set of capability names this node provides.
|
|
191
|
+
capacity: Numeric capacity map (e.g., {"gpu_vram_gb": 80.0,
|
|
192
|
+
"ram_gb": 192.0, "cpu_cores": 64}).
|
|
193
|
+
max_concurrent: Maximum number of jobs this worker runs simultaneously.
|
|
194
|
+
job_types: Job types this node is willing to accept. Empty set
|
|
195
|
+
means all types are accepted.
|
|
196
|
+
available: Whether the node is currently accepting new jobs.
|
|
197
|
+
load: Current load factor 0.0–1.0.
|
|
198
|
+
registered_at: When this worker last registered with the scheduler.
|
|
199
|
+
last_seen: Timestamp of most recent heartbeat.
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
node_id: str
|
|
203
|
+
capabilities: set = field(default_factory=set)
|
|
204
|
+
capacity: Dict[str, float] = field(default_factory=dict)
|
|
205
|
+
max_concurrent: int = 4
|
|
206
|
+
job_types: set = field(default_factory=set)
|
|
207
|
+
available: bool = True
|
|
208
|
+
load: float = 0.0
|
|
209
|
+
registered_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
210
|
+
last_seen: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
211
|
+
|
|
212
|
+
def can_accept(self, job: Job) -> bool:
|
|
213
|
+
"""Return True if this worker satisfies all required capabilities."""
|
|
214
|
+
required = set(job.required_capabilities())
|
|
215
|
+
if not required.issubset(self.capabilities):
|
|
216
|
+
return False
|
|
217
|
+
if self.job_types and job.job_type not in self.job_types:
|
|
218
|
+
return False
|
|
219
|
+
if not self.available:
|
|
220
|
+
return False
|
|
221
|
+
if self.load >= 1.0:
|
|
222
|
+
return False
|
|
223
|
+
for req in job.capabilities:
|
|
224
|
+
if req.minimum is not None and not req.preferred:
|
|
225
|
+
actual = self.capacity.get(req.name, 0.0)
|
|
226
|
+
if actual < req.minimum:
|
|
227
|
+
return False
|
|
228
|
+
return True
|
|
229
|
+
|
|
230
|
+
def affinity_score(self, job: Job) -> float:
|
|
231
|
+
"""Compute how well this worker matches a job (higher is better).
|
|
232
|
+
|
|
233
|
+
Score components:
|
|
234
|
+
- Required capability match: binary (0 if not met)
|
|
235
|
+
- Preferred capabilities present: +0.1 per match
|
|
236
|
+
- Available headroom: (1 - load) × 0.5
|
|
237
|
+
- Capacity surplus for numeric requirements: up to 0.3
|
|
238
|
+
"""
|
|
239
|
+
if not self.can_accept(job):
|
|
240
|
+
return 0.0
|
|
241
|
+
score = 1.0
|
|
242
|
+
for name in job.preferred_capabilities():
|
|
243
|
+
if name in self.capabilities:
|
|
244
|
+
score += 0.1
|
|
245
|
+
score += (1.0 - self.load) * 0.5
|
|
246
|
+
for req in job.capabilities:
|
|
247
|
+
if req.minimum is not None and req.name in self.capacity:
|
|
248
|
+
surplus = self.capacity[req.name] - (req.minimum or 0.0)
|
|
249
|
+
score += min(surplus / max(req.minimum or 1.0, 1.0), 1.0) * 0.15
|
|
250
|
+
return score
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
@dataclass
|
|
254
|
+
class HeartbeatPayload:
|
|
255
|
+
"""Progress update sent by a worker alongside a heartbeat."""
|
|
256
|
+
|
|
257
|
+
node_id: str
|
|
258
|
+
job_ids: List[str]
|
|
259
|
+
timestamp: datetime
|
|
260
|
+
progress: Dict[str, float] = field(default_factory=dict) # job_id → 0.0–1.0
|
|
261
|
+
log_lines: Dict[str, List[str]] = field(default_factory=dict) # job_id → logs
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
@dataclass
|
|
265
|
+
class QueueStats:
|
|
266
|
+
"""Counts per status and per job type."""
|
|
267
|
+
|
|
268
|
+
by_status: Dict[str, int] = field(default_factory=dict)
|
|
269
|
+
by_type: Dict[str, int] = field(default_factory=dict)
|
|
270
|
+
# ``total_workers`` is retained as the compatibility spelling for every
|
|
271
|
+
# durable registry row. The additive fields separate registration from
|
|
272
|
+
# heartbeat truth without a data migration.
|
|
273
|
+
total_workers: int = 0
|
|
274
|
+
available_workers: int = 0
|
|
275
|
+
registered_workers: int = 0
|
|
276
|
+
active_workers: int = 0
|
|
277
|
+
stale_workers: int = 0
|
|
278
|
+
worker_heartbeat_ttl_secs: float = 60.0
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
@dataclass
|
|
282
|
+
class AuditEntry:
|
|
283
|
+
"""An immutable audit record for a job state transition."""
|
|
284
|
+
|
|
285
|
+
id: int
|
|
286
|
+
job_id: str
|
|
287
|
+
timestamp: datetime
|
|
288
|
+
from_status: Optional[str]
|
|
289
|
+
to_status: str
|
|
290
|
+
node_id: Optional[str]
|
|
291
|
+
reason: Optional[str]
|
|
292
|
+
details: Dict[str, Any] = field(default_factory=dict)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
@dataclass
|
|
296
|
+
class FederatedJob:
|
|
297
|
+
"""A job posted by a federated peer colony."""
|
|
298
|
+
|
|
299
|
+
job: Job
|
|
300
|
+
source_colony_id: str
|
|
301
|
+
source_colony_trust_level: int
|
|
302
|
+
signature: str # Ed25519 signature from source colony
|
|
303
|
+
payment_intent: Optional[str] = None
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
class CircularDependencyError(ValueError):
|
|
307
|
+
"""Raised when a job dependency graph contains a cycle."""
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def deadline_urgency(job: Job, now: datetime) -> float:
|
|
311
|
+
"""Returns 0.0 if no deadline, otherwise urgency in [0, 100]."""
|
|
312
|
+
if job.deadline is None:
|
|
313
|
+
return 0.0
|
|
314
|
+
remaining = (job.deadline - now).total_seconds()
|
|
315
|
+
if remaining <= 0:
|
|
316
|
+
return 100.0
|
|
317
|
+
return max(0.0, min(100.0, (300.0 / max(remaining, 1.0)) * 100.0))
|