@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,262 @@
|
|
|
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
|
+
* Story 3.8 — OPENLIFE_RUNTIME_PROFILE=oauth-only regression test.
|
|
38
|
+
*
|
|
39
|
+
* Hardens the previously undocumented "oauth-only" runtime profile defined in
|
|
40
|
+
* `src/cli/WorldClassCommands.ts` (`doctorWorldDetailed()`). The profile is a
|
|
41
|
+
* pure SEVERITY CLASSIFIER — it downgrades four specific doctor checks from
|
|
42
|
+
* `blocker` to `info` when the operator runs OAuth-authenticated LLM CLIs
|
|
43
|
+
* (`claude`, `codex`, `gemini`) instead of API keys. It does NOT alter the
|
|
44
|
+
* Brain.ts provider chain.
|
|
45
|
+
*
|
|
46
|
+
* Asserts (4 scenarios):
|
|
47
|
+
* a) Default profile (no env var) — failing oauth-downgrade names come back
|
|
48
|
+
* with their non-`info` default severity (cli:ollama → blocker; the three
|
|
49
|
+
* env:*_API_KEY → warning). In short: NONE of the four is `info`.
|
|
50
|
+
* b) `oauth-only` set — failing names of cli:ollama / env:OPENAI_API_KEY /
|
|
51
|
+
* env:GEMINI_API_KEY / env:ANTHROPIC_API_KEY all come back as `info`.
|
|
52
|
+
* c) Case-insensitive — `OAuth-Only` triggers the same downgrade
|
|
53
|
+
* (the classifier calls `.toLowerCase()`).
|
|
54
|
+
* d) Other failing checks are unaffected — e.g. `cli:codex`, `cli:claude`,
|
|
55
|
+
* `runtime:*` stay non-`info` even with oauth-only profile.
|
|
56
|
+
*
|
|
57
|
+
* Test seams used (per project convention — production code is strict):
|
|
58
|
+
* - process.chdir(tempDir) because WorldClassCommands reads process.cwd().
|
|
59
|
+
* - Mutate process.env directly and restore in finally.
|
|
60
|
+
*/
|
|
61
|
+
const fs = __importStar(require("fs"));
|
|
62
|
+
const path = __importStar(require("path"));
|
|
63
|
+
const os = __importStar(require("os"));
|
|
64
|
+
function assert(cond, msg) {
|
|
65
|
+
if (!cond)
|
|
66
|
+
throw new Error(`ASSERTION_FAILED: ${msg}`);
|
|
67
|
+
}
|
|
68
|
+
const OAUTH_DOWNGRADE_NAMES = [
|
|
69
|
+
'cli:ollama',
|
|
70
|
+
'env:OPENAI_API_KEY',
|
|
71
|
+
'env:GEMINI_API_KEY',
|
|
72
|
+
'env:ANTHROPIC_API_KEY'
|
|
73
|
+
];
|
|
74
|
+
function makeTempDir(label) {
|
|
75
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), `openlife-oauth-only-${label}-`));
|
|
76
|
+
return dir;
|
|
77
|
+
}
|
|
78
|
+
const PROBE_KEYS = [
|
|
79
|
+
'OPENLIFE_RUNTIME_PROFILE',
|
|
80
|
+
'OPENLIFE_ENABLE_OLLAMA',
|
|
81
|
+
'OPENAI_API_KEY',
|
|
82
|
+
'GEMINI_API_KEY',
|
|
83
|
+
'ANTHROPIC_API_KEY',
|
|
84
|
+
'TELEGRAM_BOT_TOKEN'
|
|
85
|
+
];
|
|
86
|
+
function snapshotEnvAndCwd() {
|
|
87
|
+
const envBackup = {};
|
|
88
|
+
for (const k of PROBE_KEYS)
|
|
89
|
+
envBackup[k] = process.env[k];
|
|
90
|
+
return { cwd: process.cwd(), envBackup };
|
|
91
|
+
}
|
|
92
|
+
function restoreEnvAndCwd(snap) {
|
|
93
|
+
for (const k of PROBE_KEYS) {
|
|
94
|
+
const v = snap.envBackup[k];
|
|
95
|
+
if (v === undefined)
|
|
96
|
+
delete process.env[k];
|
|
97
|
+
else
|
|
98
|
+
process.env[k] = v;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
process.chdir(snap.cwd);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
/* best effort */
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function clearApiKeysAndProfile() {
|
|
108
|
+
// Force the four oauth-downgrade checks to FAIL.
|
|
109
|
+
delete process.env.OPENAI_API_KEY;
|
|
110
|
+
delete process.env.GEMINI_API_KEY;
|
|
111
|
+
delete process.env.ANTHROPIC_API_KEY;
|
|
112
|
+
// Force cli:ollama check to actually run AND fail (PATH probably has no ollama).
|
|
113
|
+
process.env.OPENLIFE_ENABLE_OLLAMA = 'true';
|
|
114
|
+
// Default: clear the profile.
|
|
115
|
+
delete process.env.OPENLIFE_RUNTIME_PROFILE;
|
|
116
|
+
}
|
|
117
|
+
function runDoctor() {
|
|
118
|
+
// Late require — production code only loads on demand.
|
|
119
|
+
const mod = require('../dist/cli/WorldClassCommands');
|
|
120
|
+
const wc = new mod.WorldClassCommands();
|
|
121
|
+
return wc.doctorWorldDetailed();
|
|
122
|
+
}
|
|
123
|
+
function findCheck(results, name) {
|
|
124
|
+
return results.find((r) => r.name === name);
|
|
125
|
+
}
|
|
126
|
+
// -----------------------------------------------------------------------------
|
|
127
|
+
// Scenario A: default profile — failing oauth-downgrade names are NOT `info`.
|
|
128
|
+
//
|
|
129
|
+
// The default classifier in WorldClassCommands.ts routes:
|
|
130
|
+
// - `cli:ollama` → blocker (cli:* branch)
|
|
131
|
+
// - `env:OPENAI_API_KEY` → warning (no special branch, falls through)
|
|
132
|
+
// - `env:GEMINI_API_KEY` → warning
|
|
133
|
+
// - `env:ANTHROPIC_API_KEY`→ warning
|
|
134
|
+
// The contract this test pins down is: none of them is `info` by default.
|
|
135
|
+
// (Scenario B verifies they ALL flip to `info` under oauth-only.)
|
|
136
|
+
// -----------------------------------------------------------------------------
|
|
137
|
+
function testDefaultProfileKeepsNonInfoSeverity() {
|
|
138
|
+
const tmp = makeTempDir('default');
|
|
139
|
+
const snap = snapshotEnvAndCwd();
|
|
140
|
+
try {
|
|
141
|
+
process.chdir(tmp);
|
|
142
|
+
clearApiKeysAndProfile();
|
|
143
|
+
// Explicitly NO profile set.
|
|
144
|
+
assert(!process.env.OPENLIFE_RUNTIME_PROFILE, 'precondition: OPENLIFE_RUNTIME_PROFILE must be unset');
|
|
145
|
+
const results = runDoctor();
|
|
146
|
+
const expectedDefault = {
|
|
147
|
+
'cli:ollama': 'blocker',
|
|
148
|
+
'env:OPENAI_API_KEY': 'warning',
|
|
149
|
+
'env:GEMINI_API_KEY': 'warning',
|
|
150
|
+
'env:ANTHROPIC_API_KEY': 'warning'
|
|
151
|
+
};
|
|
152
|
+
for (const name of OAUTH_DOWNGRADE_NAMES) {
|
|
153
|
+
const c = findCheck(results, name);
|
|
154
|
+
assert(c, `default-profile: doctor result must include "${name}"`);
|
|
155
|
+
// We forced these to fail (no API keys, no ollama on PATH typically).
|
|
156
|
+
assert(c.ok === false, `default-profile: "${name}" must be failing for the test to be meaningful; got ok=${c.ok}`);
|
|
157
|
+
assert(c.severity !== 'info', `default-profile: failing "${name}" must NOT be info without oauth-only profile; got "${c.severity}"`);
|
|
158
|
+
assert(c.severity === expectedDefault[name], `default-profile: failing "${name}" must have severity="${expectedDefault[name]}" (default classifier); got "${c.severity}"`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
restoreEnvAndCwd(snap);
|
|
163
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// -----------------------------------------------------------------------------
|
|
167
|
+
// Scenario B: oauth-only — failing oauth-downgrade names are `info`.
|
|
168
|
+
// -----------------------------------------------------------------------------
|
|
169
|
+
function testOauthOnlyDowngradesToInfo() {
|
|
170
|
+
const tmp = makeTempDir('oauth');
|
|
171
|
+
const snap = snapshotEnvAndCwd();
|
|
172
|
+
try {
|
|
173
|
+
process.chdir(tmp);
|
|
174
|
+
clearApiKeysAndProfile();
|
|
175
|
+
process.env.OPENLIFE_RUNTIME_PROFILE = 'oauth-only';
|
|
176
|
+
const results = runDoctor();
|
|
177
|
+
for (const name of OAUTH_DOWNGRADE_NAMES) {
|
|
178
|
+
const c = findCheck(results, name);
|
|
179
|
+
assert(c, `oauth-only: doctor result must include "${name}"`);
|
|
180
|
+
assert(c.ok === false, `oauth-only: "${name}" must still be failing (no keys/ollama); got ok=${c.ok}`);
|
|
181
|
+
assert(c.severity === 'info', `oauth-only: failing "${name}" must be downgraded to severity=info; got "${c.severity}"`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
restoreEnvAndCwd(snap);
|
|
186
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// -----------------------------------------------------------------------------
|
|
190
|
+
// Scenario C: case-insensitive — `OAuth-Only` also downgrades.
|
|
191
|
+
// -----------------------------------------------------------------------------
|
|
192
|
+
function testOauthOnlyIsCaseInsensitive() {
|
|
193
|
+
const tmp = makeTempDir('caseins');
|
|
194
|
+
const snap = snapshotEnvAndCwd();
|
|
195
|
+
try {
|
|
196
|
+
process.chdir(tmp);
|
|
197
|
+
clearApiKeysAndProfile();
|
|
198
|
+
process.env.OPENLIFE_RUNTIME_PROFILE = 'OAuth-Only';
|
|
199
|
+
const results = runDoctor();
|
|
200
|
+
for (const name of OAUTH_DOWNGRADE_NAMES) {
|
|
201
|
+
const c = findCheck(results, name);
|
|
202
|
+
assert(c, `case-insensitive: doctor result must include "${name}"`);
|
|
203
|
+
assert(c.ok === false, `case-insensitive: "${name}" must be failing`);
|
|
204
|
+
assert(c.severity === 'info', `case-insensitive: "OAuth-Only" must downgrade "${name}" to severity=info; got "${c.severity}" — classifier .toLowerCase() contract broken?`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
finally {
|
|
208
|
+
restoreEnvAndCwd(snap);
|
|
209
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// -----------------------------------------------------------------------------
|
|
213
|
+
// Scenario D: other failing checks are unaffected (not silently demoted).
|
|
214
|
+
// -----------------------------------------------------------------------------
|
|
215
|
+
function testOtherChecksUnaffectedByOauthOnly() {
|
|
216
|
+
const tmp = makeTempDir('others');
|
|
217
|
+
const snap = snapshotEnvAndCwd();
|
|
218
|
+
try {
|
|
219
|
+
process.chdir(tmp);
|
|
220
|
+
clearApiKeysAndProfile();
|
|
221
|
+
process.env.OPENLIFE_RUNTIME_PROFILE = 'oauth-only';
|
|
222
|
+
// Telegram unset → env:TELEGRAM_BOT_TOKEN should fail and stay blocker.
|
|
223
|
+
delete process.env.TELEGRAM_BOT_TOKEN;
|
|
224
|
+
const results = runDoctor();
|
|
225
|
+
// We expect at LEAST one failing non-downgraded check to be present so the
|
|
226
|
+
// assertion has bite. cli:codex / cli:claude / env:TELEGRAM_BOT_TOKEN are
|
|
227
|
+
// very likely to fail inside a fresh tmp dir with cleared env.
|
|
228
|
+
const failingOthers = results.filter((r) => {
|
|
229
|
+
if (r.ok)
|
|
230
|
+
return false;
|
|
231
|
+
if (OAUTH_DOWNGRADE_NAMES.includes(r.name))
|
|
232
|
+
return false;
|
|
233
|
+
// Only consider names the classifier flags as blocker/warning — i.e. names
|
|
234
|
+
// that the classifier branches MAY have moved to blocker.
|
|
235
|
+
const looksRouted = r.name.startsWith('runtime:') ||
|
|
236
|
+
r.name.includes('TELEGRAM_BOT_TOKEN') ||
|
|
237
|
+
r.name.startsWith('cli:') ||
|
|
238
|
+
r.name.includes('promoted-assets') ||
|
|
239
|
+
r.name.includes('security-events');
|
|
240
|
+
return looksRouted;
|
|
241
|
+
});
|
|
242
|
+
assert(failingOthers.length > 0, 'precondition: at least one failing non-oauth-downgrade check must exist to make this scenario meaningful');
|
|
243
|
+
for (const c of failingOthers) {
|
|
244
|
+
assert(c.severity !== 'info', `oauth-only must NOT downgrade unrelated check "${c.name}" to info; got severity="${c.severity}"`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
finally {
|
|
248
|
+
restoreEnvAndCwd(snap);
|
|
249
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
async function main() {
|
|
253
|
+
testDefaultProfileKeepsNonInfoSeverity();
|
|
254
|
+
testOauthOnlyDowngradesToInfo();
|
|
255
|
+
testOauthOnlyIsCaseInsensitive();
|
|
256
|
+
testOtherChecksUnaffectedByOauthOnly();
|
|
257
|
+
console.log('TEST_RUNTIME_PROFILE_OAUTH_ONLY_OK');
|
|
258
|
+
}
|
|
259
|
+
main().catch((err) => {
|
|
260
|
+
console.error('TEST_RUNTIME_PROFILE_OAUTH_ONLY_FAIL:', err?.message || err);
|
|
261
|
+
process.exit(1);
|
|
262
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const RuntimeRegistry_1 = require("./orchestrator/RuntimeRegistry");
|
|
4
|
+
const rr = new RuntimeRegistry_1.RuntimeRegistry('testws');
|
|
5
|
+
const probed = rr.probe();
|
|
6
|
+
if (!probed.length)
|
|
7
|
+
throw new Error('runtime probe should return entries');
|
|
8
|
+
const listed = rr.list();
|
|
9
|
+
if (!listed.length)
|
|
10
|
+
throw new Error('runtime list should return entries');
|
|
11
|
+
console.log('TEST_RUNTIME_REGISTRY_OK');
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* test_security_download_and_scan.ts — Stories 9.1 + 9.2
|
|
4
|
+
*
|
|
5
|
+
* Asserts:
|
|
6
|
+
* 1. SecurityDownloadGuard.downloadAndScan() refuses untrusted URLs
|
|
7
|
+
* 2. downloadAndScan() returns errors for unreachable hosts
|
|
8
|
+
* 3. downloadAndScan() rejects blocked filename patterns (e.g. .exe)
|
|
9
|
+
* 4. ExternalCatalogRegistry.import() returns policy decision (no fetch)
|
|
10
|
+
* 5. ExternalCatalogRegistry.importAndFetch() reports network failure
|
|
11
|
+
* gracefully (we can't actually reach github.com in test env)
|
|
12
|
+
*
|
|
13
|
+
* NOTE: No live network calls expected on CI; all assertions verify
|
|
14
|
+
* graceful failure modes, never success-with-network.
|
|
15
|
+
*/
|
|
16
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(o, k2, desc);
|
|
23
|
+
}) : (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
o[k2] = m[k];
|
|
26
|
+
}));
|
|
27
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
+
}) : function(o, v) {
|
|
30
|
+
o["default"] = v;
|
|
31
|
+
});
|
|
32
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
+
var ownKeys = function(o) {
|
|
34
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
+
var ar = [];
|
|
36
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
+
return ar;
|
|
38
|
+
};
|
|
39
|
+
return ownKeys(o);
|
|
40
|
+
};
|
|
41
|
+
return function (mod) {
|
|
42
|
+
if (mod && mod.__esModule) return mod;
|
|
43
|
+
var result = {};
|
|
44
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
+
__setModuleDefault(result, mod);
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
})();
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
const fs = __importStar(require("fs"));
|
|
51
|
+
const os = __importStar(require("os"));
|
|
52
|
+
const path = __importStar(require("path"));
|
|
53
|
+
const SecurityDownloadGuard_1 = require("./orchestrator/SecurityDownloadGuard");
|
|
54
|
+
const ExternalCatalogRegistry_1 = require("./orchestrator/ExternalCatalogRegistry");
|
|
55
|
+
function assertTrue(cond, label) {
|
|
56
|
+
if (!cond)
|
|
57
|
+
throw new Error(`ASSERT_FAILED[${label}]`);
|
|
58
|
+
}
|
|
59
|
+
async function main() {
|
|
60
|
+
const guard = new SecurityDownloadGuard_1.SecurityDownloadGuard();
|
|
61
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'dl-scan-'));
|
|
62
|
+
try {
|
|
63
|
+
// 1. Untrusted URL rejected before fetch
|
|
64
|
+
const r1 = await guard.downloadAndScan('https://evil.example/foo.md', tmp, { timeoutMs: 1000 });
|
|
65
|
+
assertTrue(!r1.ok, 'untrusted url rejected');
|
|
66
|
+
assertTrue(r1.errors.includes('untrusted_url'), 'errors include untrusted_url');
|
|
67
|
+
console.log('[9.1] untrusted URL rejected ✓');
|
|
68
|
+
// 2. Trusted URL but unreachable host → fetch_exception or timeout
|
|
69
|
+
const r2 = await guard.downloadAndScan('https://github.com/this/does/not/exist/12345.md', tmp, { timeoutMs: 3000 });
|
|
70
|
+
assertTrue(!r2.ok, 'unreachable/404 yields not ok');
|
|
71
|
+
console.log(`[9.1] trusted URL but unreachable rejected (${r2.errors[0]}) ✓`);
|
|
72
|
+
// 3. Filename blocked pattern — simulate by passing a URL ending in .exe.
|
|
73
|
+
// We won't actually reach it because the URL is trusted but unreachable,
|
|
74
|
+
// but we verify the scan path is wired.
|
|
75
|
+
const r3 = await guard.downloadAndScan('https://github.com/x/y/blob/main/bad.exe', tmp, { timeoutMs: 3000 });
|
|
76
|
+
assertTrue(!r3.ok, 'blocked filename pattern rejected');
|
|
77
|
+
console.log(`[9.1] blocked filename rejected (${r3.errors[0]}) ✓`);
|
|
78
|
+
// 4. ExternalCatalogRegistry.import — policy-only
|
|
79
|
+
const reg = new ExternalCatalogRegistry_1.ExternalCatalogRegistry();
|
|
80
|
+
const i1 = reg.import('github', 'somepack');
|
|
81
|
+
assertTrue(i1.ok, 'import-allowed source returns ok');
|
|
82
|
+
assertTrue(!('downloadedTo' in i1), 'no downloadedTo on policy-only path');
|
|
83
|
+
console.log('[9.2] ExternalCatalogRegistry.import policy-only ✓');
|
|
84
|
+
// 5. importAndFetch reports failure gracefully
|
|
85
|
+
const i2 = await reg.importAndFetch('github', 'somepack', 'https://github.com/this/does/not/exist/12345.md', tmp);
|
|
86
|
+
assertTrue(!i2.ok, 'importAndFetch reports failure');
|
|
87
|
+
assertTrue(i2.error === 'download_or_scan_failed', `error code matches (got ${i2.error})`);
|
|
88
|
+
console.log('[9.2] ExternalCatalogRegistry.importAndFetch graceful failure ✓');
|
|
89
|
+
// 6. importAndFetch refuses reference-only source
|
|
90
|
+
const i3 = await reg.importAndFetch('skills-sh', 'somepack', 'https://github.com/foo/bar.md', tmp);
|
|
91
|
+
assertTrue(!i3.ok, 'reference-only source refused');
|
|
92
|
+
assertTrue(i3.error === 'source_is_reference_only', `reference rejection (got ${i3.error})`);
|
|
93
|
+
console.log('[9.2] reference-only source refused by importAndFetch ✓');
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
97
|
+
}
|
|
98
|
+
console.log('TEST_SECURITY_DOWNLOAD_AND_SCAN_OK');
|
|
99
|
+
}
|
|
100
|
+
main().catch((err) => {
|
|
101
|
+
console.error('[download-and-scan] FAILED:', err instanceof Error ? err.message : err);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const SecurityDownloadGuard_1 = require("./orchestrator/SecurityDownloadGuard");
|
|
4
|
+
const g = new SecurityDownloadGuard_1.SecurityDownloadGuard();
|
|
5
|
+
const good = g.validateUrl('https://skills.sh/');
|
|
6
|
+
if (!good.ok)
|
|
7
|
+
throw new Error('skills.sh should be allowed reference');
|
|
8
|
+
const bad = g.validateUrl('https://evil.example.com/dropper.zip');
|
|
9
|
+
if (bad.ok)
|
|
10
|
+
throw new Error('untrusted should be blocked');
|
|
11
|
+
const scan = g.scanFileList(['pack/SKILL.md', 'pack/.env', 'pack/run.exe']);
|
|
12
|
+
if (scan.ok)
|
|
13
|
+
throw new Error('malicious files should be blocked');
|
|
14
|
+
console.log('TEST_SECURITY_DOWNLOAD_GUARD_OK');
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const ServiceState_1 = require("./orchestrator/ServiceState");
|
|
4
|
+
function assert(condition, message) {
|
|
5
|
+
if (!condition)
|
|
6
|
+
throw new Error(message);
|
|
7
|
+
}
|
|
8
|
+
const store = new ServiceState_1.ServiceStateStore();
|
|
9
|
+
const serviceId = `test_service_${Date.now()}`;
|
|
10
|
+
const missing = store.getById(serviceId);
|
|
11
|
+
assert(missing === null, 'new service should be null before promotion');
|
|
12
|
+
console.log('TEST_SERVICE_COMMAND_SURFACE_OK');
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const ServiceCompletionPolicy_1 = require("./orchestrator/ServiceCompletionPolicy");
|
|
4
|
+
const ExecutionState_1 = require("./orchestrator/ExecutionState");
|
|
5
|
+
function assert(condition, message) {
|
|
6
|
+
if (!condition)
|
|
7
|
+
throw new Error(message);
|
|
8
|
+
}
|
|
9
|
+
async function main() {
|
|
10
|
+
const policy = new ServiceCompletionPolicy_1.ServiceCompletionPolicy();
|
|
11
|
+
const criteria = policy.enforceCriteria(['Resultado útil']);
|
|
12
|
+
assert(criteria.includes('Provisionamento concluído'), 'must enforce provisioning criterion');
|
|
13
|
+
assert(criteria.includes('Operação real documentada'), 'must enforce operational criterion');
|
|
14
|
+
const incomplete = (0, ExecutionState_1.createExecutionState)('t1', 'goal', 'u1');
|
|
15
|
+
incomplete.plan = ['a', 'b'];
|
|
16
|
+
incomplete.successCriteria = ['x'];
|
|
17
|
+
const reportIncomplete = policy.evaluate(incomplete);
|
|
18
|
+
assert(reportIncomplete.complete === false, 'should detect incomplete service');
|
|
19
|
+
const complete = (0, ExecutionState_1.createExecutionState)('t2', 'goal', 'u1');
|
|
20
|
+
complete.plan = ['analisar', 'executar', 'validar'];
|
|
21
|
+
complete.successCriteria = policy.enforceCriteria(['resultado']);
|
|
22
|
+
complete.attempts.push({ role: 'executor', summary: 'exec ok', status: 'success', at: new Date().toISOString(), artifactPath: '.artifacts/a.txt' });
|
|
23
|
+
complete.attempts.push({ role: 'reviewer', summary: 'review ok', status: 'success', at: new Date().toISOString() });
|
|
24
|
+
complete.artifacts.push('.artifacts/a.txt');
|
|
25
|
+
const reportComplete = policy.evaluate(complete);
|
|
26
|
+
assert(reportComplete.complete === true, 'should pass complete service report');
|
|
27
|
+
console.log('TEST_SERVICE_COMPLETION_POLICY_OK');
|
|
28
|
+
}
|
|
29
|
+
main().catch((error) => {
|
|
30
|
+
console.error(error.message || error);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const GovernanceLayer_1 = require("./orchestrator/GovernanceLayer");
|
|
4
|
+
function assert(condition, message) {
|
|
5
|
+
if (!condition)
|
|
6
|
+
throw new Error(message);
|
|
7
|
+
}
|
|
8
|
+
const governance = new GovernanceLayer_1.GovernanceLayer();
|
|
9
|
+
const deletionRequest = governance.evaluate('please delete all user files now');
|
|
10
|
+
assert(deletionRequest.allowed === false, 'delete requests must be blocked by default');
|
|
11
|
+
assert(deletionRequest.requiresConsent === true, 'delete requests must require explicit consent');
|
|
12
|
+
console.log('TEST_SERVICE_GUARDRAILS_DELETE_OK');
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* test_service_mode_explicit_only.ts — Stories 2.3 + 2.4
|
|
4
|
+
*
|
|
5
|
+
* Asserts the v1.3 explicit-only service-mode contract:
|
|
6
|
+
* - WorkflowEngine.run() throws if workflow.mode='service' and caller
|
|
7
|
+
* did not pass allowServiceMode=true.
|
|
8
|
+
* - WorkflowEngine.run() succeeds for the same workflow when caller
|
|
9
|
+
* explicitly opts in.
|
|
10
|
+
* - ServiceState.promoteTaskToService() refuses silent promotion
|
|
11
|
+
* (no actor, system actor, missing consent scope).
|
|
12
|
+
* - ServiceState.promoteTaskToService() succeeds with explicit human
|
|
13
|
+
* actor + consentScope='task_promotion'.
|
|
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 path = __importStar(require("path"));
|
|
51
|
+
const os = __importStar(require("os"));
|
|
52
|
+
const WorkflowEngine_1 = require("./orchestrator/workflow/WorkflowEngine");
|
|
53
|
+
const ServiceState_1 = require("./orchestrator/ServiceState");
|
|
54
|
+
function assertTrue(cond, label) {
|
|
55
|
+
if (!cond)
|
|
56
|
+
throw new Error(`ASSERT_FAILED[${label}]`);
|
|
57
|
+
}
|
|
58
|
+
async function main() {
|
|
59
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'service-mode-explicit-'));
|
|
60
|
+
const stateDir = path.join(tmp, '.openlife');
|
|
61
|
+
fs.mkdirSync(stateDir, { recursive: true });
|
|
62
|
+
try {
|
|
63
|
+
// ── Scenario 1: WorkflowEngine refuses service mode without opt-in ──
|
|
64
|
+
const serviceWf = {
|
|
65
|
+
id: 'svc-wf',
|
|
66
|
+
name: 'Service workflow',
|
|
67
|
+
type: 'custom',
|
|
68
|
+
version: '1.0',
|
|
69
|
+
mode: 'service',
|
|
70
|
+
sequence: [{ id: 'step-1', agent: 'dev', action: 'do' }],
|
|
71
|
+
};
|
|
72
|
+
const engine = new WorkflowEngine_1.WorkflowEngine({ stateDir });
|
|
73
|
+
let threwOnImplicit = false;
|
|
74
|
+
let errCode;
|
|
75
|
+
try {
|
|
76
|
+
await engine.run(serviceWf, {});
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
threwOnImplicit = true;
|
|
80
|
+
errCode = e.code;
|
|
81
|
+
}
|
|
82
|
+
assertTrue(threwOnImplicit, 'scenario 1: implicit service run rejected');
|
|
83
|
+
assertTrue(errCode === 'service_mode_requires_explicit_opt_in', `scenario 1: error code (got ${errCode})`);
|
|
84
|
+
console.log('[2.3] scenario 1 (implicit service run refused) ✓');
|
|
85
|
+
// ── Scenario 2: WorkflowEngine accepts service mode with opt-in ─────
|
|
86
|
+
const state = await engine.run(serviceWf, {}, { allowServiceMode: true });
|
|
87
|
+
assertTrue(state.status === 'completed' || state.status === 'awaiting_input' || state.status === 'failed', 'scenario 2: service run executes');
|
|
88
|
+
assertTrue(state.context?.__mode === 'service', 'scenario 2: mode plumbed to context');
|
|
89
|
+
console.log('[2.3] scenario 2 (explicit service run accepted) ✓');
|
|
90
|
+
// ── Scenario 3: task workflow runs without any flag ────────────────
|
|
91
|
+
const taskWf = {
|
|
92
|
+
id: 'task-wf',
|
|
93
|
+
name: 'Task workflow',
|
|
94
|
+
type: 'custom',
|
|
95
|
+
version: '1.0',
|
|
96
|
+
sequence: [{ id: 'step-1', agent: 'dev', action: 'do' }],
|
|
97
|
+
};
|
|
98
|
+
const taskState = await engine.run(taskWf, {});
|
|
99
|
+
assertTrue(taskState.context?.__mode === 'task', 'scenario 3: defaults to task mode');
|
|
100
|
+
console.log('[2.3] scenario 3 (task is default) ✓');
|
|
101
|
+
// ── Scenario 4: promoteTaskToService refuses missing actor ─────────
|
|
102
|
+
// ServiceStateStore reads .artifacts/workspaces/<wsId>/... via process.cwd(),
|
|
103
|
+
// so run the test from within tmp.
|
|
104
|
+
const origCwd = process.cwd();
|
|
105
|
+
process.chdir(tmp);
|
|
106
|
+
const svcStore = new ServiceState_1.ServiceStateStore('test-ws');
|
|
107
|
+
// Minimal MissionState — ServiceStateStore.promoteTaskToService only
|
|
108
|
+
// reads .taskId, .goal, and optional .consequenceThoughtTrace.
|
|
109
|
+
const mission = {
|
|
110
|
+
taskId: 'mission-1',
|
|
111
|
+
goal: 'test goal',
|
|
112
|
+
};
|
|
113
|
+
let threw1 = false;
|
|
114
|
+
let err1;
|
|
115
|
+
try {
|
|
116
|
+
svcStore.promoteTaskToService(mission, 'svc-from-missing-actor', undefined);
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
threw1 = true;
|
|
120
|
+
err1 = e.code;
|
|
121
|
+
}
|
|
122
|
+
assertTrue(threw1, 'scenario 4: missing actor refused');
|
|
123
|
+
assertTrue(err1 === 'task_promotion_requires_human_actor', `scenario 4: error code (got ${err1})`);
|
|
124
|
+
console.log('[2.4] scenario 4 (missing actor refused) ✓');
|
|
125
|
+
// ── Scenario 5: promoteTaskToService refuses system actor ──────────
|
|
126
|
+
let threw2 = false;
|
|
127
|
+
let err2;
|
|
128
|
+
try {
|
|
129
|
+
svcStore.promoteTaskToService(mission, 'svc-from-system', undefined, { actor: 'system', consentScope: 'task_promotion' });
|
|
130
|
+
}
|
|
131
|
+
catch (e) {
|
|
132
|
+
threw2 = true;
|
|
133
|
+
err2 = e.code;
|
|
134
|
+
}
|
|
135
|
+
assertTrue(threw2, 'scenario 5: system actor refused');
|
|
136
|
+
assertTrue(err2 === 'task_promotion_requires_human_actor', `scenario 5: error code (got ${err2})`);
|
|
137
|
+
console.log('[2.4] scenario 5 (system actor refused) ✓');
|
|
138
|
+
// ── Scenario 6: promoteTaskToService refuses missing consent scope ─
|
|
139
|
+
let threw3 = false;
|
|
140
|
+
let err3;
|
|
141
|
+
try {
|
|
142
|
+
svcStore.promoteTaskToService(mission, 'svc-no-scope', undefined, { actor: 'rafa' });
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
threw3 = true;
|
|
146
|
+
err3 = e.code;
|
|
147
|
+
}
|
|
148
|
+
assertTrue(threw3, 'scenario 6: missing consent scope refused');
|
|
149
|
+
assertTrue(err3 === 'task_promotion_requires_consent_scope', `scenario 6: error code (got ${err3})`);
|
|
150
|
+
console.log('[2.4] scenario 6 (missing consent scope refused) ✓');
|
|
151
|
+
// ── Scenario 7: explicit human actor + scope succeeds ──────────────
|
|
152
|
+
const svc = svcStore.promoteTaskToService(mission, 'svc-ok', 'real promotion', {
|
|
153
|
+
actor: 'rafa',
|
|
154
|
+
consentScope: 'task_promotion',
|
|
155
|
+
reason: 'long-running research',
|
|
156
|
+
});
|
|
157
|
+
assertTrue(svc.serviceId === 'svc-ok', 'scenario 7: service created');
|
|
158
|
+
assertTrue(svc.missionIds.includes('mission-1'), 'scenario 7: mission attached');
|
|
159
|
+
console.log('[2.4] scenario 7 (explicit promotion succeeds) ✓');
|
|
160
|
+
process.chdir(origCwd);
|
|
161
|
+
console.log('TEST_SERVICE_MODE_EXPLICIT_ONLY_OK');
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
try {
|
|
165
|
+
process.chdir(path.dirname(tmp));
|
|
166
|
+
}
|
|
167
|
+
catch { /* ignore */ }
|
|
168
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
main().catch((err) => {
|
|
172
|
+
console.error('[service-mode-explicit] FAILED:', err instanceof Error ? err.message : err);
|
|
173
|
+
process.exit(1);
|
|
174
|
+
});
|