@openlife/cli 1.7.3
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.
- package/INSTALL.md +266 -0
- package/LICENSE +21 -0
- package/README.md +142 -0
- package/bin/openlife.js +3 -0
- package/dist/admin_panel_server.js +66 -0
- package/dist/cli/AgentManager.js +109 -0
- package/dist/cli/AutonomousInstaller.js +134 -0
- package/dist/cli/DreamOrganizer.js +88 -0
- package/dist/cli/HostInstaller.js +426 -0
- package/dist/cli/InstallBanner.js +16 -0
- package/dist/cli/InstallFlow.js +256 -0
- package/dist/cli/InstallHeadless.js +47 -0
- package/dist/cli/InstallModules.js +148 -0
- package/dist/cli/InstallStateStore.js +75 -0
- package/dist/cli/InstallWizard.js +364 -0
- package/dist/cli/ProfileManager.js +163 -0
- package/dist/cli/SystemInstaller.js +89 -0
- package/dist/cli/WorldClassCommands.js +208 -0
- package/dist/design/DesignMdImporter.js +82 -0
- package/dist/design/DesignMdMode.js +93 -0
- package/dist/design/DesignMdRegistry.js +67 -0
- package/dist/index.js +2575 -0
- package/dist/memory/ConversationMemory.js +33 -0
- package/dist/memory/LocalMemoryProvider.js +86 -0
- package/dist/memory/Mem0Provider.js +16 -0
- package/dist/memory/MemoryNamespacePolicy.js +27 -0
- package/dist/memory/MemoryOrchestrator.js +65 -0
- package/dist/memory/MemoryPromotionFlow.js +32 -0
- package/dist/memory/MemoryProvider.js +2 -0
- package/dist/memory/MemoryProviderRegistry.js +27 -0
- package/dist/memory/MemoryRetentionPolicy.js +60 -0
- package/dist/memory/MempalaceProvider.js +72 -0
- package/dist/memory/OmniMemory.js +106 -0
- package/dist/memory/RedisAgentMemoryProvider.js +16 -0
- package/dist/memory/SessionManager.js +86 -0
- package/dist/memory/ZepGraphitiProvider.js +16 -0
- package/dist/orchestrator/AgentRegistry.js +56 -0
- package/dist/orchestrator/AgentScoring.js +82 -0
- package/dist/orchestrator/AgentTeam.js +22 -0
- package/dist/orchestrator/ArbitrationAgent.js +43 -0
- package/dist/orchestrator/ArbitrationScorecard.js +17 -0
- package/dist/orchestrator/AssetPromotionEngine.js +65 -0
- package/dist/orchestrator/AssetReuseRouter.js +63 -0
- package/dist/orchestrator/BenchmarkEngine.js +75 -0
- package/dist/orchestrator/Brain.js +298 -0
- package/dist/orchestrator/CadenceEngine.js +76 -0
- package/dist/orchestrator/CapabilityRouter.js +36 -0
- package/dist/orchestrator/CommandLanguage.js +27 -0
- package/dist/orchestrator/CommandRouter.js +70 -0
- package/dist/orchestrator/ConsequenceForecaster.js +286 -0
- package/dist/orchestrator/CronManager.js +286 -0
- package/dist/orchestrator/DynamicAgentBuilder.js +48 -0
- package/dist/orchestrator/DynamicAgentExecutor.js +15 -0
- package/dist/orchestrator/EnterpriseAgenticCore.js +276 -0
- package/dist/orchestrator/ExecutionBoard.js +86 -0
- package/dist/orchestrator/ExecutionIntent.js +13 -0
- package/dist/orchestrator/ExecutionModePolicy.js +48 -0
- package/dist/orchestrator/ExecutionRouter.js +9 -0
- package/dist/orchestrator/ExecutionState.js +20 -0
- package/dist/orchestrator/ExecutorHealth.js +86 -0
- package/dist/orchestrator/ExternalCatalogRegistry.js +83 -0
- package/dist/orchestrator/Gatekeeper.js +414 -0
- package/dist/orchestrator/Gateway.js +508 -0
- package/dist/orchestrator/GovernanceConsentStore.js +66 -0
- package/dist/orchestrator/GovernanceLayer.js +179 -0
- package/dist/orchestrator/GovernancePolicyStore.js +53 -0
- package/dist/orchestrator/GovernanceScopeLedger.js +134 -0
- package/dist/orchestrator/GovernanceScopePolicy.js +67 -0
- package/dist/orchestrator/IntentClassifier.js +45 -0
- package/dist/orchestrator/JobLifecycle.js +91 -0
- package/dist/orchestrator/LearningRouter.js +24 -0
- package/dist/orchestrator/MediaManager.js +92 -0
- package/dist/orchestrator/MemoryCuratorAgent.js +41 -0
- package/dist/orchestrator/MissionState.js +155 -0
- package/dist/orchestrator/ModelManager.js +84 -0
- package/dist/orchestrator/OperatingSystem.js +71 -0
- package/dist/orchestrator/OperationalMemoryStore.js +94 -0
- package/dist/orchestrator/OptimizationLoop.js +72 -0
- package/dist/orchestrator/OrchestrationLoop.js +905 -0
- package/dist/orchestrator/OrgStructure.js +88 -0
- package/dist/orchestrator/OutcomeSimulator.js +46 -0
- package/dist/orchestrator/ParallelOrchestrationLoop.js +36 -0
- package/dist/orchestrator/PerformanceScorecard.js +105 -0
- package/dist/orchestrator/PlannerAgent.js +46 -0
- package/dist/orchestrator/ProcessSandbox.js +129 -0
- package/dist/orchestrator/PromotionPipeline.js +74 -0
- package/dist/orchestrator/PromotionReviewGate.js +11 -0
- package/dist/orchestrator/QueueScheduler.js +260 -0
- package/dist/orchestrator/ReleaseGate.js +36 -0
- package/dist/orchestrator/ReleaseWorkflow.js +68 -0
- package/dist/orchestrator/RemotePublisher.js +139 -0
- package/dist/orchestrator/ReuseEngine.js +89 -0
- package/dist/orchestrator/ReviewerAgent.js +49 -0
- package/dist/orchestrator/RoleHandoff.js +65 -0
- package/dist/orchestrator/RuntimeHealthMonitor.js +143 -0
- package/dist/orchestrator/RuntimePolicy.js +105 -0
- package/dist/orchestrator/RuntimeProbe.js +97 -0
- package/dist/orchestrator/RuntimeRegistry.js +73 -0
- package/dist/orchestrator/SandboxPolicy.js +22 -0
- package/dist/orchestrator/SecurityDownloadGuard.js +169 -0
- package/dist/orchestrator/SecurityEventStore.js +58 -0
- package/dist/orchestrator/ServiceCompletionPolicy.js +36 -0
- package/dist/orchestrator/ServiceState.js +195 -0
- package/dist/orchestrator/SkillCreator.js +404 -0
- package/dist/orchestrator/SkillLearningLoop.js +57 -0
- package/dist/orchestrator/SkillManager.js +75 -0
- package/dist/orchestrator/SkillNetwork.js +29 -0
- package/dist/orchestrator/SkillRegistryV2.js +28 -0
- package/dist/orchestrator/SkillScoring.js +70 -0
- package/dist/orchestrator/SquadAutoCreator.js +64 -0
- package/dist/orchestrator/SquadCreator.js +727 -0
- package/dist/orchestrator/SquadRegistry.js +28 -0
- package/dist/orchestrator/SquadRouter.js +33 -0
- package/dist/orchestrator/SquadScoring.js +70 -0
- package/dist/orchestrator/SubagentLifecycle.js +90 -0
- package/dist/orchestrator/SynthesizerAgent.js +48 -0
- package/dist/orchestrator/SystemDoctor.js +224 -0
- package/dist/orchestrator/TaskExecutor.js +422 -0
- package/dist/orchestrator/TeammateBoard.js +61 -0
- package/dist/orchestrator/TestHarness.js +184 -0
- package/dist/orchestrator/VoiceManager.js +203 -0
- package/dist/orchestrator/VoiceRouter.js +89 -0
- package/dist/orchestrator/capability/CapabilityGenesisEngine.js +278 -0
- package/dist/orchestrator/capability/CapabilityPackParser.js +223 -0
- package/dist/orchestrator/capability/CapabilityPackSchema.js +62 -0
- package/dist/orchestrator/capability/CapabilityPackState.js +163 -0
- package/dist/orchestrator/providers/AgentProvider.js +2 -0
- package/dist/orchestrator/providers/CapabilityProvider.js +12 -0
- package/dist/orchestrator/providers/CloudAgentProvider.js +55 -0
- package/dist/orchestrator/providers/CloudSkillProvider.js +55 -0
- package/dist/orchestrator/providers/CloudSquadProvider.js +55 -0
- package/dist/orchestrator/providers/CompositeAgentProvider.js +16 -0
- package/dist/orchestrator/providers/CompositeCapabilityProvider.js +25 -0
- package/dist/orchestrator/providers/CompositeSkillProvider.js +16 -0
- package/dist/orchestrator/providers/CompositeSquadProvider.js +16 -0
- package/dist/orchestrator/providers/CompositeWorkflowProvider.js +46 -0
- package/dist/orchestrator/providers/FileAgentProvider.js +105 -0
- package/dist/orchestrator/providers/FileCapabilityProvider.js +106 -0
- package/dist/orchestrator/providers/FileSkillProvider.js +65 -0
- package/dist/orchestrator/providers/FileSquadProvider.js +69 -0
- package/dist/orchestrator/providers/FileWorkflowProvider.js +103 -0
- package/dist/orchestrator/providers/SkillProvider.js +2 -0
- package/dist/orchestrator/providers/SquadProvider.js +2 -0
- package/dist/orchestrator/toolset/ToolsetGuard.js +69 -0
- package/dist/orchestrator/toolset/ToolsetRegistry.js +65 -0
- package/dist/orchestrator/toolset/ToolsetSchema.js +21 -0
- package/dist/orchestrator/util/AtomicWriter.js +204 -0
- package/dist/orchestrator/util/DistributedLock.js +232 -0
- package/dist/orchestrator/util/TemplateRenderer.js +87 -0
- package/dist/orchestrator/util/WatchdogHeartbeat.js +116 -0
- package/dist/orchestrator/workflow/ConditionParser.js +232 -0
- package/dist/orchestrator/workflow/WorkflowEngine.js +379 -0
- package/dist/orchestrator/workflow/WorkflowParser.js +368 -0
- package/dist/orchestrator/workflow/WorkflowSchema.js +65 -0
- package/dist/orchestrator/workflow/WorkflowState.js +11 -0
- package/dist/reversa/ReversaAgent.js +134 -0
- package/dist/reversa/ReversaContracts.js +62 -0
- package/dist/reversa/ReversaExecutors.js +65 -0
- package/dist/skills/SkillRegistry.js +71 -0
- package/dist/squads/SquadManager.js +87 -0
- package/dist/test_admin_teams_networks.js +54 -0
- package/dist/test_agent_team_skill_network.js +15 -0
- package/dist/test_aiobuilder_cli_parity.js +169 -0
- package/dist/test_ask_exit.js +73 -0
- package/dist/test_atomic_writer.js +209 -0
- package/dist/test_autonomous_soak.js +141 -0
- package/dist/test_benchmark_engine.js +41 -0
- package/dist/test_brain_error_diagnostics.js +51 -0
- package/dist/test_brain_fallback_chain.js +93 -0
- package/dist/test_capability_genesis_engine.js +225 -0
- package/dist/test_capability_pack_schema.js +214 -0
- package/dist/test_catalog_quality.js +150 -0
- package/dist/test_cli_crud_roundtrip.js +154 -0
- package/dist/test_cli_diagnostics.js +131 -0
- package/dist/test_cli_doc_parity.js +126 -0
- package/dist/test_cli_help_surface.js +106 -0
- package/dist/test_cli_service_commands.js +83 -0
- package/dist/test_consequence_forecast_brain.js +165 -0
- package/dist/test_consequence_forecaster.js +24 -0
- package/dist/test_conversation_memory.js +36 -0
- package/dist/test_create_entities.js +54 -0
- package/dist/test_creator_placeholders_completed.js +177 -0
- package/dist/test_cron_manager.js +123 -0
- package/dist/test_daemon_sigterm.js +72 -0
- package/dist/test_deep_research_capability.js +87 -0
- package/dist/test_designmd_import_registry.js +16 -0
- package/dist/test_designmd_mode.js +50 -0
- package/dist/test_designmd_mode_workspace.js +13 -0
- package/dist/test_dist_templates_layout.js +135 -0
- package/dist/test_distributed_lock.js +201 -0
- package/dist/test_distribution_installability.js +67 -0
- package/dist/test_doctor_sandbox_check.js +44 -0
- package/dist/test_dream_organizer.js +25 -0
- package/dist/test_dual_mode.js +15 -0
- package/dist/test_enterprise_agentic_core.js +128 -0
- package/dist/test_forecast_brain_wiring.js +87 -0
- package/dist/test_gateway_telegram_guardrails.js +52 -0
- package/dist/test_governance.js +34 -0
- package/dist/test_governance_advanced.js +75 -0
- package/dist/test_governance_scope_ledger.js +147 -0
- package/dist/test_governance_v13_policies.js +44 -0
- package/dist/test_guided_creator_cli.js +100 -0
- package/dist/test_host_install_e2e.js +324 -0
- package/dist/test_host_installer.js +259 -0
- package/dist/test_host_installers_gemini_codex.js +95 -0
- package/dist/test_host_uninstaller.js +295 -0
- package/dist/test_install_flow.js +70 -0
- package/dist/test_install_flow_host_validation.js +143 -0
- package/dist/test_install_wizard.js +272 -0
- package/dist/test_integration_gemini_live.js +95 -0
- package/dist/test_integration_http_trigger_live.js +154 -0
- package/dist/test_integration_telegram_live.js +102 -0
- package/dist/test_job_lifecycle.js +16 -0
- package/dist/test_memory_orchestrator.js +33 -0
- package/dist/test_memory_promotion.js +36 -0
- package/dist/test_memory_retention.js +37 -0
- package/dist/test_mission_checkpoint.js +204 -0
- package/dist/test_multi_host_docs_parity.js +125 -0
- package/dist/test_openlife_auto_creator_routing.js +69 -0
- package/dist/test_openlife_evolution_surface.js +77 -0
- package/dist/test_openlife_gatekeeper_routing.js +15 -0
- package/dist/test_openlife_routing_surface.js +27 -0
- package/dist/test_openlife_runtime_source_truth.js +25 -0
- package/dist/test_operating_system.js +45 -0
- package/dist/test_optimization_loop.js +38 -0
- package/dist/test_orchestration_assets_lifecycle.js +78 -0
- package/dist/test_outcome_simulator.js +38 -0
- package/dist/test_performance_latency.js +215 -0
- package/dist/test_performance_scorecard.js +38 -0
- package/dist/test_phase1_check_exit.js +103 -0
- package/dist/test_phase6_board.js +31 -0
- package/dist/test_phase6_cadence.js +29 -0
- package/dist/test_phase6_ops.js +37 -0
- package/dist/test_post_mission_evaluation.js +190 -0
- package/dist/test_process_sandbox.js +88 -0
- package/dist/test_profile_toolset_mcp.js +125 -0
- package/dist/test_queue_scheduler.js +239 -0
- package/dist/test_release_gate.js +23 -0
- package/dist/test_remote_publish.js +193 -0
- package/dist/test_reversa_contracts_e2e.js +48 -0
- package/dist/test_reversa_export_and_strict.js +51 -0
- package/dist/test_reversa_full_execution.js +12 -0
- package/dist/test_reversa_lite.js +9 -0
- package/dist/test_royal_stack_golden.js +179 -0
- package/dist/test_runtime_health_backoff.js +154 -0
- package/dist/test_runtime_policy.js +26 -0
- package/dist/test_runtime_probe.js +19 -0
- package/dist/test_runtime_profile_oauth_only.js +262 -0
- package/dist/test_runtime_registry.js +11 -0
- package/dist/test_security_download_and_scan.js +103 -0
- package/dist/test_security_download_guard.js +14 -0
- package/dist/test_service_command_surface.js +12 -0
- package/dist/test_service_completion_policy.js +32 -0
- package/dist/test_service_guardrails_delete.js +12 -0
- package/dist/test_service_mode_explicit_only.js +174 -0
- package/dist/test_sources_import_ref.js +46 -0
- package/dist/test_sources_scaffold.js +43 -0
- package/dist/test_squad_skill_creator.js +305 -0
- package/dist/test_squad_skill_design_llm.js +176 -0
- package/dist/test_subsystems_org_state.js +271 -0
- package/dist/test_subsystems_promotion_memory_assets.js +343 -0
- package/dist/test_subsystems_routing_governance.js +234 -0
- package/dist/test_task_executor_sandbox_optin.js +127 -0
- package/dist/test_teammate_learning.js +15 -0
- package/dist/test_telegram_delete_guardrail.js +21 -0
- package/dist/test_toolset_enforcement.js +188 -0
- package/dist/test_trigger_basic_auth.js +112 -0
- package/dist/test_util/doc_parity.js +120 -0
- package/dist/test_v15_e2e_integration.js +207 -0
- package/dist/test_watchdog_heartbeat.js +152 -0
- package/dist/test_workflow_condition_parser.js +63 -0
- package/dist/test_workflow_e2e.js +240 -0
- package/dist/test_workflow_engine.js +330 -0
- package/dist/test_workflow_parser.js +245 -0
- package/dist/test_workflow_schema_backward_compat.js +197 -0
- package/dist-templates/README.md +91 -0
- package/dist-templates/claude-code/agents/openlife-atlas.md +52 -0
- package/dist-templates/claude-code/agents/openlife-forge.md +42 -0
- package/dist-templates/claude-code/agents/openlife-genesis.md +59 -0
- package/dist-templates/claude-code/agents/openlife-lyra.md +40 -0
- package/dist-templates/claude-code/agents/openlife-maestro.md +45 -0
- package/dist-templates/claude-code/commands/openlife/ask.md +14 -0
- package/dist-templates/claude-code/commands/openlife/doctor.md +19 -0
- package/dist-templates/claude-code/commands/openlife/dream.md +20 -0
- package/dist-templates/claude-code/commands/openlife/status.md +14 -0
- package/dist-templates/claude-code/mcp/openlife-orchestrator.json +46 -0
- package/dist-templates/codex/README.md +7 -0
- package/dist-templates/codex/agents/openlife-atlas.md +52 -0
- package/dist-templates/codex/agents/openlife-forge.md +42 -0
- package/dist-templates/codex/agents/openlife-genesis.md +59 -0
- package/dist-templates/codex/agents/openlife-lyra.md +40 -0
- package/dist-templates/codex/agents/openlife-maestro.md +45 -0
- package/dist-templates/codex/commands/openlife/ask.md +14 -0
- package/dist-templates/codex/commands/openlife/doctor.md +19 -0
- package/dist-templates/codex/commands/openlife/dream.md +20 -0
- package/dist-templates/codex/commands/openlife/status.md +14 -0
- package/dist-templates/codex/mcp/openlife-orchestrator.json +46 -0
- package/dist-templates/gemini-cli/README.md +8 -0
- package/dist-templates/gemini-cli/agents/openlife-atlas.md +52 -0
- package/dist-templates/gemini-cli/agents/openlife-forge.md +42 -0
- package/dist-templates/gemini-cli/agents/openlife-genesis.md +59 -0
- package/dist-templates/gemini-cli/agents/openlife-lyra.md +40 -0
- package/dist-templates/gemini-cli/agents/openlife-maestro.md +45 -0
- package/dist-templates/gemini-cli/commands/openlife/ask.md +14 -0
- package/dist-templates/gemini-cli/commands/openlife/doctor.md +19 -0
- package/dist-templates/gemini-cli/commands/openlife/dream.md +20 -0
- package/dist-templates/gemini-cli/commands/openlife/status.md +14 -0
- package/dist-templates/gemini-cli/mcp/openlife-orchestrator.json +46 -0
- package/dist-templates/skill-template/README.md +34 -0
- package/dist-templates/skill-template/SKILL.md.template +59 -0
- package/dist-templates/squad-template/README.md +82 -0
- package/dist-templates/squad-template/SQUAD.md.template +51 -0
- package/dist-templates/squad-template/agent-template.md +51 -0
- package/dist-templates/squad-template/checklist-template.md +25 -0
- package/dist-templates/squad-template/task-template.md +36 -0
- package/dist-templates/workflows/PORTED_WORKFLOWS.md +60 -0
- package/dist-templates/workflows/brownfield-discovery.yaml +137 -0
- package/dist-templates/workflows/greenfield-fullstack.yaml +132 -0
- package/dist-templates/workflows/qa-loop.yaml +125 -0
- package/dist-templates/workflows/story-development-cycle.yaml +80 -0
- package/docs/CHANGELOG_FEATURE_ROLLOUT_DESIGNMD.md +43 -0
- package/docs/EXTERNAL_SOURCES_AND_SECURITY_GUARD.md +33 -0
- package/docs/OPENLIFE_AUDIT_2026-05-06.md +170 -0
- package/docs/OPENLIFE_CONSOLIDATED_PLAN_2026-05-06.md +299 -0
- package/docs/OPENLIFE_DUAL_MODE_IMPLEMENTATION_PLAN.md +205 -0
- package/docs/OPENLIFE_EVOLUTION_SURFACE_2026-05-07.md +53 -0
- package/docs/OPENLIFE_SKILLS_IMPORT_2026-05-07.json +223 -0
- package/docs/OPENLIFE_SQUADS_IMPORT_2026-05-07.json +184 -0
- package/docs/PAPERCLIP_OPENLIFE_INVESTIGATION.md +85 -0
- package/docs/README.md +28 -0
- package/docs/RELEASE_ORGANIZATION_PLAN.md +164 -0
- package/docs/audit/CLI-EXECUTION-RESULTS.md +113 -0
- package/docs/audit/CLI-MATRIX.md +556 -0
- package/docs/audit/DOC-PARITY-GAPS.md +351 -0
- package/docs/audit/ORCHESTRATOR-MATRIX.md +136 -0
- package/docs/audit/TEST-COVERAGE-GAPS.md +334 -0
- package/docs/audit/integrations/SKIPPED.md +101 -0
- package/docs/autonomous-install.md +79 -0
- package/docs/capability-genesis.md +137 -0
- package/docs/capability-pack-schema.md +157 -0
- package/docs/commands.md +82 -0
- package/docs/deep-research-capability.md +114 -0
- package/docs/development/typescript-conventions.md +95 -0
- package/docs/host-installers.md +68 -0
- package/docs/install/aiobuilder.md +70 -0
- package/docs/install/claude-code.md +83 -0
- package/docs/install/codex.md +64 -0
- package/docs/install/gemini-cli.md +64 -0
- package/docs/install/runtime-profiles.md +83 -0
- package/docs/openlife-agent-os-blueprint.md +114 -0
- package/docs/openlife-install-backlog.md +115 -0
- package/docs/openlife-install-spec.md +306 -0
- package/docs/operations/CLOUD_CUTOVER_AUDIT.md +37 -0
- package/docs/operations/PHASE_PROGRESS_CONTINUATION.md +24 -0
- package/docs/performance-benchmarks.md +83 -0
- package/docs/planning/v1.3-capability-genesis.md +157 -0
- package/docs/plans/2026-05-05-admin-interface-professional-dark-premium-plan.md +84 -0
- package/docs/plans/2026-05-05-openlife-autonomous-domain-marketplace-masterplan.md +122 -0
- package/docs/quickstart.md +60 -0
- package/docs/release-process.md +236 -0
- package/docs/roadmap/OPENLIFE_MASTER_PLAN_CLOUD_V3.md +97 -0
- package/docs/sandboxing-research.md +117 -0
- package/docs/stories/epic-feature-audit/1.1.story.md +84 -0
- package/docs/stories/epic-feature-audit/1.2.story.md +102 -0
- package/docs/stories/epic-feature-audit/1.3.story.md +93 -0
- package/docs/stories/epic-feature-audit/1.5.story.md +121 -0
- package/docs/stories/epic-feature-audit/1.6.story.md +80 -0
- package/docs/stories/epic-feature-completeness/2.1.story.md +70 -0
- package/docs/stories/epic-feature-completeness/2.2.story.md +49 -0
- package/docs/stories/epic-feature-completeness/2.3.story.md +74 -0
- package/docs/stories/epic-feature-completeness/2.4.story.md +71 -0
- package/docs/stories/epic-feature-completeness/3.1.story.md +56 -0
- package/docs/stories/epic-feature-completeness/3.2.story.md +80 -0
- package/docs/stories/epic-feature-completeness/3.3.story.md +68 -0
- package/docs/stories/epic-feature-completeness/3.4.story.md +71 -0
- package/docs/stories/epic-feature-completeness/3.5.story.md +72 -0
- package/docs/stories/epic-feature-completeness/3.6.story.md +69 -0
- package/docs/stories/epic-feature-completeness/3.7.story.md +68 -0
- package/docs/stories/epic-feature-completeness/3.8.story.md +57 -0
- package/docs/toolset-enforcement.md +122 -0
- package/docs/v1.4-changelog.md +159 -0
- package/docs/v1.5-changelog.md +106 -0
- package/docs/v1.5-roadmap.md +121 -0
- package/docs/v1.6-changelog.md +67 -0
- package/docs/v1.6-roadmap.md +89 -0
- package/docs/v1.7-changelog.md +98 -0
- package/docs/workflow-schema.md +177 -0
- package/package.json +177 -0
- package/scripts/clean-test-pollution.js +61 -0
- package/scripts/openlife-agent-start.sh +6 -0
- package/scripts/openlife-agent.service.example +13 -0
- package/scripts/openlife-agent.supervisord.conf.example +8 -0
- package/scripts/openlife-autonomous-install.sh +29 -0
- package/scripts/postinstall-check.sh +37 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
/*
|
|
37
|
+
* INT-03 + INT-04 — Live integration test against HTTP gateway.
|
|
38
|
+
*
|
|
39
|
+
* Boots a real Gateway on port 4099, hits /api/v1/trigger and admin endpoints
|
|
40
|
+
* with Basic Auth, asserts shape. Shuts down gracefully.
|
|
41
|
+
*
|
|
42
|
+
* NOT included in test:all. Run via: npm run test:integration-http
|
|
43
|
+
*/
|
|
44
|
+
const dotenv = __importStar(require("dotenv"));
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
const http = __importStar(require("http"));
|
|
48
|
+
const Gateway_1 = require("./orchestrator/Gateway");
|
|
49
|
+
dotenv.config();
|
|
50
|
+
const PORT = 4099;
|
|
51
|
+
const TRIGGER_LOG = path.join(process.cwd(), 'docs', 'audit', 'integrations', 'http-trigger.log');
|
|
52
|
+
const ADMIN_LOG = path.join(process.cwd(), 'docs', 'audit', 'integrations', 'admin.log');
|
|
53
|
+
function log(file, line) {
|
|
54
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
55
|
+
fs.appendFileSync(file, `${new Date().toISOString()} ${line}\n`);
|
|
56
|
+
}
|
|
57
|
+
function request(method, path, headers, body) {
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
const req = http.request({
|
|
60
|
+
host: '127.0.0.1', port: PORT, method, path,
|
|
61
|
+
headers: { ...headers, ...(body ? { 'Content-Length': Buffer.byteLength(body).toString() } : {}) }
|
|
62
|
+
}, (res) => {
|
|
63
|
+
let buf = '';
|
|
64
|
+
res.on('data', (d) => { buf += d.toString(); });
|
|
65
|
+
res.on('end', () => resolve({ status: res.statusCode || 0, headers: res.headers, body: buf }));
|
|
66
|
+
});
|
|
67
|
+
req.on('error', reject);
|
|
68
|
+
req.setTimeout(10000, () => req.destroy(new Error('REQUEST_TIMEOUT')));
|
|
69
|
+
if (body)
|
|
70
|
+
req.write(body);
|
|
71
|
+
req.end();
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async function main() {
|
|
75
|
+
// Force credentials for this test (do not leak real ones to test code)
|
|
76
|
+
process.env.PORT = String(PORT);
|
|
77
|
+
process.env.OPENLIFE_TRIGGER_USER = 'audit-trigger';
|
|
78
|
+
process.env.OPENLIFE_TRIGGER_PASS = 'audit-pass-' + process.pid;
|
|
79
|
+
process.env.OPENLIFE_ADMIN_USER = 'audit-admin';
|
|
80
|
+
process.env.OPENLIFE_ADMIN_PASS = 'audit-adminpass-' + process.pid;
|
|
81
|
+
const triggerAuth = 'Basic ' + Buffer.from(`audit-trigger:${process.env.OPENLIFE_TRIGGER_PASS}`).toString('base64');
|
|
82
|
+
const adminAuth = 'Basic ' + Buffer.from(`audit-admin:${process.env.OPENLIFE_ADMIN_PASS}`).toString('base64');
|
|
83
|
+
const gateway = new Gateway_1.Gateway();
|
|
84
|
+
gateway.start();
|
|
85
|
+
// Give Express + Telegraf launch a beat
|
|
86
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
87
|
+
const failures = [];
|
|
88
|
+
try {
|
|
89
|
+
// INT-03: /api/v1/trigger
|
|
90
|
+
log(TRIGGER_LOG, '----- INT-03 /api/v1/trigger -----');
|
|
91
|
+
// 3a: no auth → 401
|
|
92
|
+
const r1 = await request('POST', '/api/v1/trigger', { 'Content-Type': 'application/json' }, JSON.stringify({ text: 'audit ping' }));
|
|
93
|
+
log(TRIGGER_LOG, `no-auth status=${r1.status} body=${r1.body.slice(0, 100)}`);
|
|
94
|
+
if (r1.status !== 401)
|
|
95
|
+
failures.push(`trigger no-auth expected 401 got ${r1.status}`);
|
|
96
|
+
// 3b: wrong pass → 403
|
|
97
|
+
const wrongAuth = 'Basic ' + Buffer.from('audit-trigger:wrong').toString('base64');
|
|
98
|
+
const r2 = await request('POST', '/api/v1/trigger', { 'Content-Type': 'application/json', 'Authorization': wrongAuth }, JSON.stringify({ text: 'audit ping' }));
|
|
99
|
+
log(TRIGGER_LOG, `wrong-pass status=${r2.status} body=${r2.body.slice(0, 100)}`);
|
|
100
|
+
if (r2.status !== 403)
|
|
101
|
+
failures.push(`trigger wrong-pass expected 403 got ${r2.status}`);
|
|
102
|
+
// 3c: valid auth → 200
|
|
103
|
+
const r3 = await request('POST', '/api/v1/trigger', { 'Content-Type': 'application/json', 'Authorization': triggerAuth }, JSON.stringify({ text: 'audit ping via INT-03' }));
|
|
104
|
+
log(TRIGGER_LOG, `valid-auth status=${r3.status} body=${r3.body.slice(0, 200)}`);
|
|
105
|
+
if (r3.status !== 200 && r3.status !== 202 && r3.status !== 500) {
|
|
106
|
+
failures.push(`trigger valid-auth expected 200/202/500 got ${r3.status}`);
|
|
107
|
+
}
|
|
108
|
+
// 500 is acceptable: Brain may fail downstream when running without full env
|
|
109
|
+
// INT-04: admin endpoints
|
|
110
|
+
log(ADMIN_LOG, '----- INT-04 admin endpoints -----');
|
|
111
|
+
const adminEndpoints = ['/api/v1/admin/teams', '/api/v1/admin/networks', '/api/v1/admin/status'];
|
|
112
|
+
for (const ep of adminEndpoints) {
|
|
113
|
+
// no auth → 401
|
|
114
|
+
const ra = await request('GET', ep, {});
|
|
115
|
+
log(ADMIN_LOG, `${ep} no-auth status=${ra.status}`);
|
|
116
|
+
if (ra.status !== 401)
|
|
117
|
+
failures.push(`${ep} no-auth expected 401 got ${ra.status}`);
|
|
118
|
+
// valid auth → 200
|
|
119
|
+
const rb = await request('GET', ep, { 'Authorization': adminAuth });
|
|
120
|
+
let parsed;
|
|
121
|
+
try {
|
|
122
|
+
parsed = JSON.parse(rb.body);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
parsed = null;
|
|
126
|
+
}
|
|
127
|
+
const ok = rb.status === 200 && parsed && typeof parsed === 'object';
|
|
128
|
+
log(ADMIN_LOG, `${ep} valid-auth status=${rb.status} json_ok=${!!parsed} preview=${rb.body.slice(0, 120)}`);
|
|
129
|
+
if (!ok)
|
|
130
|
+
failures.push(`${ep} valid-auth expected 200+JSON got status=${rb.status} parsed=${!!parsed}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
try {
|
|
135
|
+
await gateway.shutdown('TEST_DONE');
|
|
136
|
+
}
|
|
137
|
+
catch (e) {
|
|
138
|
+
log(TRIGGER_LOG, `shutdown_error: ${e?.message || e}`);
|
|
139
|
+
}
|
|
140
|
+
delete process.env.OPENLIFE_TRIGGER_PASS;
|
|
141
|
+
delete process.env.OPENLIFE_ADMIN_PASS;
|
|
142
|
+
}
|
|
143
|
+
if (failures.length > 0) {
|
|
144
|
+
throw new Error(`HTTP_INTEGRATION_FAILURES (${failures.length}):\n${failures.join('\n')}`);
|
|
145
|
+
}
|
|
146
|
+
console.log(`TEST_INTEGRATION_HTTP_TRIGGER_LIVE_OK (trigger=3 cases, admin=${adminEndpoints_count()} endpoints × 2 auth states)`);
|
|
147
|
+
console.log(` trigger log: ${TRIGGER_LOG}`);
|
|
148
|
+
console.log(` admin log: ${ADMIN_LOG}`);
|
|
149
|
+
}
|
|
150
|
+
function adminEndpoints_count() { return 3; }
|
|
151
|
+
main().catch((err) => {
|
|
152
|
+
console.error('TEST_INTEGRATION_HTTP_TRIGGER_LIVE_FAIL:', err?.message || err);
|
|
153
|
+
process.exit(1);
|
|
154
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
/*
|
|
37
|
+
* INT-02 — Live integration test against Telegram Bot API.
|
|
38
|
+
*
|
|
39
|
+
* SIDE EFFECT: sends one real message to the allowlisted chat_id.
|
|
40
|
+
* The message will appear in Rafael's Telegram chat with the bot.
|
|
41
|
+
*
|
|
42
|
+
* Requires TELEGRAM_BOT_TOKEN + OPENLIFE_TELEGRAM_ALLOWED_USER_ID in .env.
|
|
43
|
+
*
|
|
44
|
+
* NOT included in test:all. Run via: npm run test:integration-telegram
|
|
45
|
+
*/
|
|
46
|
+
const dotenv = __importStar(require("dotenv"));
|
|
47
|
+
const fs = __importStar(require("fs"));
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const telegraf_1 = require("telegraf");
|
|
50
|
+
dotenv.config();
|
|
51
|
+
const LOG_PATH = path.join(process.cwd(), 'docs', 'audit', 'integrations', 'telegram.log');
|
|
52
|
+
function logLine(line) {
|
|
53
|
+
fs.mkdirSync(path.dirname(LOG_PATH), { recursive: true });
|
|
54
|
+
fs.appendFileSync(LOG_PATH, `${new Date().toISOString()} ${line}\n`);
|
|
55
|
+
}
|
|
56
|
+
async function main() {
|
|
57
|
+
const token = process.env.TELEGRAM_BOT_TOKEN;
|
|
58
|
+
const chatId = process.env.OPENLIFE_TELEGRAM_ALLOWED_USER_ID;
|
|
59
|
+
if (!token || !chatId) {
|
|
60
|
+
throw new Error(`MISSING_CREDS: token=${!!token} chatId=${!!chatId}`);
|
|
61
|
+
}
|
|
62
|
+
logLine(`START telegram live test (chat_id=${chatId})`);
|
|
63
|
+
const bot = new telegraf_1.Telegraf(token);
|
|
64
|
+
// Verify bot identity (read-only, no message sent)
|
|
65
|
+
let botInfo;
|
|
66
|
+
try {
|
|
67
|
+
botInfo = await bot.telegram.getMe();
|
|
68
|
+
logLine(`bot_info username=@${botInfo.username} id=${botInfo.id} is_bot=${botInfo.is_bot}`);
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
logLine(`FAIL getMe error=${err?.message || err}`);
|
|
72
|
+
throw new Error(`TELEGRAM_GETME_FAILED: ${err?.message || err}`);
|
|
73
|
+
}
|
|
74
|
+
// Send real message
|
|
75
|
+
const messageText = `🤖 AUDIT-OK from Phase 4 INT-02 — Total Feature Audit milestone — ${new Date().toISOString()}`;
|
|
76
|
+
let sentMsg;
|
|
77
|
+
const t0 = Date.now();
|
|
78
|
+
try {
|
|
79
|
+
sentMsg = await bot.telegram.sendMessage(chatId, messageText);
|
|
80
|
+
const elapsed = Date.now() - t0;
|
|
81
|
+
logLine(`OK message_id=${sentMsg.message_id} elapsed=${elapsed}ms`);
|
|
82
|
+
console.log(`TEST_INTEGRATION_TELEGRAM_LIVE_OK (bot=@${botInfo.username}, message_id=${sentMsg.message_id}, elapsed=${elapsed}ms)`);
|
|
83
|
+
console.log(` log: ${LOG_PATH}`);
|
|
84
|
+
console.log(` message: ${messageText.slice(0, 80)}...`);
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
logLine(`FAIL sendMessage error=${err?.message || err}`);
|
|
88
|
+
throw new Error(`TELEGRAM_SEND_FAILED: ${err?.message || err}`);
|
|
89
|
+
}
|
|
90
|
+
// Telegraf has no pending handle to close in this path (we never started polling),
|
|
91
|
+
// so the process should exit cleanly. Add safety net just in case.
|
|
92
|
+
setTimeout(() => process.exit(0), 100).unref();
|
|
93
|
+
}
|
|
94
|
+
main().catch((err) => {
|
|
95
|
+
const msg = err?.message || String(err);
|
|
96
|
+
try {
|
|
97
|
+
logLine(`FAIL ${msg.slice(0, 300)}`);
|
|
98
|
+
}
|
|
99
|
+
catch { }
|
|
100
|
+
console.error('TEST_INTEGRATION_TELEGRAM_LIVE_FAIL:', msg);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const JobLifecycle_1 = require("./orchestrator/JobLifecycle");
|
|
4
|
+
function assert(condition, message) {
|
|
5
|
+
if (!condition)
|
|
6
|
+
throw new Error(message);
|
|
7
|
+
}
|
|
8
|
+
const store = new JobLifecycle_1.JobLifecycleStore('testws');
|
|
9
|
+
const job = store.enqueue('test objective', 'testws');
|
|
10
|
+
store.transition(job.jobId, 'testws', 'claimed', 'claimed', 'agent-a');
|
|
11
|
+
store.transition(job.jobId, 'testws', 'started', 'started', 'agent-a');
|
|
12
|
+
store.transition(job.jobId, 'testws', 'completed', 'done', 'agent-a');
|
|
13
|
+
const rec = store.get(job.jobId);
|
|
14
|
+
assert(rec?.status === 'completed', 'job should be completed');
|
|
15
|
+
assert(store.events(job.jobId).length >= 4, 'job should have lifecycle events');
|
|
16
|
+
console.log('TEST_JOB_LIFECYCLE_OK');
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const MemoryOrchestrator_1 = require("./memory/MemoryOrchestrator");
|
|
4
|
+
function assert(condition, message) {
|
|
5
|
+
if (!condition)
|
|
6
|
+
throw new Error(message);
|
|
7
|
+
}
|
|
8
|
+
async function main() {
|
|
9
|
+
const orchestrator = new MemoryOrchestrator_1.MemoryOrchestrator();
|
|
10
|
+
await orchestrator.save({
|
|
11
|
+
type: 'semantic',
|
|
12
|
+
namespace: { project: 'open-life-core', user: 'rafa' },
|
|
13
|
+
content: 'Runtime policy agora usa health e cooldown para fallback.',
|
|
14
|
+
summary: 'runtime policy com health e cooldown',
|
|
15
|
+
tags: ['runtime', 'phase1'],
|
|
16
|
+
confidence: 0.9,
|
|
17
|
+
dedupeKey: 'phase1-runtime-health',
|
|
18
|
+
providers: ['local']
|
|
19
|
+
});
|
|
20
|
+
const results = await orchestrator.search({
|
|
21
|
+
query: 'runtime policy health cooldown',
|
|
22
|
+
namespace: { project: 'open-life-core' },
|
|
23
|
+
topK: 5
|
|
24
|
+
}, ['local']);
|
|
25
|
+
assert(results.length >= 1, 'should retrieve at least one memory result');
|
|
26
|
+
assert(results[0].record.namespace.project === 'open-life-core', 'should preserve namespace');
|
|
27
|
+
assert(results[0].provider === 'local', 'should expose provider origin');
|
|
28
|
+
console.log('TEST_MEMORY_ORCHESTRATOR_OK');
|
|
29
|
+
}
|
|
30
|
+
main().catch((error) => {
|
|
31
|
+
console.error(error.message || error);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const PromotionPipeline_1 = require("./orchestrator/PromotionPipeline");
|
|
4
|
+
const MemoryPromotionFlow_1 = require("./memory/MemoryPromotionFlow");
|
|
5
|
+
function assert(condition, message) {
|
|
6
|
+
if (!condition)
|
|
7
|
+
throw new Error(message);
|
|
8
|
+
}
|
|
9
|
+
async function main() {
|
|
10
|
+
const pipeline = new PromotionPipeline_1.PromotionPipeline();
|
|
11
|
+
const flow = new MemoryPromotionFlow_1.MemoryPromotionFlow();
|
|
12
|
+
pipeline.add({
|
|
13
|
+
id: 'playbook-runtime-fallback',
|
|
14
|
+
type: 'playbook',
|
|
15
|
+
sourceMissionId: 'mission-123',
|
|
16
|
+
summary: 'Quando Gemini cair por quota, priorizar cooldown e fallback para Codex.',
|
|
17
|
+
createdAt: new Date().toISOString()
|
|
18
|
+
}, {
|
|
19
|
+
project: 'open-life-core',
|
|
20
|
+
user: 'rafa',
|
|
21
|
+
domain: 'runtime',
|
|
22
|
+
missionType: 'runtime'
|
|
23
|
+
});
|
|
24
|
+
const results = await flow.retrieve('Gemini quota fallback codex', {
|
|
25
|
+
project: 'open-life-core',
|
|
26
|
+
user: 'rafa',
|
|
27
|
+
domain: 'runtime'
|
|
28
|
+
}, ['semantic', 'episodic']);
|
|
29
|
+
assert(results.length >= 1, 'should retrieve promoted memory');
|
|
30
|
+
assert(results.some((item) => item.record.namespace.project === 'open-life-core'), 'promoted memory should preserve namespace');
|
|
31
|
+
console.log('TEST_MEMORY_PROMOTION_OK');
|
|
32
|
+
}
|
|
33
|
+
main().catch((error) => {
|
|
34
|
+
console.error(error.message || error);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const MemoryRetentionPolicy_1 = require("./memory/MemoryRetentionPolicy");
|
|
4
|
+
function assert(condition, message) {
|
|
5
|
+
if (!condition)
|
|
6
|
+
throw new Error(message);
|
|
7
|
+
}
|
|
8
|
+
function makeRecord(type, createdAt, confidence = 0.8) {
|
|
9
|
+
return {
|
|
10
|
+
id: `${type}-${createdAt}`,
|
|
11
|
+
type,
|
|
12
|
+
namespace: { project: 'open-life-core' },
|
|
13
|
+
content: 'runtime fallback policy with cooldown and codex recovery',
|
|
14
|
+
summary: 'runtime fallback policy',
|
|
15
|
+
tags: ['runtime', 'fallback'],
|
|
16
|
+
confidence,
|
|
17
|
+
createdAt,
|
|
18
|
+
updatedAt: createdAt
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
async function main() {
|
|
22
|
+
const retention = new MemoryRetentionPolicy_1.MemoryRetentionPolicy();
|
|
23
|
+
const oldWorking = makeRecord('working', new Date(Date.now() - 10 * 24 * 60 * 60 * 1000).toISOString());
|
|
24
|
+
const recentSemantic = makeRecord('semantic', new Date().toISOString(), 0.9);
|
|
25
|
+
const profile = makeRecord('profile', new Date(Date.now() - 120 * 24 * 60 * 60 * 1000).toISOString(), 0.7);
|
|
26
|
+
assert(retention.decide(oldWorking).keep === false, 'old working memory should expire');
|
|
27
|
+
assert(retention.decide(recentSemantic).keep === true, 'recent semantic memory should be kept');
|
|
28
|
+
assert(retention.decide(profile).keep === true, 'profile memory should persist');
|
|
29
|
+
const recentScore = retention.score(recentSemantic, 'runtime fallback codex');
|
|
30
|
+
const oldScore = retention.score(oldWorking, 'runtime fallback codex');
|
|
31
|
+
assert(recentScore > oldScore, 'recent semantic memory should outrank stale working memory');
|
|
32
|
+
console.log('TEST_MEMORY_RETENTION_OK');
|
|
33
|
+
}
|
|
34
|
+
main().catch((error) => {
|
|
35
|
+
console.error(error.message || error);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
});
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* test_mission_checkpoint — Story 6.2 regression suite.
|
|
4
|
+
*
|
|
5
|
+
* Asserts the MissionCheckpointStore contract:
|
|
6
|
+
* 1. Save + read round-trip; getLatest returns null before any save
|
|
7
|
+
* 2. Resume semantics: resumeFromCheckpoint returns latest, list/clear
|
|
8
|
+
* 3. Save overwrites previous checkpoint (latest wins); sanitization
|
|
9
|
+
* protects against directory traversal in missionId
|
|
10
|
+
*
|
|
11
|
+
* Path resolution honors OPENLIFE_STATE_DIR (so the test can sandbox in a
|
|
12
|
+
* temp dir without touching the real `.openlife/`).
|
|
13
|
+
*
|
|
14
|
+
* Run via: `npm run test:mission-checkpoint`. Prints
|
|
15
|
+
* TEST_MISSION_CHECKPOINT_OK on full pass.
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
const fs = __importStar(require("fs"));
|
|
52
|
+
const os = __importStar(require("os"));
|
|
53
|
+
const path = __importStar(require("path"));
|
|
54
|
+
const MissionState_1 = require("./orchestrator/MissionState");
|
|
55
|
+
function assert(cond, msg) {
|
|
56
|
+
if (!cond)
|
|
57
|
+
throw new Error(`assertion failed: ${msg}`);
|
|
58
|
+
}
|
|
59
|
+
function mkTmp() {
|
|
60
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'mission-ckpt-test-'));
|
|
61
|
+
}
|
|
62
|
+
function rmTmp(dir) {
|
|
63
|
+
try {
|
|
64
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
65
|
+
}
|
|
66
|
+
catch { /* ignore */ }
|
|
67
|
+
}
|
|
68
|
+
// ─────────────────────────────────────────────────────────────
|
|
69
|
+
// Scenario 1: save + getLatest round-trip
|
|
70
|
+
// ─────────────────────────────────────────────────────────────
|
|
71
|
+
function scenarioRoundTrip() {
|
|
72
|
+
const tmpRoot = mkTmp();
|
|
73
|
+
const prev = process.env.OPENLIFE_STATE_DIR;
|
|
74
|
+
try {
|
|
75
|
+
process.env.OPENLIFE_STATE_DIR = path.join(tmpRoot, '.openlife');
|
|
76
|
+
const store = new MissionState_1.MissionCheckpointStore();
|
|
77
|
+
// Pre-condition: no checkpoint exists
|
|
78
|
+
assert(store.getLatestCheckpoint('mission-001') === null, 'must return null before any save');
|
|
79
|
+
assert(store.list().length === 0, 'list must be empty initially');
|
|
80
|
+
// Save a checkpoint
|
|
81
|
+
const state = { workflowRunId: 'run-abc', completedSteps: ['s1', 's2'], pendingSteps: ['s3'] };
|
|
82
|
+
store.saveCheckpoint('mission-001', 'step-3', state);
|
|
83
|
+
// Read back
|
|
84
|
+
const ckpt = store.getLatestCheckpoint('mission-001');
|
|
85
|
+
assert(ckpt !== null, 'getLatest must return saved checkpoint');
|
|
86
|
+
const c = ckpt;
|
|
87
|
+
assert(c.missionId === 'mission-001', 'missionId mismatch');
|
|
88
|
+
assert(c.step === 'step-3', 'step mismatch');
|
|
89
|
+
assert(JSON.stringify(c.state) === JSON.stringify(state), 'state round-trip mismatch');
|
|
90
|
+
assert(typeof c.savedAt === 'string' && c.savedAt.length > 0, 'savedAt must be a non-empty ISO string');
|
|
91
|
+
// File should live under <state>/checkpoints/
|
|
92
|
+
const baseDir = store._baseDir();
|
|
93
|
+
assert(baseDir.startsWith(process.env.OPENLIFE_STATE_DIR), 'baseDir must respect OPENLIFE_STATE_DIR');
|
|
94
|
+
assert(fs.existsSync(path.join(baseDir, 'mission-001.json')), 'checkpoint file must exist on disk');
|
|
95
|
+
// List must report the missionId
|
|
96
|
+
const list = store.list();
|
|
97
|
+
assert(list.length === 1 && list[0] === 'mission-001', `list mismatch: ${JSON.stringify(list)}`);
|
|
98
|
+
console.log('✅ scenario 1: save + getLatest round-trip');
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
if (prev === undefined)
|
|
102
|
+
delete process.env.OPENLIFE_STATE_DIR;
|
|
103
|
+
else
|
|
104
|
+
process.env.OPENLIFE_STATE_DIR = prev;
|
|
105
|
+
rmTmp(tmpRoot);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// ─────────────────────────────────────────────────────────────
|
|
109
|
+
// Scenario 2: resume semantics + clear
|
|
110
|
+
// ─────────────────────────────────────────────────────────────
|
|
111
|
+
function scenarioResumeAndClear() {
|
|
112
|
+
const tmpRoot = mkTmp();
|
|
113
|
+
const prev = process.env.OPENLIFE_STATE_DIR;
|
|
114
|
+
try {
|
|
115
|
+
process.env.OPENLIFE_STATE_DIR = path.join(tmpRoot, '.openlife');
|
|
116
|
+
const store = new MissionState_1.MissionCheckpointStore();
|
|
117
|
+
store.saveCheckpoint('m-a', 'step-1', { foo: 'a' });
|
|
118
|
+
store.saveCheckpoint('m-b', 'step-1', { foo: 'b' });
|
|
119
|
+
store.saveCheckpoint('m-c', 'step-2', { foo: 'c' });
|
|
120
|
+
const list = store.list().sort();
|
|
121
|
+
assert(list.length === 3, `expected 3 missions with checkpoints, got ${list.length}`);
|
|
122
|
+
assert(JSON.stringify(list) === JSON.stringify(['m-a', 'm-b', 'm-c']), `list contents: ${JSON.stringify(list)}`);
|
|
123
|
+
// resumeFromCheckpoint should return the same as getLatest
|
|
124
|
+
const resumeB = store.resumeFromCheckpoint('m-b');
|
|
125
|
+
const getB = store.getLatestCheckpoint('m-b');
|
|
126
|
+
assert(resumeB !== null && getB !== null, 'both must return non-null');
|
|
127
|
+
assert(JSON.stringify(resumeB) === JSON.stringify(getB), 'resume and getLatest must return identical data');
|
|
128
|
+
// Clear m-b
|
|
129
|
+
store.clear('m-b');
|
|
130
|
+
assert(store.getLatestCheckpoint('m-b') === null, 'after clear, getLatest must return null');
|
|
131
|
+
assert(store.list().length === 2, 'list must shrink after clear');
|
|
132
|
+
// Clearing a non-existent missionId is a no-op (no throw)
|
|
133
|
+
store.clear('does-not-exist');
|
|
134
|
+
console.log('✅ scenario 2: resume semantics + clear');
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
if (prev === undefined)
|
|
138
|
+
delete process.env.OPENLIFE_STATE_DIR;
|
|
139
|
+
else
|
|
140
|
+
process.env.OPENLIFE_STATE_DIR = prev;
|
|
141
|
+
rmTmp(tmpRoot);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// ─────────────────────────────────────────────────────────────
|
|
145
|
+
// Scenario 3: overwrite + missionId sanitization
|
|
146
|
+
// ─────────────────────────────────────────────────────────────
|
|
147
|
+
function scenarioOverwriteAndSanitize() {
|
|
148
|
+
const tmpRoot = mkTmp();
|
|
149
|
+
const prev = process.env.OPENLIFE_STATE_DIR;
|
|
150
|
+
try {
|
|
151
|
+
process.env.OPENLIFE_STATE_DIR = path.join(tmpRoot, '.openlife');
|
|
152
|
+
const store = new MissionState_1.MissionCheckpointStore();
|
|
153
|
+
// Overwrite: saving twice keeps only the latest
|
|
154
|
+
store.saveCheckpoint('m-x', 'step-1', { value: 'first' });
|
|
155
|
+
const firstSavedAt = store.getLatestCheckpoint('m-x')?.savedAt;
|
|
156
|
+
// Ensure measurable time gap before overwrite (ISO timestamps are ms precision)
|
|
157
|
+
const deadline = Date.now() + 5;
|
|
158
|
+
while (Date.now() < deadline) { /* spin briefly */ }
|
|
159
|
+
store.saveCheckpoint('m-x', 'step-2', { value: 'second' });
|
|
160
|
+
const after = store.getLatestCheckpoint('m-x');
|
|
161
|
+
assert(after !== null, 'overwritten checkpoint must still be readable');
|
|
162
|
+
assert(after.step === 'step-2', `latest step must be 'step-2', got '${after.step}'`);
|
|
163
|
+
assert(after.state.value === 'second', 'latest state must reflect overwrite');
|
|
164
|
+
assert(after.savedAt !== firstSavedAt, 'savedAt must change after overwrite');
|
|
165
|
+
// List should still report m-x exactly once
|
|
166
|
+
assert(store.list().filter((m) => m === 'm-x').length === 1, 'list must not duplicate after overwrite');
|
|
167
|
+
// Sanitization: missionIds with path traversal attempts must be neutralized
|
|
168
|
+
const sneaky = '../../../etc/passwd';
|
|
169
|
+
store.saveCheckpoint(sneaky, 'step-1', { value: 'blocked' });
|
|
170
|
+
const baseDir = store._baseDir();
|
|
171
|
+
// The sanitized file must live INSIDE baseDir, never outside it
|
|
172
|
+
const dangerousPath = path.join(baseDir, '..', '..', '..', 'etc', 'passwd.json');
|
|
173
|
+
assert(!fs.existsSync(dangerousPath), 'sanitization must prevent path traversal');
|
|
174
|
+
// And the checkpoint must still be retrievable using the original (un-sanitized) missionId
|
|
175
|
+
const sneakyCkpt = store.getLatestCheckpoint(sneaky);
|
|
176
|
+
assert(sneakyCkpt !== null, 'sanitized checkpoint must round-trip with the original missionId key');
|
|
177
|
+
console.log('✅ scenario 3: overwrite + sanitization');
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
if (prev === undefined)
|
|
181
|
+
delete process.env.OPENLIFE_STATE_DIR;
|
|
182
|
+
else
|
|
183
|
+
process.env.OPENLIFE_STATE_DIR = prev;
|
|
184
|
+
rmTmp(tmpRoot);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// ─────────────────────────────────────────────────────────────
|
|
188
|
+
// Driver
|
|
189
|
+
// ─────────────────────────────────────────────────────────────
|
|
190
|
+
function main() {
|
|
191
|
+
console.log('🧪 test_mission_checkpoint — Story 6.2 regression suite');
|
|
192
|
+
scenarioRoundTrip();
|
|
193
|
+
scenarioResumeAndClear();
|
|
194
|
+
scenarioOverwriteAndSanitize();
|
|
195
|
+
console.log('');
|
|
196
|
+
console.log('TEST_MISSION_CHECKPOINT_OK');
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
main();
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
console.error('❌ test_mission_checkpoint FAILED:', err instanceof Error ? err.message : err);
|
|
203
|
+
process.exit(1);
|
|
204
|
+
}
|