@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,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* test_capability_genesis_engine.ts — Stories 1.2/1.3/1.4/1.5
|
|
4
|
+
*
|
|
5
|
+
* Integration test covering the whole Sprint 1 stack:
|
|
6
|
+
* 1. CapabilityGenesisEngine.generate() produces a draft pack
|
|
7
|
+
* 2. The manifest parses cleanly via CapabilityPackParser
|
|
8
|
+
* 3. FileCapabilityProvider.list() finds the new pack
|
|
9
|
+
* 4. CapabilityPackStateStore tracks the pack as draft
|
|
10
|
+
* 5. CompositeCapabilityProvider primary/fallback chain works
|
|
11
|
+
* 6. CompositeWorkflowProvider primary/fallback chain works
|
|
12
|
+
* 7. Lifecycle transitions follow the state machine (draft→tested→active)
|
|
13
|
+
* 8. Invalid transitions are rejected
|
|
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 CapabilityGenesisEngine_1 = require("./orchestrator/capability/CapabilityGenesisEngine");
|
|
53
|
+
const CapabilityPackState_1 = require("./orchestrator/capability/CapabilityPackState");
|
|
54
|
+
const CapabilityPackParser_1 = require("./orchestrator/capability/CapabilityPackParser");
|
|
55
|
+
const FileCapabilityProvider_1 = require("./orchestrator/providers/FileCapabilityProvider");
|
|
56
|
+
const CompositeCapabilityProvider_1 = require("./orchestrator/providers/CompositeCapabilityProvider");
|
|
57
|
+
const CompositeWorkflowProvider_1 = require("./orchestrator/providers/CompositeWorkflowProvider");
|
|
58
|
+
function assertTrue(cond, label) {
|
|
59
|
+
if (!cond)
|
|
60
|
+
throw new Error(`ASSERT_FAILED[${label}]`);
|
|
61
|
+
}
|
|
62
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'capability-genesis-'));
|
|
63
|
+
const catalogRoot = path.join(tmp, 'catalog', 'capabilities');
|
|
64
|
+
const stateDir = path.join(tmp, '.openlife');
|
|
65
|
+
fs.mkdirSync(stateDir, { recursive: true });
|
|
66
|
+
fs.mkdirSync(path.join(stateDir, 'capabilities'), { recursive: true });
|
|
67
|
+
try {
|
|
68
|
+
// ── Scenario 1: Genesis generates a quick pack ─────────────────────
|
|
69
|
+
const stateStore = new CapabilityPackState_1.CapabilityPackStateStore({ stateDir });
|
|
70
|
+
const engine = new CapabilityGenesisEngine_1.CapabilityGenesisEngine({
|
|
71
|
+
catalogRoot,
|
|
72
|
+
stateStore,
|
|
73
|
+
});
|
|
74
|
+
const r1 = engine.generate({
|
|
75
|
+
description: 'research mid-cap medical devices',
|
|
76
|
+
packId: 'medical-devices-research',
|
|
77
|
+
mode: 'professional',
|
|
78
|
+
hints: {
|
|
79
|
+
skills: ['source-credibility-scoring', 'evidence-synthesis'],
|
|
80
|
+
squads: ['medical-research-squad'],
|
|
81
|
+
},
|
|
82
|
+
actor: 'test-runner',
|
|
83
|
+
});
|
|
84
|
+
assertTrue(r1.ok, 'scenario 1: genesis ok');
|
|
85
|
+
if (!r1.ok)
|
|
86
|
+
throw new Error('cannot continue');
|
|
87
|
+
assertTrue(fs.existsSync(r1.manifestPath), 'scenario 1: manifest written');
|
|
88
|
+
assertTrue(fs.existsSync(path.join(r1.packDir, 'INDEX.md')), 'scenario 1: INDEX.md written');
|
|
89
|
+
assertTrue(r1.pack.status === 'draft', 'scenario 1: pack status=draft');
|
|
90
|
+
assertTrue(r1.createdAssets.length === 3, `scenario 1: 3 assets created (got ${r1.createdAssets.length})`);
|
|
91
|
+
console.log('[1.5] scenario 1 (genesis → draft pack) ✓');
|
|
92
|
+
// ── Scenario 2: Generated manifest parses cleanly ──────────────────
|
|
93
|
+
const parsed = (0, CapabilityPackParser_1.parseCapabilityPackFile)(r1.manifestPath);
|
|
94
|
+
assertTrue(parsed.ok, `scenario 2: manifest parses (errors=${JSON.stringify(parsed.errors)})`);
|
|
95
|
+
assertTrue(parsed.pack?.id === 'medical-devices-research', 'scenario 2: id round-trip');
|
|
96
|
+
assertTrue((parsed.pack?.skills?.length || 0) === 2, 'scenario 2: 2 skill refs');
|
|
97
|
+
assertTrue((parsed.pack?.squads?.length || 0) === 1, 'scenario 2: 1 squad ref');
|
|
98
|
+
console.log('[1.1+1.5] scenario 2 (parse round-trip) ✓');
|
|
99
|
+
// ── Scenario 3: FileCapabilityProvider finds it ────────────────────
|
|
100
|
+
const fileProvider = new FileCapabilityProvider_1.FileCapabilityProvider({
|
|
101
|
+
cwd: tmp,
|
|
102
|
+
catalogRoot,
|
|
103
|
+
templateRoot: path.join(tmp, 'never-exists'),
|
|
104
|
+
});
|
|
105
|
+
const list = fileProvider.list();
|
|
106
|
+
assertTrue(list.length === 1, `scenario 3: 1 pack listed (got ${list.length})`);
|
|
107
|
+
assertTrue(list[0].id === 'medical-devices-research', 'scenario 3: correct id');
|
|
108
|
+
assertTrue(list[0].source === 'catalog', 'scenario 3: source=catalog');
|
|
109
|
+
console.log('[1.2] scenario 3 (FileCapabilityProvider) ✓');
|
|
110
|
+
// ── Scenario 4: Composite primary/fallback ─────────────────────────
|
|
111
|
+
const emptyProvider = { list: () => [] };
|
|
112
|
+
const fallbackProvider = {
|
|
113
|
+
list: () => [{
|
|
114
|
+
id: 'from-fallback',
|
|
115
|
+
name: 'Fallback',
|
|
116
|
+
description: 'x',
|
|
117
|
+
version: '1.0.0',
|
|
118
|
+
status: 'active',
|
|
119
|
+
filePath: '/fake',
|
|
120
|
+
packDir: '/fake',
|
|
121
|
+
source: 'cloud',
|
|
122
|
+
}],
|
|
123
|
+
};
|
|
124
|
+
const composite = new CompositeCapabilityProvider_1.CompositeCapabilityProvider(emptyProvider, fallbackProvider);
|
|
125
|
+
const fallbackList = composite.list();
|
|
126
|
+
assertTrue(fallbackList.length === 1, 'scenario 4: fallback engaged when primary empty');
|
|
127
|
+
assertTrue(fallbackList[0].id === 'from-fallback', 'scenario 4: fallback id');
|
|
128
|
+
const composite2 = new CompositeCapabilityProvider_1.CompositeCapabilityProvider(fileProvider, fallbackProvider);
|
|
129
|
+
const primaryList = composite2.list();
|
|
130
|
+
assertTrue(primaryList.length === 1, 'scenario 4: primary takes precedence');
|
|
131
|
+
assertTrue(primaryList[0].id === 'medical-devices-research', 'scenario 4: primary id wins');
|
|
132
|
+
console.log('[1.2] scenario 4 (CompositeCapabilityProvider) ✓');
|
|
133
|
+
// ── Scenario 5: Lifecycle store tracks pack ────────────────────────
|
|
134
|
+
const status1 = stateStore.read('medical-devices-research');
|
|
135
|
+
assertTrue(status1?.status === 'draft', 'scenario 5: lifecycle=draft');
|
|
136
|
+
assertTrue(status1?.history.length === 0, 'scenario 5: no history yet');
|
|
137
|
+
console.log('[1.4] scenario 5 (lifecycle init) ✓');
|
|
138
|
+
// ── Scenario 6: Promote draft → tested with validatedBy ────────────
|
|
139
|
+
const promote1 = stateStore.promote({
|
|
140
|
+
packId: 'medical-devices-research',
|
|
141
|
+
to: 'tested',
|
|
142
|
+
actor: 'qa',
|
|
143
|
+
validatedBy: 'manual-checklist',
|
|
144
|
+
});
|
|
145
|
+
assertTrue(promote1.ok, `scenario 6: promote to tested ok (error=${promote1.error})`);
|
|
146
|
+
assertTrue(promote1.status?.status === 'tested', 'scenario 6: status=tested');
|
|
147
|
+
assertTrue(promote1.status?.history.length === 1, 'scenario 6: 1 transition recorded');
|
|
148
|
+
console.log('[1.4] scenario 6 (promote draft→tested) ✓');
|
|
149
|
+
// ── Scenario 7: Refuse silent promotion to tested (no validatedBy) ─
|
|
150
|
+
// Start a fresh pack to test the refusal
|
|
151
|
+
const engine2 = new CapabilityGenesisEngine_1.CapabilityGenesisEngine({ catalogRoot, stateStore });
|
|
152
|
+
const r2 = engine2.generate({
|
|
153
|
+
description: 'simple test pack',
|
|
154
|
+
packId: 'simple-test',
|
|
155
|
+
mode: 'quick',
|
|
156
|
+
hints: { skills: ['simple-skill'] },
|
|
157
|
+
actor: 'test',
|
|
158
|
+
});
|
|
159
|
+
assertTrue(r2.ok, 'scenario 7: second pack generated');
|
|
160
|
+
const bad = stateStore.promote({
|
|
161
|
+
packId: 'simple-test',
|
|
162
|
+
to: 'tested',
|
|
163
|
+
actor: 'qa',
|
|
164
|
+
// intentionally no validatedBy
|
|
165
|
+
});
|
|
166
|
+
assertTrue(!bad.ok, 'scenario 7: silent promotion refused');
|
|
167
|
+
assertTrue(bad.error === 'tested_promotion_requires_validated_by', `scenario 7: expected error code, got ${bad.error}`);
|
|
168
|
+
console.log('[1.4] scenario 7 (refuse silent tested promotion) ✓');
|
|
169
|
+
// ── Scenario 8: Refuse auto-system promotion to active ─────────────
|
|
170
|
+
stateStore.promote({
|
|
171
|
+
packId: 'simple-test',
|
|
172
|
+
to: 'tested',
|
|
173
|
+
actor: 'qa',
|
|
174
|
+
validatedBy: 'auto-test',
|
|
175
|
+
});
|
|
176
|
+
const sysBad = stateStore.promote({
|
|
177
|
+
packId: 'simple-test',
|
|
178
|
+
to: 'active',
|
|
179
|
+
actor: 'system',
|
|
180
|
+
});
|
|
181
|
+
assertTrue(!sysBad.ok, 'scenario 8: system actor refused for active');
|
|
182
|
+
assertTrue(sysBad.error === 'active_promotion_requires_human_actor', `scenario 8: expected error code, got ${sysBad.error}`);
|
|
183
|
+
console.log('[1.4] scenario 8 (refuse auto active promotion) ✓');
|
|
184
|
+
// ── Scenario 9: Refuse invalid transition (draft → active) ─────────
|
|
185
|
+
const engine3 = new CapabilityGenesisEngine_1.CapabilityGenesisEngine({ catalogRoot, stateStore });
|
|
186
|
+
engine3.generate({
|
|
187
|
+
description: 'leap pack',
|
|
188
|
+
packId: 'leap-pack',
|
|
189
|
+
mode: 'quick',
|
|
190
|
+
actor: 'test',
|
|
191
|
+
});
|
|
192
|
+
const invalidLeap = stateStore.promote({
|
|
193
|
+
packId: 'leap-pack',
|
|
194
|
+
to: 'active',
|
|
195
|
+
actor: 'rafa',
|
|
196
|
+
});
|
|
197
|
+
assertTrue(!invalidLeap.ok, 'scenario 9: draft→active rejected');
|
|
198
|
+
assertTrue(invalidLeap.error?.startsWith('transition_not_allowed'), `scenario 9: expected transition_not_allowed, got ${invalidLeap.error}`);
|
|
199
|
+
console.log('[1.4] scenario 9 (invalid transition rejected) ✓');
|
|
200
|
+
// ── Scenario 10: CompositeWorkflowProvider primary/fallback ────────
|
|
201
|
+
const primaryWfEntry = {
|
|
202
|
+
id: 'wf-primary',
|
|
203
|
+
name: 'Primary',
|
|
204
|
+
type: 'custom',
|
|
205
|
+
version: '1.0',
|
|
206
|
+
filePath: '/fake',
|
|
207
|
+
source: 'catalog',
|
|
208
|
+
};
|
|
209
|
+
const fakePrimary = {
|
|
210
|
+
list: () => [primaryWfEntry],
|
|
211
|
+
load: (id) => id === 'wf-primary' ? { entry: primaryWfEntry, workflow: {} } : null,
|
|
212
|
+
};
|
|
213
|
+
const fakeFallback = {
|
|
214
|
+
list: () => [{ ...primaryWfEntry, id: 'wf-fallback' }],
|
|
215
|
+
load: () => null,
|
|
216
|
+
};
|
|
217
|
+
const wfComposite = new CompositeWorkflowProvider_1.CompositeWorkflowProvider(fakePrimary, fakeFallback);
|
|
218
|
+
const wfList = wfComposite.list();
|
|
219
|
+
assertTrue(wfList.length === 1 && wfList[0].id === 'wf-primary', 'scenario 10: primary workflow wins');
|
|
220
|
+
console.log('[1.3] scenario 10 (CompositeWorkflowProvider) ✓');
|
|
221
|
+
console.log('TEST_CAPABILITY_GENESIS_ENGINE_OK');
|
|
222
|
+
}
|
|
223
|
+
finally {
|
|
224
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
225
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* test_capability_pack_schema.ts — Story 1.1
|
|
4
|
+
*
|
|
5
|
+
* Regression test for CapabilityPackSchema + Parser.
|
|
6
|
+
*
|
|
7
|
+
* Asserts:
|
|
8
|
+
* 1. A minimal valid pack parses.
|
|
9
|
+
* 2. A complete pack with all sections parses and round-trips fields.
|
|
10
|
+
* 3. Missing required fields surface stable error codes.
|
|
11
|
+
* 4. Invalid status surfaces INVALID_STATUS.
|
|
12
|
+
* 5. Bad YAML surfaces INVALID_YAML.
|
|
13
|
+
* 6. Missing root key surfaces MISSING_ROOT.
|
|
14
|
+
* 7. Duplicate asset ids inside the same kind surface DUPLICATE_ASSET_REF.
|
|
15
|
+
* 8. Asset refs with invalid source surface INVALID_TYPE.
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
const fs = __importStar(require("fs"));
|
|
52
|
+
const path = __importStar(require("path"));
|
|
53
|
+
const os = __importStar(require("os"));
|
|
54
|
+
const CapabilityPackParser_1 = require("./orchestrator/capability/CapabilityPackParser");
|
|
55
|
+
const CapabilityPackSchema_1 = require("./orchestrator/capability/CapabilityPackSchema");
|
|
56
|
+
function assertTrue(cond, label) {
|
|
57
|
+
if (!cond)
|
|
58
|
+
throw new Error(`ASSERT_FAILED[${label}]`);
|
|
59
|
+
}
|
|
60
|
+
function assertErrorCode(errors, code, label) {
|
|
61
|
+
if (!errors.some((e) => e.code === code)) {
|
|
62
|
+
throw new Error(`ASSERT_FAILED[${label}]: expected error code ${code}, got ${JSON.stringify(errors.map((e) => e.code))}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// ─── Scenario 1: minimal valid pack ──────────────────────────────────
|
|
66
|
+
const minimal = `
|
|
67
|
+
capability:
|
|
68
|
+
id: minimal-pack
|
|
69
|
+
name: Minimal Pack
|
|
70
|
+
description: smallest possible pack
|
|
71
|
+
version: "1.0.0"
|
|
72
|
+
status: draft
|
|
73
|
+
objective: prove the parser accepts a minimal manifest
|
|
74
|
+
`;
|
|
75
|
+
const r1 = (0, CapabilityPackParser_1.parseCapabilityPack)(minimal);
|
|
76
|
+
assertTrue(r1.ok, 'scenario 1: minimal pack ok');
|
|
77
|
+
assertTrue(r1.pack?.id === 'minimal-pack', 'scenario 1: id round-trip');
|
|
78
|
+
assertTrue(r1.pack?.status === 'draft', 'scenario 1: status round-trip');
|
|
79
|
+
console.log('[1.1] scenario 1 (minimal) ✓');
|
|
80
|
+
// ─── Scenario 2: complete pack ───────────────────────────────────────
|
|
81
|
+
const complete = `
|
|
82
|
+
capability:
|
|
83
|
+
id: deep-research
|
|
84
|
+
name: Deep Research
|
|
85
|
+
description: thorough research capability
|
|
86
|
+
version: "1.0.0"
|
|
87
|
+
status: draft
|
|
88
|
+
objective: produce verifiable research reports with cited sources
|
|
89
|
+
success_criteria:
|
|
90
|
+
- "Every claim has a verifiable citation"
|
|
91
|
+
- "At least 3 contradicting sources considered"
|
|
92
|
+
agents:
|
|
93
|
+
- { id: research-lead, source: embedded, label: "Research Lead" }
|
|
94
|
+
- { id: writer, source: referenced, version: "1.0.0" }
|
|
95
|
+
skills:
|
|
96
|
+
- { id: source-credibility-scoring, source: embedded }
|
|
97
|
+
squads:
|
|
98
|
+
- { id: research-squad, source: embedded }
|
|
99
|
+
workflows:
|
|
100
|
+
- { id: deep-research-flow, source: embedded }
|
|
101
|
+
checklists:
|
|
102
|
+
- { id: quality-gate, path: checklists/quality-gate.md }
|
|
103
|
+
templates:
|
|
104
|
+
- { id: report, path: templates/report.md }
|
|
105
|
+
policies:
|
|
106
|
+
- { id: no-uncited-claims, rationale: "All claims must cite a source" }
|
|
107
|
+
metadata:
|
|
108
|
+
author: Genesis Engine
|
|
109
|
+
tags: [research, analysis]
|
|
110
|
+
`;
|
|
111
|
+
const r2 = (0, CapabilityPackParser_1.parseCapabilityPack)(complete);
|
|
112
|
+
assertTrue(r2.ok, 'scenario 2: complete pack ok');
|
|
113
|
+
assertTrue((r2.pack?.agents?.length || 0) === 2, 'scenario 2: 2 agents');
|
|
114
|
+
assertTrue(r2.pack?.agents?.[0].source === 'embedded', 'scenario 2: first agent embedded');
|
|
115
|
+
assertTrue(r2.pack?.agents?.[1].source === 'referenced', 'scenario 2: second agent referenced');
|
|
116
|
+
assertTrue((r2.pack?.success_criteria?.length || 0) === 2, 'scenario 2: 2 success criteria');
|
|
117
|
+
assertTrue(r2.pack?.policies?.[0].id === 'no-uncited-claims', 'scenario 2: policy round-trip');
|
|
118
|
+
console.log('[1.1] scenario 2 (complete) ✓');
|
|
119
|
+
// ─── Scenario 3: missing required fields ────────────────────────────
|
|
120
|
+
const missingFields = `
|
|
121
|
+
capability:
|
|
122
|
+
name: No ID
|
|
123
|
+
`;
|
|
124
|
+
const r3 = (0, CapabilityPackParser_1.parseCapabilityPack)(missingFields);
|
|
125
|
+
assertTrue(!r3.ok, 'scenario 3: missing fields fails');
|
|
126
|
+
assertErrorCode(r3.errors, CapabilityPackSchema_1.CAPABILITY_ERRORS.MISSING_REQUIRED_FIELD, 'scenario 3: error code');
|
|
127
|
+
console.log('[1.1] scenario 3 (missing fields) ✓');
|
|
128
|
+
// ─── Scenario 4: invalid status ─────────────────────────────────────
|
|
129
|
+
const invalidStatus = `
|
|
130
|
+
capability:
|
|
131
|
+
id: bad-status
|
|
132
|
+
name: Bad Status
|
|
133
|
+
description: x
|
|
134
|
+
version: "1.0.0"
|
|
135
|
+
status: unstable
|
|
136
|
+
objective: x
|
|
137
|
+
`;
|
|
138
|
+
const r4 = (0, CapabilityPackParser_1.parseCapabilityPack)(invalidStatus);
|
|
139
|
+
assertTrue(!r4.ok, 'scenario 4: invalid status fails');
|
|
140
|
+
assertErrorCode(r4.errors, CapabilityPackSchema_1.CAPABILITY_ERRORS.INVALID_STATUS, 'scenario 4: error code');
|
|
141
|
+
console.log('[1.1] scenario 4 (invalid status) ✓');
|
|
142
|
+
// ─── Scenario 5: bad YAML ────────────────────────────────────────────
|
|
143
|
+
const r5 = (0, CapabilityPackParser_1.parseCapabilityPack)(':\n bad: [unclosed');
|
|
144
|
+
assertTrue(!r5.ok, 'scenario 5: bad yaml fails');
|
|
145
|
+
assertErrorCode(r5.errors, CapabilityPackSchema_1.CAPABILITY_ERRORS.INVALID_YAML, 'scenario 5: error code');
|
|
146
|
+
console.log('[1.1] scenario 5 (bad yaml) ✓');
|
|
147
|
+
// ─── Scenario 6: missing root key ────────────────────────────────────
|
|
148
|
+
const r6 = (0, CapabilityPackParser_1.parseCapabilityPack)('not_capability:\n id: x');
|
|
149
|
+
assertTrue(!r6.ok, 'scenario 6: missing root fails');
|
|
150
|
+
assertErrorCode(r6.errors, CapabilityPackSchema_1.CAPABILITY_ERRORS.MISSING_ROOT, 'scenario 6: error code');
|
|
151
|
+
console.log('[1.1] scenario 6 (missing root) ✓');
|
|
152
|
+
// ─── Scenario 7: duplicate asset ids ─────────────────────────────────
|
|
153
|
+
const dupes = `
|
|
154
|
+
capability:
|
|
155
|
+
id: dup-pack
|
|
156
|
+
name: Dup
|
|
157
|
+
description: x
|
|
158
|
+
version: "1.0.0"
|
|
159
|
+
status: draft
|
|
160
|
+
objective: x
|
|
161
|
+
skills:
|
|
162
|
+
- { id: same-skill, source: embedded }
|
|
163
|
+
- { id: same-skill, source: referenced }
|
|
164
|
+
`;
|
|
165
|
+
const r7 = (0, CapabilityPackParser_1.parseCapabilityPack)(dupes);
|
|
166
|
+
assertTrue(!r7.ok, 'scenario 7: duplicate refs fail');
|
|
167
|
+
assertErrorCode(r7.errors, CapabilityPackSchema_1.CAPABILITY_ERRORS.DUPLICATE_ASSET_REF, 'scenario 7: error code');
|
|
168
|
+
console.log('[1.1] scenario 7 (duplicate refs) ✓');
|
|
169
|
+
// ─── Scenario 8: invalid asset source ────────────────────────────────
|
|
170
|
+
const badSource = `
|
|
171
|
+
capability:
|
|
172
|
+
id: bad-source
|
|
173
|
+
name: Bad Source
|
|
174
|
+
description: x
|
|
175
|
+
version: "1.0.0"
|
|
176
|
+
status: draft
|
|
177
|
+
objective: x
|
|
178
|
+
agents:
|
|
179
|
+
- { id: a1, source: cloud }
|
|
180
|
+
`;
|
|
181
|
+
const r8 = (0, CapabilityPackParser_1.parseCapabilityPack)(badSource);
|
|
182
|
+
assertTrue(!r8.ok, 'scenario 8: bad source fails');
|
|
183
|
+
assertErrorCode(r8.errors, CapabilityPackSchema_1.CAPABILITY_ERRORS.INVALID_TYPE, 'scenario 8: error code');
|
|
184
|
+
console.log('[1.1] scenario 8 (invalid source) ✓');
|
|
185
|
+
// ─── Scenario 9: file-mode parse + embedded ref file check ───────────
|
|
186
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'capability-test-'));
|
|
187
|
+
try {
|
|
188
|
+
const packDir = path.join(tmp, 'demo-pack');
|
|
189
|
+
fs.mkdirSync(packDir, { recursive: true });
|
|
190
|
+
fs.mkdirSync(path.join(packDir, 'skills'), { recursive: true });
|
|
191
|
+
fs.writeFileSync(path.join(packDir, 'skills', 'real-skill.md'), '# Real Skill\n');
|
|
192
|
+
const yamlPath = path.join(packDir, 'capability.yaml');
|
|
193
|
+
fs.writeFileSync(yamlPath, `
|
|
194
|
+
capability:
|
|
195
|
+
id: demo-pack
|
|
196
|
+
name: Demo
|
|
197
|
+
description: file-mode test
|
|
198
|
+
version: "1.0.0"
|
|
199
|
+
status: draft
|
|
200
|
+
objective: prove file-mode parsing finds embedded files
|
|
201
|
+
skills:
|
|
202
|
+
- { id: real-skill, source: embedded }
|
|
203
|
+
- { id: ghost-skill, source: embedded }
|
|
204
|
+
`);
|
|
205
|
+
const r9 = (0, CapabilityPackParser_1.parseCapabilityPackFile)(yamlPath);
|
|
206
|
+
// ghost-skill has no file → should error; real-skill is fine
|
|
207
|
+
assertTrue(!r9.ok, 'scenario 9: ghost-skill missing file fails');
|
|
208
|
+
assertErrorCode(r9.errors, CapabilityPackSchema_1.CAPABILITY_ERRORS.EMBEDDED_REF_MISSING_FILE, 'scenario 9: error code');
|
|
209
|
+
console.log('[1.1] scenario 9 (file-mode + embedded check) ✓');
|
|
210
|
+
}
|
|
211
|
+
finally {
|
|
212
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
213
|
+
}
|
|
214
|
+
console.log('TEST_CAPABILITY_PACK_SCHEMA_OK');
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* test_catalog_quality.ts — Story 5.6
|
|
4
|
+
*
|
|
5
|
+
* Regression gate against bad squad/skill check-ins.
|
|
6
|
+
*
|
|
7
|
+
* Scans `.catalog/squads/` and `.catalog/skills/` (excluding `test-*`) and asserts:
|
|
8
|
+
* - Every entry has the expected primary doc (SQUAD.md or SKILL.md).
|
|
9
|
+
* - Frontmatter parses and contains required fields (id, name, status).
|
|
10
|
+
* - Frontmatter `id` matches the directory name.
|
|
11
|
+
* - No squad is left in status=`draft` with `source: aiobuilder-auto-route` for
|
|
12
|
+
* more than CATALOG_DRAFT_TTL_DAYS days (default 7).
|
|
13
|
+
*
|
|
14
|
+
* Test-pollution entries (prefix `test-`) are ignored — `clean-test-pollution.js`
|
|
15
|
+
* sweeps them in `pretest:all`. This test guards permanent check-ins.
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
const fs = __importStar(require("fs"));
|
|
52
|
+
const path = __importStar(require("path"));
|
|
53
|
+
const CATALOG_ROOT = path.join(process.cwd(), '.catalog');
|
|
54
|
+
const SQUADS_DIR = path.join(CATALOG_ROOT, 'squads');
|
|
55
|
+
const SKILLS_DIR = path.join(CATALOG_ROOT, 'skills');
|
|
56
|
+
const DRAFT_TTL_DAYS = Number(process.env.OPENLIFE_DRAFT_TTL_DAYS || '7');
|
|
57
|
+
function parseFrontmatter(content) {
|
|
58
|
+
const m = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
59
|
+
if (!m)
|
|
60
|
+
return {};
|
|
61
|
+
const out = {};
|
|
62
|
+
for (const line of m[1].split('\n')) {
|
|
63
|
+
const kv = line.match(/^([\w-]+):\s*(.*)$/);
|
|
64
|
+
if (kv)
|
|
65
|
+
out[kv[1]] = kv[2].trim();
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
function getDirMtimeMs(dir) {
|
|
70
|
+
try {
|
|
71
|
+
return fs.statSync(dir).mtimeMs;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return Date.now();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function scan(dir, docName, label) {
|
|
78
|
+
const issues = [];
|
|
79
|
+
if (!fs.existsSync(dir))
|
|
80
|
+
return issues;
|
|
81
|
+
for (const entry of fs.readdirSync(dir)) {
|
|
82
|
+
if (entry.startsWith('test-'))
|
|
83
|
+
continue;
|
|
84
|
+
if (entry.startsWith('.'))
|
|
85
|
+
continue;
|
|
86
|
+
const entryDir = path.join(dir, entry);
|
|
87
|
+
const stat = fs.statSync(entryDir);
|
|
88
|
+
if (!stat.isDirectory())
|
|
89
|
+
continue;
|
|
90
|
+
const docPath = path.join(entryDir, docName);
|
|
91
|
+
if (!fs.existsSync(docPath)) {
|
|
92
|
+
// Imported-reference-only directories are tolerated: they hold raw upstream
|
|
93
|
+
// material (e.g. fetched HTML, source-of-truth excerpts) and aren't meant
|
|
94
|
+
// to be loaded as runtime skills. They must declare themselves with
|
|
95
|
+
// IMPORTED_REFERENCE.md and no primary doc.
|
|
96
|
+
const importedRef = path.join(entryDir, 'IMPORTED_REFERENCE.md');
|
|
97
|
+
if (fs.existsSync(importedRef))
|
|
98
|
+
continue;
|
|
99
|
+
issues.push({ kind: 'missing_primary_doc', entry, detail: `${label} ${entry}/ has no ${docName}` });
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const fm = parseFrontmatter(fs.readFileSync(docPath, 'utf-8'));
|
|
103
|
+
if (!fm.id)
|
|
104
|
+
issues.push({ kind: 'missing_id', entry, detail: `${label} ${entry}/${docName} frontmatter missing 'id'` });
|
|
105
|
+
if (!fm.name)
|
|
106
|
+
issues.push({ kind: 'missing_name', entry, detail: `${label} ${entry}/${docName} frontmatter missing 'name'` });
|
|
107
|
+
if (fm.id && fm.id !== entry) {
|
|
108
|
+
issues.push({ kind: 'id_dir_mismatch', entry, detail: `${label} frontmatter id='${fm.id}' but directory is '${entry}'` });
|
|
109
|
+
}
|
|
110
|
+
// Stale draft gate — only enforced for auto-route auto-creations.
|
|
111
|
+
if (fm.status === 'draft' && /aiobuilder-auto-route/.test(fm.source || '')) {
|
|
112
|
+
const ageDays = (Date.now() - getDirMtimeMs(entryDir)) / (1000 * 60 * 60 * 24);
|
|
113
|
+
if (ageDays > DRAFT_TTL_DAYS) {
|
|
114
|
+
issues.push({
|
|
115
|
+
kind: 'stale_auto_route_draft',
|
|
116
|
+
entry,
|
|
117
|
+
detail: `${label} ${entry}/ is auto-route draft for ${ageDays.toFixed(1)}d (TTL ${DRAFT_TTL_DAYS}d). Promote with \`openlife aiobuilder canonize\` or delete.`,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return issues;
|
|
123
|
+
}
|
|
124
|
+
function main() {
|
|
125
|
+
const squadIssues = scan(SQUADS_DIR, 'SQUAD.md', 'squad');
|
|
126
|
+
const skillIssues = scan(SKILLS_DIR, 'SKILL.md', 'skill');
|
|
127
|
+
const all = [...squadIssues, ...skillIssues];
|
|
128
|
+
const squadsScanned = fs.existsSync(SQUADS_DIR)
|
|
129
|
+
? fs.readdirSync(SQUADS_DIR).filter((e) => !e.startsWith('test-') && !e.startsWith('.')).length
|
|
130
|
+
: 0;
|
|
131
|
+
const skillsScanned = fs.existsSync(SKILLS_DIR)
|
|
132
|
+
? fs.readdirSync(SKILLS_DIR).filter((e) => !e.startsWith('test-') && !e.startsWith('.')).length
|
|
133
|
+
: 0;
|
|
134
|
+
console.log(`[catalog-quality] Scanned ${squadsScanned} squads, ${skillsScanned} skills.`);
|
|
135
|
+
if (all.length > 0) {
|
|
136
|
+
console.error(`[catalog-quality] ${all.length} issue(s) found:`);
|
|
137
|
+
for (const i of all)
|
|
138
|
+
console.error(` - [${i.kind}] ${i.detail}`);
|
|
139
|
+
throw new Error(`CATALOG_QUALITY_FAILED: ${all.length} issue(s) in .catalog/`);
|
|
140
|
+
}
|
|
141
|
+
console.log('[catalog-quality] PASS — no broken squad/skill check-ins.');
|
|
142
|
+
console.log('TEST_CATALOG_QUALITY_OK');
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
main();
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
console.error('[catalog-quality] FAILED:', err instanceof Error ? err.message : err);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|