@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,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const IntentClassifier_1 = require("./orchestrator/IntentClassifier");
|
|
4
|
+
const CapabilityRouter_1 = require("./orchestrator/CapabilityRouter");
|
|
5
|
+
const AgentRegistry_1 = require("./orchestrator/AgentRegistry");
|
|
6
|
+
const AssetReuseRouter_1 = require("./orchestrator/AssetReuseRouter");
|
|
7
|
+
const SquadRouter_1 = require("./orchestrator/SquadRouter");
|
|
8
|
+
const SquadRegistry_1 = require("./orchestrator/SquadRegistry");
|
|
9
|
+
const ExecutionRouter_1 = require("./orchestrator/ExecutionRouter");
|
|
10
|
+
const ExecutionIntent_1 = require("./orchestrator/ExecutionIntent");
|
|
11
|
+
const LearningRouter_1 = require("./orchestrator/LearningRouter");
|
|
12
|
+
const AgentScoring_1 = require("./orchestrator/AgentScoring");
|
|
13
|
+
const GovernanceLayer_1 = require("./orchestrator/GovernanceLayer");
|
|
14
|
+
const RuntimePolicy_1 = require("./orchestrator/RuntimePolicy");
|
|
15
|
+
const SandboxPolicy_1 = require("./orchestrator/SandboxPolicy");
|
|
16
|
+
const SecurityDownloadGuard_1 = require("./orchestrator/SecurityDownloadGuard");
|
|
17
|
+
function assert(condition, message) {
|
|
18
|
+
if (!condition)
|
|
19
|
+
throw new Error(message);
|
|
20
|
+
}
|
|
21
|
+
// ============ SUB-03 IntentClassifier ============
|
|
22
|
+
async function testIntentClassifierEngineering() {
|
|
23
|
+
const classifier = new IntentClassifier_1.IntentClassifier();
|
|
24
|
+
const result = await classifier.classify('crie um agente novo para revisão de código');
|
|
25
|
+
if (result.intent !== IntentClassifier_1.TaskIntent.ENGINEERING_BUILD) {
|
|
26
|
+
throw new Error(`INTENT_ENGINEERING_FAILED: expected ENGINEERING_BUILD got ${result.intent}`);
|
|
27
|
+
}
|
|
28
|
+
if (typeof result.budgetLimit !== 'number' || result.budgetLimit <= 0) {
|
|
29
|
+
throw new Error(`INTENT_BUDGET_FAILED: invalid budget ${result.budgetLimit}`);
|
|
30
|
+
}
|
|
31
|
+
if (result.requiresHarness !== true) {
|
|
32
|
+
throw new Error(`INTENT_HARNESS_FAILED: engineering must require harness`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function testIntentClassifierResearch() {
|
|
36
|
+
const classifier = new IntentClassifier_1.IntentClassifier();
|
|
37
|
+
const result = await classifier.classify('pesquise concorrentes do setor jurídico');
|
|
38
|
+
if (result.intent !== IntentClassifier_1.TaskIntent.RESEARCH_ANALYSIS) {
|
|
39
|
+
throw new Error(`INTENT_RESEARCH_FAILED: expected RESEARCH_ANALYSIS got ${result.intent}`);
|
|
40
|
+
}
|
|
41
|
+
if (!result.requiresHarness) {
|
|
42
|
+
throw new Error(`INTENT_RESEARCH_HARNESS_FAILED: research must require harness`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function testIntentClassifierAmbiguous() {
|
|
46
|
+
const classifier = new IntentClassifier_1.IntentClassifier();
|
|
47
|
+
const result = await classifier.classify('hmm, talvez algo aleatório aqui');
|
|
48
|
+
// Should not crash and must return SOMETHING (default = KNOWLEDGE_RETRIEVAL)
|
|
49
|
+
if (!result || !result.intent) {
|
|
50
|
+
throw new Error(`INTENT_AMBIGUOUS_FAILED: classifier returned no intent`);
|
|
51
|
+
}
|
|
52
|
+
if (typeof result.budgetLimit !== 'number') {
|
|
53
|
+
throw new Error(`INTENT_AMBIGUOUS_BUDGET_FAILED: budget missing`);
|
|
54
|
+
}
|
|
55
|
+
if (typeof result.requiresHarness !== 'boolean') {
|
|
56
|
+
throw new Error(`INTENT_AMBIGUOUS_HARNESS_FAILED: requiresHarness missing`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// ============ SUB-04 Routers ============
|
|
60
|
+
async function testCapabilityRouter() {
|
|
61
|
+
const registry = new AgentRegistry_1.AgentRegistry();
|
|
62
|
+
const router = new CapabilityRouter_1.CapabilityRouter(registry);
|
|
63
|
+
const task = { intent: IntentClassifier_1.TaskIntent.ENGINEERING_BUILD, budgetLimit: 5, requiresHarness: true };
|
|
64
|
+
const route = router.route(task, 'crie uma feature de auth');
|
|
65
|
+
if (!route)
|
|
66
|
+
throw new Error('CAPABILITY_ROUTER_FAILED: undefined route');
|
|
67
|
+
if (!Array.isArray(route.capabilities))
|
|
68
|
+
throw new Error('CAPABILITY_ROUTER_FAILED: capabilities not array');
|
|
69
|
+
if (!Array.isArray(route.agents))
|
|
70
|
+
throw new Error('CAPABILITY_ROUTER_FAILED: agents not array');
|
|
71
|
+
if (!route.mode)
|
|
72
|
+
throw new Error('CAPABILITY_ROUTER_FAILED: missing mode');
|
|
73
|
+
if (!route.rationale)
|
|
74
|
+
throw new Error('CAPABILITY_ROUTER_FAILED: missing rationale');
|
|
75
|
+
}
|
|
76
|
+
async function testAssetReuseRouter() {
|
|
77
|
+
const router = new AssetReuseRouter_1.AssetReuseRouter();
|
|
78
|
+
const found = router.find('build auth feature');
|
|
79
|
+
// Without a promoted-assets dir this returns []. Structural invariant only.
|
|
80
|
+
if (!Array.isArray(found)) {
|
|
81
|
+
throw new Error('ASSET_REUSE_ROUTER_FAILED: find() must return array');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async function testSquadRouter() {
|
|
85
|
+
const registry = new SquadRegistry_1.SquadRegistry();
|
|
86
|
+
const router = new SquadRouter_1.SquadRouter(registry);
|
|
87
|
+
const task = { intent: IntentClassifier_1.TaskIntent.ENGINEERING_BUILD, budgetLimit: 5, requiresHarness: true };
|
|
88
|
+
const route = router.route(task, 'construa o módulo X');
|
|
89
|
+
if (!route)
|
|
90
|
+
throw new Error('SQUAD_ROUTER_FAILED: undefined route');
|
|
91
|
+
if (!Array.isArray(route.squads))
|
|
92
|
+
throw new Error('SQUAD_ROUTER_FAILED: squads not array');
|
|
93
|
+
if (typeof route.rationale !== 'string')
|
|
94
|
+
throw new Error('SQUAD_ROUTER_FAILED: missing rationale');
|
|
95
|
+
}
|
|
96
|
+
async function testExecutionRouter() {
|
|
97
|
+
const router = new ExecutionRouter_1.ExecutionRouter();
|
|
98
|
+
const taskIntent = (0, ExecutionIntent_1.normalizeExecutionIntent)({ goal: 'do something', mode: 'task' });
|
|
99
|
+
const serviceIntent = (0, ExecutionIntent_1.normalizeExecutionIntent)({ goal: 'run service', mode: 'service' });
|
|
100
|
+
const taskPath = router.route(taskIntent);
|
|
101
|
+
const servicePath = router.route(serviceIntent);
|
|
102
|
+
if (taskPath !== 'task')
|
|
103
|
+
throw new Error(`EXECUTION_ROUTER_TASK_FAILED: got ${taskPath}`);
|
|
104
|
+
if (servicePath !== 'service')
|
|
105
|
+
throw new Error(`EXECUTION_ROUTER_SERVICE_FAILED: got ${servicePath}`);
|
|
106
|
+
}
|
|
107
|
+
async function testLearningRouter() {
|
|
108
|
+
const registry = new AgentRegistry_1.AgentRegistry();
|
|
109
|
+
const capabilityRouter = new CapabilityRouter_1.CapabilityRouter(registry);
|
|
110
|
+
const scoring = new AgentScoring_1.AgentScoring();
|
|
111
|
+
const learning = new LearningRouter_1.LearningRouter(capabilityRouter, scoring);
|
|
112
|
+
const task = { intent: IntentClassifier_1.TaskIntent.ENGINEERING_BUILD, budgetLimit: 5, requiresHarness: true };
|
|
113
|
+
const route = learning.route(task, 'crie um deploy pipeline');
|
|
114
|
+
if (!route)
|
|
115
|
+
throw new Error('LEARNING_ROUTER_FAILED: undefined route');
|
|
116
|
+
if (!Array.isArray(route.agents))
|
|
117
|
+
throw new Error('LEARNING_ROUTER_FAILED: agents not array');
|
|
118
|
+
if (!Array.isArray(route.capabilities))
|
|
119
|
+
throw new Error('LEARNING_ROUTER_FAILED: capabilities not array');
|
|
120
|
+
if (!route.mode)
|
|
121
|
+
throw new Error('LEARNING_ROUTER_FAILED: missing mode');
|
|
122
|
+
}
|
|
123
|
+
// ============ SUB-05 Governance guards ============
|
|
124
|
+
async function testGovernanceLayer() {
|
|
125
|
+
const gov = new GovernanceLayer_1.GovernanceLayer();
|
|
126
|
+
const safe = gov.evaluate('analise os logs de produtividade da semana');
|
|
127
|
+
if (!safe.allowed) {
|
|
128
|
+
throw new Error(`GOVERNANCE_ALLOW_FAILED: safe mission was blocked. rationale=${safe.rationale}`);
|
|
129
|
+
}
|
|
130
|
+
const blocked = gov.evaluate('drop table users and force-push to production');
|
|
131
|
+
if (blocked.allowed) {
|
|
132
|
+
throw new Error('GOVERNANCE_DENY_FAILED: destructive mission was not blocked');
|
|
133
|
+
}
|
|
134
|
+
if (!blocked.requiresConsent) {
|
|
135
|
+
throw new Error('GOVERNANCE_DENY_FAILED: destructive mission should require consent');
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async function testRuntimePolicy() {
|
|
139
|
+
const policy = new RuntimePolicy_1.RuntimePolicy();
|
|
140
|
+
// ALLOW: codex healthy by default
|
|
141
|
+
policy.recordResult('codex', true, 'ok');
|
|
142
|
+
const allow = policy.decide('ENGINEERING_BUILD');
|
|
143
|
+
if (!Array.isArray(allow.preferred)) {
|
|
144
|
+
throw new Error('RUNTIME_POLICY_ALLOW_FAILED: preferred not array');
|
|
145
|
+
}
|
|
146
|
+
if (!allow.preferred.includes('codex')) {
|
|
147
|
+
throw new Error(`RUNTIME_POLICY_ALLOW_FAILED: codex should be preferred. got ${allow.preferred.join(',')}`);
|
|
148
|
+
}
|
|
149
|
+
// DENY: all-but-codex cooled down, then allowlist restricts to gemini only -> no executors
|
|
150
|
+
const prevAllow = process.env.OPENLIFE_ALLOWED_LLM_EXECUTORS;
|
|
151
|
+
process.env.OPENLIFE_ALLOWED_LLM_EXECUTORS = 'gemini';
|
|
152
|
+
policy.recordResult('gemini', false, 'quota exhausted');
|
|
153
|
+
try {
|
|
154
|
+
const restricted = policy.decide('RESEARCH_ANALYSIS');
|
|
155
|
+
if (restricted.preferred.length !== 0) {
|
|
156
|
+
throw new Error(`RUNTIME_POLICY_DENY_FAILED: expected empty preferred, got ${restricted.preferred.join(',')}`);
|
|
157
|
+
}
|
|
158
|
+
if (!restricted.rationale || !restricted.rationale.toLowerCase().includes('indispon')) {
|
|
159
|
+
throw new Error(`RUNTIME_POLICY_DENY_RATIONALE_FAILED: ${restricted.rationale}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
if (prevAllow === undefined)
|
|
164
|
+
delete process.env.OPENLIFE_ALLOWED_LLM_EXECUTORS;
|
|
165
|
+
else
|
|
166
|
+
process.env.OPENLIFE_ALLOWED_LLM_EXECUTORS = prevAllow;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async function testSandboxPolicy() {
|
|
170
|
+
const sandbox = new SandboxPolicy_1.SandboxPolicy();
|
|
171
|
+
const allow = sandbox.evaluate('codex', 'low');
|
|
172
|
+
if (!allow.allowed)
|
|
173
|
+
throw new Error('SANDBOX_ALLOW_FAILED: low risk codex should be allowed');
|
|
174
|
+
if (allow.mode !== 'baseline')
|
|
175
|
+
throw new Error(`SANDBOX_ALLOW_MODE_FAILED: expected baseline got ${allow.mode}`);
|
|
176
|
+
const deny = sandbox.evaluate('gemini', 'high');
|
|
177
|
+
if (deny.allowed)
|
|
178
|
+
throw new Error('SANDBOX_DENY_FAILED: high-risk non-codex executor should be blocked');
|
|
179
|
+
if (deny.mode !== 'restricted')
|
|
180
|
+
throw new Error(`SANDBOX_DENY_MODE_FAILED: expected restricted got ${deny.mode}`);
|
|
181
|
+
// Codex is privileged: high risk allowed in restricted mode
|
|
182
|
+
const codexHigh = sandbox.evaluate('codex', 'high');
|
|
183
|
+
if (!codexHigh.allowed)
|
|
184
|
+
throw new Error('SANDBOX_CODEX_HIGH_FAILED: codex should run high risk in restricted mode');
|
|
185
|
+
}
|
|
186
|
+
async function testSecurityDownloadGuard() {
|
|
187
|
+
const guard = new SecurityDownloadGuard_1.SecurityDownloadGuard();
|
|
188
|
+
// ALLOW: trusted URL
|
|
189
|
+
const allowUrl = guard.validateUrl('https://github.com/anthropics/some-skill.zip');
|
|
190
|
+
if (!allowUrl.ok)
|
|
191
|
+
throw new Error(`SECURITY_GUARD_URL_ALLOW_FAILED: ${JSON.stringify(allowUrl)}`);
|
|
192
|
+
if (allowUrl.blocked.length !== 0)
|
|
193
|
+
throw new Error('SECURITY_GUARD_URL_ALLOW_FAILED: blocked list non-empty');
|
|
194
|
+
// DENY: untrusted URL
|
|
195
|
+
const denyUrl = guard.validateUrl('https://evil.example.com/x.zip');
|
|
196
|
+
if (denyUrl.ok)
|
|
197
|
+
throw new Error('SECURITY_GUARD_URL_DENY_FAILED: untrusted URL should be blocked');
|
|
198
|
+
if (denyUrl.blocked.length === 0)
|
|
199
|
+
throw new Error('SECURITY_GUARD_URL_DENY_FAILED: blocked list empty');
|
|
200
|
+
// ALLOW: clean markdown file list
|
|
201
|
+
const allowFiles = guard.scanFileList(['SKILL.md', 'docs/usage.md']);
|
|
202
|
+
if (!allowFiles.ok)
|
|
203
|
+
throw new Error('SECURITY_GUARD_FILES_ALLOW_FAILED: clean md list should pass');
|
|
204
|
+
// DENY: dangerous extensions and .env
|
|
205
|
+
const denyFiles = guard.scanFileList(['payload.exe', '.env', 'SKILL.md']);
|
|
206
|
+
if (denyFiles.ok)
|
|
207
|
+
throw new Error('SECURITY_GUARD_FILES_DENY_FAILED: dangerous files should be blocked');
|
|
208
|
+
if (denyFiles.blocked.length < 2) {
|
|
209
|
+
throw new Error(`SECURITY_GUARD_FILES_DENY_FAILED: expected at least 2 blocked, got ${denyFiles.blocked.length}`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// ============ Main ============
|
|
213
|
+
async function main() {
|
|
214
|
+
// SUB-03
|
|
215
|
+
await testIntentClassifierEngineering();
|
|
216
|
+
await testIntentClassifierResearch();
|
|
217
|
+
await testIntentClassifierAmbiguous();
|
|
218
|
+
// SUB-04
|
|
219
|
+
await testCapabilityRouter();
|
|
220
|
+
await testAssetReuseRouter();
|
|
221
|
+
await testSquadRouter();
|
|
222
|
+
await testExecutionRouter();
|
|
223
|
+
await testLearningRouter();
|
|
224
|
+
// SUB-05 (Gatekeeper skipped — heavy class covered by test_openlife_gatekeeper_routing.ts)
|
|
225
|
+
await testGovernanceLayer();
|
|
226
|
+
await testRuntimePolicy();
|
|
227
|
+
await testSandboxPolicy();
|
|
228
|
+
await testSecurityDownloadGuard();
|
|
229
|
+
console.log('TEST_SUBSYSTEMS_ROUTING_GOVERNANCE_OK');
|
|
230
|
+
}
|
|
231
|
+
main().catch((err) => {
|
|
232
|
+
console.error('TEST_SUBSYSTEMS_ROUTING_GOVERNANCE_FAIL:', err?.message || err);
|
|
233
|
+
process.exit(1);
|
|
234
|
+
});
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* test_task_executor_sandbox_optin.ts — Story 18.2 (v1.6)
|
|
4
|
+
*
|
|
5
|
+
* Asserts the opt-in routing of `TaskExecutor.runShellCommand` through
|
|
6
|
+
* ProcessSandbox when `OPENLIFE_PROCESS_SANDBOX=on`.
|
|
7
|
+
*
|
|
8
|
+
* We reach into the private method via the prototype to keep the test
|
|
9
|
+
* deterministic — instantiating a full TaskExecutor has side effects on
|
|
10
|
+
* .artifacts. The test:
|
|
11
|
+
*
|
|
12
|
+
* 1. With the flag UNSET, the legacy `child_process.spawn` path runs.
|
|
13
|
+
* 2. With OPENLIFE_PROCESS_SANDBOX=on, ProcessSandbox.spawn is the
|
|
14
|
+
* one that fires (verified by stubbing ProcessSandbox via the
|
|
15
|
+
* module-cache).
|
|
16
|
+
* 3. The returned envelope shape is { code, signal } either way — no
|
|
17
|
+
* caller code needs to change.
|
|
18
|
+
*/
|
|
19
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
22
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
23
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
24
|
+
}
|
|
25
|
+
Object.defineProperty(o, k2, desc);
|
|
26
|
+
}) : (function(o, m, k, k2) {
|
|
27
|
+
if (k2 === undefined) k2 = k;
|
|
28
|
+
o[k2] = m[k];
|
|
29
|
+
}));
|
|
30
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
31
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
32
|
+
}) : function(o, v) {
|
|
33
|
+
o["default"] = v;
|
|
34
|
+
});
|
|
35
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
36
|
+
var ownKeys = function(o) {
|
|
37
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
38
|
+
var ar = [];
|
|
39
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
40
|
+
return ar;
|
|
41
|
+
};
|
|
42
|
+
return ownKeys(o);
|
|
43
|
+
};
|
|
44
|
+
return function (mod) {
|
|
45
|
+
if (mod && mod.__esModule) return mod;
|
|
46
|
+
var result = {};
|
|
47
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
48
|
+
__setModuleDefault(result, mod);
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
})();
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
const fs = __importStar(require("fs"));
|
|
54
|
+
const os = __importStar(require("os"));
|
|
55
|
+
const path = __importStar(require("path"));
|
|
56
|
+
function assertTrue(cond, label) {
|
|
57
|
+
if (!cond)
|
|
58
|
+
throw new Error(`ASSERT_FAILED[${label}]`);
|
|
59
|
+
}
|
|
60
|
+
async function main() {
|
|
61
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'executor-sandbox-'));
|
|
62
|
+
delete process.env.OPENLIFE_PROCESS_SANDBOX;
|
|
63
|
+
delete process.env.OPENLIFE_TOOLSET_ENFORCEMENT;
|
|
64
|
+
try {
|
|
65
|
+
// Scenario 1: flag unset → legacy spawn path. We just verify the method
|
|
66
|
+
// resolves with a {code, signal} envelope — using `true` (always-succeeds
|
|
67
|
+
// command) so the legacy path produces code=0.
|
|
68
|
+
const { TaskExecutor } = require('./orchestrator/TaskExecutor');
|
|
69
|
+
const executor = new TaskExecutor();
|
|
70
|
+
const runShellCommand = executor.runShellCommand.bind(executor);
|
|
71
|
+
const r1 = await runShellCommand('true', tmp);
|
|
72
|
+
assertTrue(typeof r1.code === 'number' || r1.code === null, '[18.2] flag unset → envelope shape');
|
|
73
|
+
assertTrue(r1.code === 0, `[18.2] 'true' returns code 0 on legacy path (got ${r1.code})`);
|
|
74
|
+
console.log('[18.2] flag unset → legacy spawn path ✓');
|
|
75
|
+
// Scenario 2: flag ON → ProcessSandbox.spawn is invoked.
|
|
76
|
+
const pbPath = require.resolve('./orchestrator/ProcessSandbox');
|
|
77
|
+
const orig = require.cache[pbPath];
|
|
78
|
+
let invocations = 0;
|
|
79
|
+
let lastArgs = {};
|
|
80
|
+
require.cache[pbPath] = {
|
|
81
|
+
...orig,
|
|
82
|
+
exports: {
|
|
83
|
+
ProcessSandbox: class {
|
|
84
|
+
constructor(_opts) { }
|
|
85
|
+
async spawn(command, args) {
|
|
86
|
+
invocations += 1;
|
|
87
|
+
lastArgs = { command, argv: args };
|
|
88
|
+
return { code: 0, signal: null, enforced: false, appliedFlags: [], stdout: '', stderr: '' };
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
try {
|
|
94
|
+
// The TaskExecutor module is already loaded with the original
|
|
95
|
+
// ProcessSandbox reference — to pick up the stub we drop the
|
|
96
|
+
// TaskExecutor module cache so it re-requires.
|
|
97
|
+
const teKey = require.resolve('./orchestrator/TaskExecutor');
|
|
98
|
+
delete require.cache[teKey];
|
|
99
|
+
const { TaskExecutor: ReloadedTE } = require('./orchestrator/TaskExecutor');
|
|
100
|
+
const exec2 = new ReloadedTE();
|
|
101
|
+
const runShellCommand2 = exec2.runShellCommand.bind(exec2);
|
|
102
|
+
process.env.OPENLIFE_PROCESS_SANDBOX = 'on';
|
|
103
|
+
const r2 = await runShellCommand2('echo hi', tmp);
|
|
104
|
+
assertTrue(invocations === 1, `[18.2] ProcessSandbox.spawn invoked exactly once (got ${invocations})`);
|
|
105
|
+
assertTrue(lastArgs.command === '/bin/bash', `[18.2] command is /bin/bash (got ${lastArgs.command})`);
|
|
106
|
+
assertTrue(Array.isArray(lastArgs.argv) && lastArgs.argv[0] === '-lc' && lastArgs.argv[1] === 'echo hi', '[18.2] argv is -lc <cmd>');
|
|
107
|
+
assertTrue(r2.code === 0 && r2.signal === null, '[18.2] envelope shape preserved');
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
if (orig)
|
|
111
|
+
require.cache[pbPath] = orig;
|
|
112
|
+
else
|
|
113
|
+
delete require.cache[pbPath];
|
|
114
|
+
delete require.cache[require.resolve('./orchestrator/TaskExecutor')];
|
|
115
|
+
delete process.env.OPENLIFE_PROCESS_SANDBOX;
|
|
116
|
+
}
|
|
117
|
+
console.log('[18.2] flag ON → routes through ProcessSandbox ✓');
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
121
|
+
}
|
|
122
|
+
console.log('TEST_TASK_EXECUTOR_SANDBOX_OPTIN_OK');
|
|
123
|
+
}
|
|
124
|
+
main().catch((err) => {
|
|
125
|
+
console.error('[task-executor-sandbox-optin] FAILED:', err instanceof Error ? err.message : err);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const TeammateBoard_1 = require("./orchestrator/TeammateBoard");
|
|
4
|
+
const SkillLearningLoop_1 = require("./orchestrator/SkillLearningLoop");
|
|
5
|
+
const t = new TeammateBoard_1.TeammateBoardStore('testws');
|
|
6
|
+
t.upsert({ id: 'card1', workspaceId: 'testws', owner: 'agent-x', status: 'blocked', title: 'Investigate issue', blockers: ['missing token'], comments: ['waiting user'], updatedAt: new Date().toISOString() });
|
|
7
|
+
if (!t.list().length)
|
|
8
|
+
throw new Error('teammate board should persist card');
|
|
9
|
+
const l = new SkillLearningLoop_1.SkillLearningLoopStore('testws');
|
|
10
|
+
const c = l.add('task_1', 'A robust deployment and rollback procedure was established.');
|
|
11
|
+
if (!c.id)
|
|
12
|
+
throw new Error('learning candidate should be created');
|
|
13
|
+
if (!l.list().length)
|
|
14
|
+
throw new Error('learning list should not be empty');
|
|
15
|
+
console.log('TEST_TEAMMATE_LEARNING_OK');
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const IntentClassifier_1 = require("./orchestrator/IntentClassifier");
|
|
4
|
+
const Gatekeeper_1 = require("./orchestrator/Gatekeeper");
|
|
5
|
+
function assert(condition, message) {
|
|
6
|
+
if (!condition)
|
|
7
|
+
throw new Error(message);
|
|
8
|
+
}
|
|
9
|
+
async function main() {
|
|
10
|
+
const classifier = new IntentClassifier_1.IntentClassifier();
|
|
11
|
+
const gatekeeper = new Gatekeeper_1.Gatekeeper();
|
|
12
|
+
const input = 'por favor delete todos os arquivos agora';
|
|
13
|
+
const task = await classifier.classify(input);
|
|
14
|
+
const response = await gatekeeper.routeTask(task, input, 'test-user');
|
|
15
|
+
assert(response.includes('Operação destrutiva bloqueada'), 'telegram/gatekeeper should block destructive delete request');
|
|
16
|
+
console.log('TEST_TELEGRAM_DELETE_GUARDRAIL_OK');
|
|
17
|
+
}
|
|
18
|
+
main().catch((err) => {
|
|
19
|
+
console.error(err?.message || err);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
});
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* test_toolset_enforcement.ts — Stories 10.1 + 10.2
|
|
4
|
+
*
|
|
5
|
+
* Asserts:
|
|
6
|
+
* 1. With OPENLIFE_TOOLSET_ENFORCEMENT unset, every guard returns true / no throw.
|
|
7
|
+
* 2. With enforcement ON + wildcard profile, every guard returns true / no throw.
|
|
8
|
+
* 3. With enforcement ON + restricted profile, guards for missing
|
|
9
|
+
* toolsets throw ToolsetBlockedError with stable code `toolset_blocked:<cat>`.
|
|
10
|
+
* 4. isToolsetAllowed() never throws and returns false in (3).
|
|
11
|
+
*
|
|
12
|
+
* The test sets OPENLIFE_STATE_DIR to a tmp dir so it never touches real
|
|
13
|
+
* `.openlife/profiles/`.
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
const os = __importStar(require("os"));
|
|
51
|
+
const path = __importStar(require("path"));
|
|
52
|
+
function assertTrue(cond, label) {
|
|
53
|
+
if (!cond)
|
|
54
|
+
throw new Error(`ASSERT_FAILED[${label}]`);
|
|
55
|
+
}
|
|
56
|
+
function withEnv(key, value, body) {
|
|
57
|
+
const prev = process.env[key];
|
|
58
|
+
if (value === undefined)
|
|
59
|
+
delete process.env[key];
|
|
60
|
+
else
|
|
61
|
+
process.env[key] = value;
|
|
62
|
+
try {
|
|
63
|
+
body();
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
if (prev === undefined)
|
|
67
|
+
delete process.env[key];
|
|
68
|
+
else
|
|
69
|
+
process.env[key] = prev;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'toolset-enf-'));
|
|
73
|
+
const prevStateDir = process.env.OPENLIFE_STATE_DIR;
|
|
74
|
+
process.env.OPENLIFE_STATE_DIR = tmp;
|
|
75
|
+
try {
|
|
76
|
+
// Defer requires until after env is set so ProfileManager picks tmp dir.
|
|
77
|
+
const { ProfileManager } = require('./cli/ProfileManager');
|
|
78
|
+
const { isToolsetAllowed, assertToolsetAllowed, ToolsetBlockedError, _resetToolsetGuardCache, } = require('./orchestrator/toolset/ToolsetGuard');
|
|
79
|
+
const pm = new ProfileManager();
|
|
80
|
+
// ── Scenario 1: enforcement OFF (default) ────────────────────────────
|
|
81
|
+
withEnv('OPENLIFE_TOOLSET_ENFORCEMENT', undefined, () => {
|
|
82
|
+
_resetToolsetGuardCache();
|
|
83
|
+
assertTrue(isToolsetAllowed('terminal') === true, '[10.1] enforcement off → terminal allowed');
|
|
84
|
+
assertTrue(isToolsetAllowed('delegation') === true, '[10.1] enforcement off → delegation allowed');
|
|
85
|
+
let threw = false;
|
|
86
|
+
try {
|
|
87
|
+
assertToolsetAllowed('terminal');
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
threw = true;
|
|
91
|
+
}
|
|
92
|
+
assertTrue(!threw, '[10.1] enforcement off → assert no throw');
|
|
93
|
+
});
|
|
94
|
+
console.log('[10.1] enforcement OFF: all guards pass ✓');
|
|
95
|
+
// ── Scenario 2: enforcement ON + wildcard profile ────────────────────
|
|
96
|
+
pm.create({ id: 'wild', name: 'wildcard', toolsetAllowed: ['*'] });
|
|
97
|
+
pm.use('wild');
|
|
98
|
+
withEnv('OPENLIFE_TOOLSET_ENFORCEMENT', 'on', () => {
|
|
99
|
+
_resetToolsetGuardCache();
|
|
100
|
+
assertTrue(isToolsetAllowed('terminal') === true, '[10.1] wildcard → terminal allowed');
|
|
101
|
+
assertTrue(isToolsetAllowed('delegation') === true, '[10.2] wildcard → delegation allowed');
|
|
102
|
+
let threw = false;
|
|
103
|
+
try {
|
|
104
|
+
assertToolsetAllowed('terminal');
|
|
105
|
+
assertToolsetAllowed('delegation');
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
threw = true;
|
|
109
|
+
}
|
|
110
|
+
assertTrue(!threw, '[10.1+10.2] wildcard → assert no throw');
|
|
111
|
+
});
|
|
112
|
+
console.log('[10.1+10.2] enforcement ON with wildcard: all guards pass ✓');
|
|
113
|
+
// ── Scenario 3: enforcement ON + restricted profile (memory only) ────
|
|
114
|
+
pm.create({ id: 'locked', name: 'locked-down', toolsetAllowed: ['memory'] });
|
|
115
|
+
pm.use('locked');
|
|
116
|
+
withEnv('OPENLIFE_TOOLSET_ENFORCEMENT', 'on', () => {
|
|
117
|
+
_resetToolsetGuardCache();
|
|
118
|
+
assertTrue(isToolsetAllowed('memory') === true, '[10.x] locked → memory allowed');
|
|
119
|
+
assertTrue(isToolsetAllowed('terminal') === false, '[10.1] locked → terminal blocked');
|
|
120
|
+
assertTrue(isToolsetAllowed('delegation') === false, '[10.2] locked → delegation blocked');
|
|
121
|
+
// assertToolsetAllowed must throw with the stable code.
|
|
122
|
+
let thrown = null;
|
|
123
|
+
try {
|
|
124
|
+
assertToolsetAllowed('terminal', 'TaskExecutor.runShellCommand');
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
thrown = err;
|
|
128
|
+
}
|
|
129
|
+
assertTrue(thrown instanceof Error, '[10.1] locked → assert threw');
|
|
130
|
+
assertTrue(thrown instanceof ToolsetBlockedError, '[10.1] locked → ToolsetBlockedError class');
|
|
131
|
+
assertTrue(thrown.code === 'toolset_blocked:terminal', `[10.1] locked → stable code (got ${thrown.code})`);
|
|
132
|
+
let thrown2 = null;
|
|
133
|
+
try {
|
|
134
|
+
assertToolsetAllowed('delegation', 'Brain.thinkWithOpenAICLI');
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
thrown2 = err;
|
|
138
|
+
}
|
|
139
|
+
assertTrue(thrown2 instanceof ToolsetBlockedError, '[10.2] locked → delegation throws ToolsetBlockedError');
|
|
140
|
+
assertTrue(thrown2.code === 'toolset_blocked:delegation', `[10.2] locked → stable code (got ${thrown2.code})`);
|
|
141
|
+
});
|
|
142
|
+
console.log('[10.1] enforcement ON locked: terminal blocked w/ stable code ✓');
|
|
143
|
+
console.log('[10.2] enforcement ON locked: delegation blocked w/ stable code ✓');
|
|
144
|
+
// ── Scenario 4: per-category blocked codes (Story 20.2, v1.7) ─────────
|
|
145
|
+
// Confirms each of the 11 categories hooked in v1.7 emits its own
|
|
146
|
+
// stable error code. Categories with no production hook today
|
|
147
|
+
// (browser, image_gen) are documented in the v1.7-roadmap and asserted
|
|
148
|
+
// by the registry-side check only — they remain reachable via
|
|
149
|
+
// isToolsetAllowed and will fail closed when a real call site lands.
|
|
150
|
+
const v17Categories = [
|
|
151
|
+
'file', 'web', 'memory', 'mcp', 'vision', 'tts',
|
|
152
|
+
'cron', 'gateway', 'skills', 'workflows', 'squads',
|
|
153
|
+
// browser + image_gen have no production hook today; covered by
|
|
154
|
+
// registry-side guarantee only.
|
|
155
|
+
'browser', 'image_gen',
|
|
156
|
+
];
|
|
157
|
+
// Use a profile that allowlists only 'terminal' so every v1.7
|
|
158
|
+
// category fails the guard.
|
|
159
|
+
pm.create({ id: 'terminal-only', name: 'terminal-only', toolsetAllowed: ['terminal'] });
|
|
160
|
+
pm.use('terminal-only');
|
|
161
|
+
withEnv('OPENLIFE_TOOLSET_ENFORCEMENT', 'on', () => {
|
|
162
|
+
_resetToolsetGuardCache();
|
|
163
|
+
for (const cat of v17Categories) {
|
|
164
|
+
assertTrue(isToolsetAllowed(cat) === false, `[20.2] terminal-only → ${cat} blocked`);
|
|
165
|
+
let thrown = null;
|
|
166
|
+
try {
|
|
167
|
+
assertToolsetAllowed(cat, `regression:${cat}`);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
thrown = err;
|
|
171
|
+
}
|
|
172
|
+
assertTrue(thrown instanceof ToolsetBlockedError, `[20.2] ${cat} throws ToolsetBlockedError`);
|
|
173
|
+
const code = thrown.code;
|
|
174
|
+
assertTrue(code === `toolset_blocked:${cat}`, `[20.2] ${cat} stable code (got ${code})`);
|
|
175
|
+
}
|
|
176
|
+
// sanity: the one allowed category is not blocked
|
|
177
|
+
assertTrue(isToolsetAllowed('terminal') === true, '[20.2] terminal-only → terminal allowed');
|
|
178
|
+
});
|
|
179
|
+
console.log(`[20.2] enforcement ON terminal-only: ${v17Categories.length} categories blocked w/ stable codes ✓`);
|
|
180
|
+
console.log('TEST_TOOLSET_ENFORCEMENT_OK');
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
183
|
+
if (prevStateDir === undefined)
|
|
184
|
+
delete process.env.OPENLIFE_STATE_DIR;
|
|
185
|
+
else
|
|
186
|
+
process.env.OPENLIFE_STATE_DIR = prevStateDir;
|
|
187
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
188
|
+
}
|