@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.
Files changed (394) hide show
  1. package/INSTALL.md +266 -0
  2. package/LICENSE +21 -0
  3. package/README.md +142 -0
  4. package/bin/openlife.js +3 -0
  5. package/dist/admin_panel_server.js +66 -0
  6. package/dist/cli/AgentManager.js +109 -0
  7. package/dist/cli/AutonomousInstaller.js +134 -0
  8. package/dist/cli/DreamOrganizer.js +88 -0
  9. package/dist/cli/HostInstaller.js +426 -0
  10. package/dist/cli/InstallBanner.js +16 -0
  11. package/dist/cli/InstallFlow.js +256 -0
  12. package/dist/cli/InstallHeadless.js +47 -0
  13. package/dist/cli/InstallModules.js +148 -0
  14. package/dist/cli/InstallStateStore.js +75 -0
  15. package/dist/cli/InstallWizard.js +364 -0
  16. package/dist/cli/ProfileManager.js +163 -0
  17. package/dist/cli/SystemInstaller.js +89 -0
  18. package/dist/cli/WorldClassCommands.js +208 -0
  19. package/dist/design/DesignMdImporter.js +82 -0
  20. package/dist/design/DesignMdMode.js +93 -0
  21. package/dist/design/DesignMdRegistry.js +67 -0
  22. package/dist/index.js +2575 -0
  23. package/dist/memory/ConversationMemory.js +33 -0
  24. package/dist/memory/LocalMemoryProvider.js +86 -0
  25. package/dist/memory/Mem0Provider.js +16 -0
  26. package/dist/memory/MemoryNamespacePolicy.js +27 -0
  27. package/dist/memory/MemoryOrchestrator.js +65 -0
  28. package/dist/memory/MemoryPromotionFlow.js +32 -0
  29. package/dist/memory/MemoryProvider.js +2 -0
  30. package/dist/memory/MemoryProviderRegistry.js +27 -0
  31. package/dist/memory/MemoryRetentionPolicy.js +60 -0
  32. package/dist/memory/MempalaceProvider.js +72 -0
  33. package/dist/memory/OmniMemory.js +106 -0
  34. package/dist/memory/RedisAgentMemoryProvider.js +16 -0
  35. package/dist/memory/SessionManager.js +86 -0
  36. package/dist/memory/ZepGraphitiProvider.js +16 -0
  37. package/dist/orchestrator/AgentRegistry.js +56 -0
  38. package/dist/orchestrator/AgentScoring.js +82 -0
  39. package/dist/orchestrator/AgentTeam.js +22 -0
  40. package/dist/orchestrator/ArbitrationAgent.js +43 -0
  41. package/dist/orchestrator/ArbitrationScorecard.js +17 -0
  42. package/dist/orchestrator/AssetPromotionEngine.js +65 -0
  43. package/dist/orchestrator/AssetReuseRouter.js +63 -0
  44. package/dist/orchestrator/BenchmarkEngine.js +75 -0
  45. package/dist/orchestrator/Brain.js +298 -0
  46. package/dist/orchestrator/CadenceEngine.js +76 -0
  47. package/dist/orchestrator/CapabilityRouter.js +36 -0
  48. package/dist/orchestrator/CommandLanguage.js +27 -0
  49. package/dist/orchestrator/CommandRouter.js +70 -0
  50. package/dist/orchestrator/ConsequenceForecaster.js +286 -0
  51. package/dist/orchestrator/CronManager.js +286 -0
  52. package/dist/orchestrator/DynamicAgentBuilder.js +48 -0
  53. package/dist/orchestrator/DynamicAgentExecutor.js +15 -0
  54. package/dist/orchestrator/EnterpriseAgenticCore.js +276 -0
  55. package/dist/orchestrator/ExecutionBoard.js +86 -0
  56. package/dist/orchestrator/ExecutionIntent.js +13 -0
  57. package/dist/orchestrator/ExecutionModePolicy.js +48 -0
  58. package/dist/orchestrator/ExecutionRouter.js +9 -0
  59. package/dist/orchestrator/ExecutionState.js +20 -0
  60. package/dist/orchestrator/ExecutorHealth.js +86 -0
  61. package/dist/orchestrator/ExternalCatalogRegistry.js +83 -0
  62. package/dist/orchestrator/Gatekeeper.js +414 -0
  63. package/dist/orchestrator/Gateway.js +508 -0
  64. package/dist/orchestrator/GovernanceConsentStore.js +66 -0
  65. package/dist/orchestrator/GovernanceLayer.js +179 -0
  66. package/dist/orchestrator/GovernancePolicyStore.js +53 -0
  67. package/dist/orchestrator/GovernanceScopeLedger.js +134 -0
  68. package/dist/orchestrator/GovernanceScopePolicy.js +67 -0
  69. package/dist/orchestrator/IntentClassifier.js +45 -0
  70. package/dist/orchestrator/JobLifecycle.js +91 -0
  71. package/dist/orchestrator/LearningRouter.js +24 -0
  72. package/dist/orchestrator/MediaManager.js +92 -0
  73. package/dist/orchestrator/MemoryCuratorAgent.js +41 -0
  74. package/dist/orchestrator/MissionState.js +155 -0
  75. package/dist/orchestrator/ModelManager.js +84 -0
  76. package/dist/orchestrator/OperatingSystem.js +71 -0
  77. package/dist/orchestrator/OperationalMemoryStore.js +94 -0
  78. package/dist/orchestrator/OptimizationLoop.js +72 -0
  79. package/dist/orchestrator/OrchestrationLoop.js +905 -0
  80. package/dist/orchestrator/OrgStructure.js +88 -0
  81. package/dist/orchestrator/OutcomeSimulator.js +46 -0
  82. package/dist/orchestrator/ParallelOrchestrationLoop.js +36 -0
  83. package/dist/orchestrator/PerformanceScorecard.js +105 -0
  84. package/dist/orchestrator/PlannerAgent.js +46 -0
  85. package/dist/orchestrator/ProcessSandbox.js +129 -0
  86. package/dist/orchestrator/PromotionPipeline.js +74 -0
  87. package/dist/orchestrator/PromotionReviewGate.js +11 -0
  88. package/dist/orchestrator/QueueScheduler.js +260 -0
  89. package/dist/orchestrator/ReleaseGate.js +36 -0
  90. package/dist/orchestrator/ReleaseWorkflow.js +68 -0
  91. package/dist/orchestrator/RemotePublisher.js +139 -0
  92. package/dist/orchestrator/ReuseEngine.js +89 -0
  93. package/dist/orchestrator/ReviewerAgent.js +49 -0
  94. package/dist/orchestrator/RoleHandoff.js +65 -0
  95. package/dist/orchestrator/RuntimeHealthMonitor.js +143 -0
  96. package/dist/orchestrator/RuntimePolicy.js +105 -0
  97. package/dist/orchestrator/RuntimeProbe.js +97 -0
  98. package/dist/orchestrator/RuntimeRegistry.js +73 -0
  99. package/dist/orchestrator/SandboxPolicy.js +22 -0
  100. package/dist/orchestrator/SecurityDownloadGuard.js +169 -0
  101. package/dist/orchestrator/SecurityEventStore.js +58 -0
  102. package/dist/orchestrator/ServiceCompletionPolicy.js +36 -0
  103. package/dist/orchestrator/ServiceState.js +195 -0
  104. package/dist/orchestrator/SkillCreator.js +404 -0
  105. package/dist/orchestrator/SkillLearningLoop.js +57 -0
  106. package/dist/orchestrator/SkillManager.js +75 -0
  107. package/dist/orchestrator/SkillNetwork.js +29 -0
  108. package/dist/orchestrator/SkillRegistryV2.js +28 -0
  109. package/dist/orchestrator/SkillScoring.js +70 -0
  110. package/dist/orchestrator/SquadAutoCreator.js +64 -0
  111. package/dist/orchestrator/SquadCreator.js +727 -0
  112. package/dist/orchestrator/SquadRegistry.js +28 -0
  113. package/dist/orchestrator/SquadRouter.js +33 -0
  114. package/dist/orchestrator/SquadScoring.js +70 -0
  115. package/dist/orchestrator/SubagentLifecycle.js +90 -0
  116. package/dist/orchestrator/SynthesizerAgent.js +48 -0
  117. package/dist/orchestrator/SystemDoctor.js +224 -0
  118. package/dist/orchestrator/TaskExecutor.js +422 -0
  119. package/dist/orchestrator/TeammateBoard.js +61 -0
  120. package/dist/orchestrator/TestHarness.js +184 -0
  121. package/dist/orchestrator/VoiceManager.js +203 -0
  122. package/dist/orchestrator/VoiceRouter.js +89 -0
  123. package/dist/orchestrator/capability/CapabilityGenesisEngine.js +278 -0
  124. package/dist/orchestrator/capability/CapabilityPackParser.js +223 -0
  125. package/dist/orchestrator/capability/CapabilityPackSchema.js +62 -0
  126. package/dist/orchestrator/capability/CapabilityPackState.js +163 -0
  127. package/dist/orchestrator/providers/AgentProvider.js +2 -0
  128. package/dist/orchestrator/providers/CapabilityProvider.js +12 -0
  129. package/dist/orchestrator/providers/CloudAgentProvider.js +55 -0
  130. package/dist/orchestrator/providers/CloudSkillProvider.js +55 -0
  131. package/dist/orchestrator/providers/CloudSquadProvider.js +55 -0
  132. package/dist/orchestrator/providers/CompositeAgentProvider.js +16 -0
  133. package/dist/orchestrator/providers/CompositeCapabilityProvider.js +25 -0
  134. package/dist/orchestrator/providers/CompositeSkillProvider.js +16 -0
  135. package/dist/orchestrator/providers/CompositeSquadProvider.js +16 -0
  136. package/dist/orchestrator/providers/CompositeWorkflowProvider.js +46 -0
  137. package/dist/orchestrator/providers/FileAgentProvider.js +105 -0
  138. package/dist/orchestrator/providers/FileCapabilityProvider.js +106 -0
  139. package/dist/orchestrator/providers/FileSkillProvider.js +65 -0
  140. package/dist/orchestrator/providers/FileSquadProvider.js +69 -0
  141. package/dist/orchestrator/providers/FileWorkflowProvider.js +103 -0
  142. package/dist/orchestrator/providers/SkillProvider.js +2 -0
  143. package/dist/orchestrator/providers/SquadProvider.js +2 -0
  144. package/dist/orchestrator/toolset/ToolsetGuard.js +69 -0
  145. package/dist/orchestrator/toolset/ToolsetRegistry.js +65 -0
  146. package/dist/orchestrator/toolset/ToolsetSchema.js +21 -0
  147. package/dist/orchestrator/util/AtomicWriter.js +204 -0
  148. package/dist/orchestrator/util/DistributedLock.js +232 -0
  149. package/dist/orchestrator/util/TemplateRenderer.js +87 -0
  150. package/dist/orchestrator/util/WatchdogHeartbeat.js +116 -0
  151. package/dist/orchestrator/workflow/ConditionParser.js +232 -0
  152. package/dist/orchestrator/workflow/WorkflowEngine.js +379 -0
  153. package/dist/orchestrator/workflow/WorkflowParser.js +368 -0
  154. package/dist/orchestrator/workflow/WorkflowSchema.js +65 -0
  155. package/dist/orchestrator/workflow/WorkflowState.js +11 -0
  156. package/dist/reversa/ReversaAgent.js +134 -0
  157. package/dist/reversa/ReversaContracts.js +62 -0
  158. package/dist/reversa/ReversaExecutors.js +65 -0
  159. package/dist/skills/SkillRegistry.js +71 -0
  160. package/dist/squads/SquadManager.js +87 -0
  161. package/dist/test_admin_teams_networks.js +54 -0
  162. package/dist/test_agent_team_skill_network.js +15 -0
  163. package/dist/test_aiobuilder_cli_parity.js +169 -0
  164. package/dist/test_ask_exit.js +73 -0
  165. package/dist/test_atomic_writer.js +209 -0
  166. package/dist/test_autonomous_soak.js +141 -0
  167. package/dist/test_benchmark_engine.js +41 -0
  168. package/dist/test_brain_error_diagnostics.js +51 -0
  169. package/dist/test_brain_fallback_chain.js +93 -0
  170. package/dist/test_capability_genesis_engine.js +225 -0
  171. package/dist/test_capability_pack_schema.js +214 -0
  172. package/dist/test_catalog_quality.js +150 -0
  173. package/dist/test_cli_crud_roundtrip.js +154 -0
  174. package/dist/test_cli_diagnostics.js +131 -0
  175. package/dist/test_cli_doc_parity.js +126 -0
  176. package/dist/test_cli_help_surface.js +106 -0
  177. package/dist/test_cli_service_commands.js +83 -0
  178. package/dist/test_consequence_forecast_brain.js +165 -0
  179. package/dist/test_consequence_forecaster.js +24 -0
  180. package/dist/test_conversation_memory.js +36 -0
  181. package/dist/test_create_entities.js +54 -0
  182. package/dist/test_creator_placeholders_completed.js +177 -0
  183. package/dist/test_cron_manager.js +123 -0
  184. package/dist/test_daemon_sigterm.js +72 -0
  185. package/dist/test_deep_research_capability.js +87 -0
  186. package/dist/test_designmd_import_registry.js +16 -0
  187. package/dist/test_designmd_mode.js +50 -0
  188. package/dist/test_designmd_mode_workspace.js +13 -0
  189. package/dist/test_dist_templates_layout.js +135 -0
  190. package/dist/test_distributed_lock.js +201 -0
  191. package/dist/test_distribution_installability.js +67 -0
  192. package/dist/test_doctor_sandbox_check.js +44 -0
  193. package/dist/test_dream_organizer.js +25 -0
  194. package/dist/test_dual_mode.js +15 -0
  195. package/dist/test_enterprise_agentic_core.js +128 -0
  196. package/dist/test_forecast_brain_wiring.js +87 -0
  197. package/dist/test_gateway_telegram_guardrails.js +52 -0
  198. package/dist/test_governance.js +34 -0
  199. package/dist/test_governance_advanced.js +75 -0
  200. package/dist/test_governance_scope_ledger.js +147 -0
  201. package/dist/test_governance_v13_policies.js +44 -0
  202. package/dist/test_guided_creator_cli.js +100 -0
  203. package/dist/test_host_install_e2e.js +324 -0
  204. package/dist/test_host_installer.js +259 -0
  205. package/dist/test_host_installers_gemini_codex.js +95 -0
  206. package/dist/test_host_uninstaller.js +295 -0
  207. package/dist/test_install_flow.js +70 -0
  208. package/dist/test_install_flow_host_validation.js +143 -0
  209. package/dist/test_install_wizard.js +272 -0
  210. package/dist/test_integration_gemini_live.js +95 -0
  211. package/dist/test_integration_http_trigger_live.js +154 -0
  212. package/dist/test_integration_telegram_live.js +102 -0
  213. package/dist/test_job_lifecycle.js +16 -0
  214. package/dist/test_memory_orchestrator.js +33 -0
  215. package/dist/test_memory_promotion.js +36 -0
  216. package/dist/test_memory_retention.js +37 -0
  217. package/dist/test_mission_checkpoint.js +204 -0
  218. package/dist/test_multi_host_docs_parity.js +125 -0
  219. package/dist/test_openlife_auto_creator_routing.js +69 -0
  220. package/dist/test_openlife_evolution_surface.js +77 -0
  221. package/dist/test_openlife_gatekeeper_routing.js +15 -0
  222. package/dist/test_openlife_routing_surface.js +27 -0
  223. package/dist/test_openlife_runtime_source_truth.js +25 -0
  224. package/dist/test_operating_system.js +45 -0
  225. package/dist/test_optimization_loop.js +38 -0
  226. package/dist/test_orchestration_assets_lifecycle.js +78 -0
  227. package/dist/test_outcome_simulator.js +38 -0
  228. package/dist/test_performance_latency.js +215 -0
  229. package/dist/test_performance_scorecard.js +38 -0
  230. package/dist/test_phase1_check_exit.js +103 -0
  231. package/dist/test_phase6_board.js +31 -0
  232. package/dist/test_phase6_cadence.js +29 -0
  233. package/dist/test_phase6_ops.js +37 -0
  234. package/dist/test_post_mission_evaluation.js +190 -0
  235. package/dist/test_process_sandbox.js +88 -0
  236. package/dist/test_profile_toolset_mcp.js +125 -0
  237. package/dist/test_queue_scheduler.js +239 -0
  238. package/dist/test_release_gate.js +23 -0
  239. package/dist/test_remote_publish.js +193 -0
  240. package/dist/test_reversa_contracts_e2e.js +48 -0
  241. package/dist/test_reversa_export_and_strict.js +51 -0
  242. package/dist/test_reversa_full_execution.js +12 -0
  243. package/dist/test_reversa_lite.js +9 -0
  244. package/dist/test_royal_stack_golden.js +179 -0
  245. package/dist/test_runtime_health_backoff.js +154 -0
  246. package/dist/test_runtime_policy.js +26 -0
  247. package/dist/test_runtime_probe.js +19 -0
  248. package/dist/test_runtime_profile_oauth_only.js +262 -0
  249. package/dist/test_runtime_registry.js +11 -0
  250. package/dist/test_security_download_and_scan.js +103 -0
  251. package/dist/test_security_download_guard.js +14 -0
  252. package/dist/test_service_command_surface.js +12 -0
  253. package/dist/test_service_completion_policy.js +32 -0
  254. package/dist/test_service_guardrails_delete.js +12 -0
  255. package/dist/test_service_mode_explicit_only.js +174 -0
  256. package/dist/test_sources_import_ref.js +46 -0
  257. package/dist/test_sources_scaffold.js +43 -0
  258. package/dist/test_squad_skill_creator.js +305 -0
  259. package/dist/test_squad_skill_design_llm.js +176 -0
  260. package/dist/test_subsystems_org_state.js +271 -0
  261. package/dist/test_subsystems_promotion_memory_assets.js +343 -0
  262. package/dist/test_subsystems_routing_governance.js +234 -0
  263. package/dist/test_task_executor_sandbox_optin.js +127 -0
  264. package/dist/test_teammate_learning.js +15 -0
  265. package/dist/test_telegram_delete_guardrail.js +21 -0
  266. package/dist/test_toolset_enforcement.js +188 -0
  267. package/dist/test_trigger_basic_auth.js +112 -0
  268. package/dist/test_util/doc_parity.js +120 -0
  269. package/dist/test_v15_e2e_integration.js +207 -0
  270. package/dist/test_watchdog_heartbeat.js +152 -0
  271. package/dist/test_workflow_condition_parser.js +63 -0
  272. package/dist/test_workflow_e2e.js +240 -0
  273. package/dist/test_workflow_engine.js +330 -0
  274. package/dist/test_workflow_parser.js +245 -0
  275. package/dist/test_workflow_schema_backward_compat.js +197 -0
  276. package/dist-templates/README.md +91 -0
  277. package/dist-templates/claude-code/agents/openlife-atlas.md +52 -0
  278. package/dist-templates/claude-code/agents/openlife-forge.md +42 -0
  279. package/dist-templates/claude-code/agents/openlife-genesis.md +59 -0
  280. package/dist-templates/claude-code/agents/openlife-lyra.md +40 -0
  281. package/dist-templates/claude-code/agents/openlife-maestro.md +45 -0
  282. package/dist-templates/claude-code/commands/openlife/ask.md +14 -0
  283. package/dist-templates/claude-code/commands/openlife/doctor.md +19 -0
  284. package/dist-templates/claude-code/commands/openlife/dream.md +20 -0
  285. package/dist-templates/claude-code/commands/openlife/status.md +14 -0
  286. package/dist-templates/claude-code/mcp/openlife-orchestrator.json +46 -0
  287. package/dist-templates/codex/README.md +7 -0
  288. package/dist-templates/codex/agents/openlife-atlas.md +52 -0
  289. package/dist-templates/codex/agents/openlife-forge.md +42 -0
  290. package/dist-templates/codex/agents/openlife-genesis.md +59 -0
  291. package/dist-templates/codex/agents/openlife-lyra.md +40 -0
  292. package/dist-templates/codex/agents/openlife-maestro.md +45 -0
  293. package/dist-templates/codex/commands/openlife/ask.md +14 -0
  294. package/dist-templates/codex/commands/openlife/doctor.md +19 -0
  295. package/dist-templates/codex/commands/openlife/dream.md +20 -0
  296. package/dist-templates/codex/commands/openlife/status.md +14 -0
  297. package/dist-templates/codex/mcp/openlife-orchestrator.json +46 -0
  298. package/dist-templates/gemini-cli/README.md +8 -0
  299. package/dist-templates/gemini-cli/agents/openlife-atlas.md +52 -0
  300. package/dist-templates/gemini-cli/agents/openlife-forge.md +42 -0
  301. package/dist-templates/gemini-cli/agents/openlife-genesis.md +59 -0
  302. package/dist-templates/gemini-cli/agents/openlife-lyra.md +40 -0
  303. package/dist-templates/gemini-cli/agents/openlife-maestro.md +45 -0
  304. package/dist-templates/gemini-cli/commands/openlife/ask.md +14 -0
  305. package/dist-templates/gemini-cli/commands/openlife/doctor.md +19 -0
  306. package/dist-templates/gemini-cli/commands/openlife/dream.md +20 -0
  307. package/dist-templates/gemini-cli/commands/openlife/status.md +14 -0
  308. package/dist-templates/gemini-cli/mcp/openlife-orchestrator.json +46 -0
  309. package/dist-templates/skill-template/README.md +34 -0
  310. package/dist-templates/skill-template/SKILL.md.template +59 -0
  311. package/dist-templates/squad-template/README.md +82 -0
  312. package/dist-templates/squad-template/SQUAD.md.template +51 -0
  313. package/dist-templates/squad-template/agent-template.md +51 -0
  314. package/dist-templates/squad-template/checklist-template.md +25 -0
  315. package/dist-templates/squad-template/task-template.md +36 -0
  316. package/dist-templates/workflows/PORTED_WORKFLOWS.md +60 -0
  317. package/dist-templates/workflows/brownfield-discovery.yaml +137 -0
  318. package/dist-templates/workflows/greenfield-fullstack.yaml +132 -0
  319. package/dist-templates/workflows/qa-loop.yaml +125 -0
  320. package/dist-templates/workflows/story-development-cycle.yaml +80 -0
  321. package/docs/CHANGELOG_FEATURE_ROLLOUT_DESIGNMD.md +43 -0
  322. package/docs/EXTERNAL_SOURCES_AND_SECURITY_GUARD.md +33 -0
  323. package/docs/OPENLIFE_AUDIT_2026-05-06.md +170 -0
  324. package/docs/OPENLIFE_CONSOLIDATED_PLAN_2026-05-06.md +299 -0
  325. package/docs/OPENLIFE_DUAL_MODE_IMPLEMENTATION_PLAN.md +205 -0
  326. package/docs/OPENLIFE_EVOLUTION_SURFACE_2026-05-07.md +53 -0
  327. package/docs/OPENLIFE_SKILLS_IMPORT_2026-05-07.json +223 -0
  328. package/docs/OPENLIFE_SQUADS_IMPORT_2026-05-07.json +184 -0
  329. package/docs/PAPERCLIP_OPENLIFE_INVESTIGATION.md +85 -0
  330. package/docs/README.md +28 -0
  331. package/docs/RELEASE_ORGANIZATION_PLAN.md +164 -0
  332. package/docs/audit/CLI-EXECUTION-RESULTS.md +113 -0
  333. package/docs/audit/CLI-MATRIX.md +556 -0
  334. package/docs/audit/DOC-PARITY-GAPS.md +351 -0
  335. package/docs/audit/ORCHESTRATOR-MATRIX.md +136 -0
  336. package/docs/audit/TEST-COVERAGE-GAPS.md +334 -0
  337. package/docs/audit/integrations/SKIPPED.md +101 -0
  338. package/docs/autonomous-install.md +79 -0
  339. package/docs/capability-genesis.md +137 -0
  340. package/docs/capability-pack-schema.md +157 -0
  341. package/docs/commands.md +82 -0
  342. package/docs/deep-research-capability.md +114 -0
  343. package/docs/development/typescript-conventions.md +95 -0
  344. package/docs/host-installers.md +68 -0
  345. package/docs/install/aiobuilder.md +70 -0
  346. package/docs/install/claude-code.md +83 -0
  347. package/docs/install/codex.md +64 -0
  348. package/docs/install/gemini-cli.md +64 -0
  349. package/docs/install/runtime-profiles.md +83 -0
  350. package/docs/openlife-agent-os-blueprint.md +114 -0
  351. package/docs/openlife-install-backlog.md +115 -0
  352. package/docs/openlife-install-spec.md +306 -0
  353. package/docs/operations/CLOUD_CUTOVER_AUDIT.md +37 -0
  354. package/docs/operations/PHASE_PROGRESS_CONTINUATION.md +24 -0
  355. package/docs/performance-benchmarks.md +83 -0
  356. package/docs/planning/v1.3-capability-genesis.md +157 -0
  357. package/docs/plans/2026-05-05-admin-interface-professional-dark-premium-plan.md +84 -0
  358. package/docs/plans/2026-05-05-openlife-autonomous-domain-marketplace-masterplan.md +122 -0
  359. package/docs/quickstart.md +60 -0
  360. package/docs/release-process.md +236 -0
  361. package/docs/roadmap/OPENLIFE_MASTER_PLAN_CLOUD_V3.md +97 -0
  362. package/docs/sandboxing-research.md +117 -0
  363. package/docs/stories/epic-feature-audit/1.1.story.md +84 -0
  364. package/docs/stories/epic-feature-audit/1.2.story.md +102 -0
  365. package/docs/stories/epic-feature-audit/1.3.story.md +93 -0
  366. package/docs/stories/epic-feature-audit/1.5.story.md +121 -0
  367. package/docs/stories/epic-feature-audit/1.6.story.md +80 -0
  368. package/docs/stories/epic-feature-completeness/2.1.story.md +70 -0
  369. package/docs/stories/epic-feature-completeness/2.2.story.md +49 -0
  370. package/docs/stories/epic-feature-completeness/2.3.story.md +74 -0
  371. package/docs/stories/epic-feature-completeness/2.4.story.md +71 -0
  372. package/docs/stories/epic-feature-completeness/3.1.story.md +56 -0
  373. package/docs/stories/epic-feature-completeness/3.2.story.md +80 -0
  374. package/docs/stories/epic-feature-completeness/3.3.story.md +68 -0
  375. package/docs/stories/epic-feature-completeness/3.4.story.md +71 -0
  376. package/docs/stories/epic-feature-completeness/3.5.story.md +72 -0
  377. package/docs/stories/epic-feature-completeness/3.6.story.md +69 -0
  378. package/docs/stories/epic-feature-completeness/3.7.story.md +68 -0
  379. package/docs/stories/epic-feature-completeness/3.8.story.md +57 -0
  380. package/docs/toolset-enforcement.md +122 -0
  381. package/docs/v1.4-changelog.md +159 -0
  382. package/docs/v1.5-changelog.md +106 -0
  383. package/docs/v1.5-roadmap.md +121 -0
  384. package/docs/v1.6-changelog.md +67 -0
  385. package/docs/v1.6-roadmap.md +89 -0
  386. package/docs/v1.7-changelog.md +98 -0
  387. package/docs/workflow-schema.md +177 -0
  388. package/package.json +177 -0
  389. package/scripts/clean-test-pollution.js +61 -0
  390. package/scripts/openlife-agent-start.sh +6 -0
  391. package/scripts/openlife-agent.service.example +13 -0
  392. package/scripts/openlife-agent.supervisord.conf.example +8 -0
  393. package/scripts/openlife-autonomous-install.sh +29 -0
  394. package/scripts/postinstall-check.sh +37 -0
@@ -0,0 +1,727 @@
1
+ "use strict";
2
+ /**
3
+ * SquadCreator — authoring system for squads under `.catalog/squads/`.
4
+ *
5
+ * Story 5.1 — OpenLife v1.2 Royal Stack.
6
+ *
7
+ * Replaces the old `aiobuilder create-squad` stub (which wrote a 16-line
8
+ * markdown file with hardcoded frontmatter) with a real authoring
9
+ * pipeline that renders `dist-templates/squad-template/` into a
10
+ * structured squad directory including agents, tasks, and a checklist.
11
+ *
12
+ * v1.2 implements 4 of the 8 methods promised by the SQUAD.md spec:
13
+ * - create — full template rendering + directory layout
14
+ * - validate — frontmatter + components reference check
15
+ * - list — delegate to SquadRegistry composite read
16
+ * - analyze — surface coverage gaps (missing tasks/orphan agents)
17
+ *
18
+ * 4 are placeholders for v1.3 (Capability Genesis Engine):
19
+ * - design — LLM-driven proposal from a brief (needs Brain wiring)
20
+ * - migrate — schema migration between versions
21
+ * - extend — append components to an existing squad
22
+ * - publish — promote draft→active, sync to remote registry
23
+ */
24
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ var desc = Object.getOwnPropertyDescriptor(m, k);
27
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
28
+ desc = { enumerable: true, get: function() { return m[k]; } };
29
+ }
30
+ Object.defineProperty(o, k2, desc);
31
+ }) : (function(o, m, k, k2) {
32
+ if (k2 === undefined) k2 = k;
33
+ o[k2] = m[k];
34
+ }));
35
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
36
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
37
+ }) : function(o, v) {
38
+ o["default"] = v;
39
+ });
40
+ var __importStar = (this && this.__importStar) || (function () {
41
+ var ownKeys = function(o) {
42
+ ownKeys = Object.getOwnPropertyNames || function (o) {
43
+ var ar = [];
44
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
45
+ return ar;
46
+ };
47
+ return ownKeys(o);
48
+ };
49
+ return function (mod) {
50
+ if (mod && mod.__esModule) return mod;
51
+ var result = {};
52
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
53
+ __setModuleDefault(result, mod);
54
+ return result;
55
+ };
56
+ })();
57
+ Object.defineProperty(exports, "__esModule", { value: true });
58
+ exports.SquadCreator = void 0;
59
+ exports.extractFirstJson = extractFirstJson;
60
+ const fs = __importStar(require("fs"));
61
+ const path = __importStar(require("path"));
62
+ const crypto = __importStar(require("crypto"));
63
+ const AtomicWriter_1 = require("./util/AtomicWriter");
64
+ const TemplateRenderer_1 = require("./util/TemplateRenderer");
65
+ const ToolsetGuard_1 = require("./toolset/ToolsetGuard");
66
+ class SquadCreator {
67
+ catalogRoot;
68
+ templateRoot;
69
+ constructor(opts = {}) {
70
+ this.catalogRoot = opts.catalogRoot || path.join(process.cwd(), '.catalog', 'squads');
71
+ this.templateRoot = opts.templateRoot || path.resolve(__dirname, '..', '..', 'dist-templates', 'squad-template');
72
+ }
73
+ // ─────────────────────────────────────────────────────────
74
+ // create — full directory rendering from templates
75
+ // ─────────────────────────────────────────────────────────
76
+ create(proposal) {
77
+ (0, ToolsetGuard_1.assertToolsetAllowed)('squads', 'SquadCreator.create');
78
+ if (!this.isValidId(proposal.id)) {
79
+ return { ok: false, error: 'invalid_squad_id', detail: 'must match /^[a-z0-9][a-z0-9._-]+$/i' };
80
+ }
81
+ if (!Array.isArray(proposal.agents) || proposal.agents.length === 0) {
82
+ return { ok: false, error: 'no_agents', detail: 'a squad needs at least one agent' };
83
+ }
84
+ const squadDir = path.join(this.catalogRoot, proposal.id);
85
+ if (fs.existsSync(squadDir)) {
86
+ return { ok: false, error: 'squad_already_exists', detail: squadDir };
87
+ }
88
+ const filesCreated = [];
89
+ try {
90
+ fs.mkdirSync(squadDir, { recursive: true });
91
+ fs.mkdirSync(path.join(squadDir, 'agents'), { recursive: true });
92
+ if (proposal.tasks?.length)
93
+ fs.mkdirSync(path.join(squadDir, 'tasks'), { recursive: true });
94
+ if (proposal.checklists?.length)
95
+ fs.mkdirSync(path.join(squadDir, 'checklists'), { recursive: true });
96
+ // Render SQUAD.md
97
+ const squadVars = this.buildSquadVars(proposal);
98
+ const squadContent = (0, TemplateRenderer_1.renderTemplateFile)(path.join(this.templateRoot, 'SQUAD.md.template'), squadVars);
99
+ const squadFile = path.join(squadDir, 'SQUAD.md');
100
+ (0, AtomicWriter_1.writeStringAtomic)(squadFile, squadContent);
101
+ filesCreated.push(squadFile);
102
+ // Render each agent
103
+ for (const agent of proposal.agents) {
104
+ const agentVars = this.buildAgentVars(agent, proposal);
105
+ const agentContent = (0, TemplateRenderer_1.renderTemplateFile)(path.join(this.templateRoot, 'agent-template.md'), agentVars);
106
+ const agentFile = path.join(squadDir, 'agents', `${agent.id}.md`);
107
+ (0, AtomicWriter_1.writeStringAtomic)(agentFile, agentContent);
108
+ filesCreated.push(agentFile);
109
+ }
110
+ // Render each task
111
+ for (const task of proposal.tasks || []) {
112
+ const taskVars = this.buildTaskVars(task, proposal);
113
+ const taskContent = (0, TemplateRenderer_1.renderTemplateFile)(path.join(this.templateRoot, 'task-template.md'), taskVars);
114
+ const taskFile = path.join(squadDir, 'tasks', `${task.id}.md`);
115
+ (0, AtomicWriter_1.writeStringAtomic)(taskFile, taskContent);
116
+ filesCreated.push(taskFile);
117
+ }
118
+ // Render each checklist
119
+ for (const checklist of proposal.checklists || []) {
120
+ const ckVars = {
121
+ CHECKLIST_NAME: checklist.id,
122
+ SQUAD_NAME: proposal.name,
123
+ PURPOSE: checklist.purpose,
124
+ ITEM_1: checklist.items[0] || '',
125
+ ITEM_2: checklist.items[1] || '',
126
+ ITEM_3: checklist.items[2] || '',
127
+ ITEM_4: checklist.items[3] || '',
128
+ ITEM_5: checklist.items[4] || '',
129
+ };
130
+ const ckContent = (0, TemplateRenderer_1.renderTemplateFile)(path.join(this.templateRoot, 'checklist-template.md'), ckVars);
131
+ const ckFile = path.join(squadDir, 'checklists', `${checklist.id}.md`);
132
+ (0, AtomicWriter_1.writeStringAtomic)(ckFile, ckContent);
133
+ filesCreated.push(ckFile);
134
+ }
135
+ return { ok: true, squadId: proposal.id, squadDir, filesCreated };
136
+ }
137
+ catch (err) {
138
+ // Roll back partial directory on error
139
+ try {
140
+ fs.rmSync(squadDir, { recursive: true, force: true });
141
+ }
142
+ catch { /* ignore */ }
143
+ return { ok: false, error: 'render_failed', detail: err instanceof Error ? err.message : String(err) };
144
+ }
145
+ }
146
+ // ─────────────────────────────────────────────────────────
147
+ // validate — frontmatter + component reference check
148
+ // ─────────────────────────────────────────────────────────
149
+ validate(squadId) {
150
+ const errors = [];
151
+ const warnings = [];
152
+ const squadDir = path.join(this.catalogRoot, squadId);
153
+ const squadFile = path.join(squadDir, 'SQUAD.md');
154
+ if (!fs.existsSync(squadDir)) {
155
+ errors.push(`squad directory not found: ${squadDir}`);
156
+ return { ok: false, squadId, errors, warnings };
157
+ }
158
+ if (!fs.existsSync(squadFile)) {
159
+ errors.push('SQUAD.md missing');
160
+ return { ok: false, squadId, errors, warnings };
161
+ }
162
+ const content = fs.readFileSync(squadFile, 'utf-8');
163
+ // Frontmatter must have id/name/status
164
+ const frontmatter = this.parseFrontmatter(content);
165
+ if (!frontmatter.id)
166
+ errors.push('frontmatter missing id');
167
+ if (!frontmatter.name)
168
+ errors.push('frontmatter missing name');
169
+ if (!frontmatter.status)
170
+ errors.push('frontmatter missing status');
171
+ if (frontmatter.id && frontmatter.id !== squadId) {
172
+ errors.push(`frontmatter id '${frontmatter.id}' does not match directory '${squadId}'`);
173
+ }
174
+ // Component files referenced in SQUAD.md should exist
175
+ const componentRefs = this.parseComponentRefs(content);
176
+ for (const refPath of componentRefs.agents) {
177
+ const full = path.join(squadDir, 'agents', refPath);
178
+ if (!fs.existsSync(full))
179
+ warnings.push(`referenced agent not found: agents/${refPath}`);
180
+ }
181
+ for (const refPath of componentRefs.tasks) {
182
+ const full = path.join(squadDir, 'tasks', refPath);
183
+ if (!fs.existsSync(full))
184
+ warnings.push(`referenced task not found: tasks/${refPath}`);
185
+ }
186
+ return { ok: errors.length === 0, squadId, errors, warnings };
187
+ }
188
+ // ─────────────────────────────────────────────────────────
189
+ // list — direct read of .catalog/squads/
190
+ // ─────────────────────────────────────────────────────────
191
+ list(filter) {
192
+ if (!fs.existsSync(this.catalogRoot))
193
+ return [];
194
+ const out = [];
195
+ for (const entry of fs.readdirSync(this.catalogRoot)) {
196
+ const squadFile = path.join(this.catalogRoot, entry, 'SQUAD.md');
197
+ if (!fs.existsSync(squadFile))
198
+ continue;
199
+ const fm = this.parseFrontmatter(fs.readFileSync(squadFile, 'utf-8'));
200
+ const item = {
201
+ id: fm.id || entry,
202
+ name: fm.name || entry,
203
+ status: fm.status || 'unknown',
204
+ };
205
+ if (filter?.status && item.status !== filter.status)
206
+ continue;
207
+ out.push(item);
208
+ }
209
+ return out;
210
+ }
211
+ // ─────────────────────────────────────────────────────────
212
+ // analyze — coverage gaps + suggestions
213
+ // ─────────────────────────────────────────────────────────
214
+ analyze(squadId) {
215
+ const squadDir = path.join(this.catalogRoot, squadId);
216
+ if (!fs.existsSync(squadDir))
217
+ return null;
218
+ const agentsDir = path.join(squadDir, 'agents');
219
+ const tasksDir = path.join(squadDir, 'tasks');
220
+ const workflowsDir = path.join(squadDir, 'workflows');
221
+ const checklistsDir = path.join(squadDir, 'checklists');
222
+ const listFiles = (d) => (fs.existsSync(d) && fs.statSync(d).isDirectory() ? fs.readdirSync(d) : []);
223
+ const agentFiles = listFiles(agentsDir).filter((f) => f.endsWith('.md'));
224
+ const taskFiles = listFiles(tasksDir).filter((f) => f.endsWith('.md'));
225
+ const workflowFiles = listFiles(workflowsDir).filter((f) => f.endsWith('.yaml') || f.endsWith('.yml'));
226
+ const checklistFiles = listFiles(checklistsDir).filter((f) => f.endsWith('.md'));
227
+ // Orphan agents: agent files not referenced in any task
228
+ const orphanAgents = [];
229
+ for (const af of agentFiles) {
230
+ const aid = af.replace(/\.md$/, '');
231
+ const referenced = taskFiles.some((tf) => fs.readFileSync(path.join(tasksDir, tf), 'utf-8').includes(aid));
232
+ if (!referenced && taskFiles.length > 0)
233
+ orphanAgents.push(aid);
234
+ }
235
+ // Unreferenced tasks: task files whose owner agent file is missing
236
+ const unreferencedTasks = [];
237
+ for (const tf of taskFiles) {
238
+ const content = fs.readFileSync(path.join(tasksDir, tf), 'utf-8');
239
+ const ownerMatch = content.match(/Owner:\s*([\w-]+)/);
240
+ if (ownerMatch && !agentFiles.includes(`${ownerMatch[1]}.md`)) {
241
+ unreferencedTasks.push(tf.replace(/\.md$/, ''));
242
+ }
243
+ }
244
+ const suggestions = [];
245
+ if (agentFiles.length === 0)
246
+ suggestions.push('squad has no agents — at least one is required');
247
+ if (taskFiles.length === 0)
248
+ suggestions.push('squad has no tasks — consider adding at least one canonical task');
249
+ if (workflowFiles.length === 0)
250
+ suggestions.push('squad has no workflows — consider adding a primary workflow for discoverability');
251
+ if (checklistFiles.length === 0)
252
+ suggestions.push('squad has no quality gates — consider adding a checklist');
253
+ if (orphanAgents.length > 0)
254
+ suggestions.push(`${orphanAgents.length} agent(s) not referenced by any task`);
255
+ if (unreferencedTasks.length > 0)
256
+ suggestions.push(`${unreferencedTasks.length} task(s) reference a missing owner agent`);
257
+ return {
258
+ squadId,
259
+ agentCount: agentFiles.length,
260
+ taskCount: taskFiles.length,
261
+ workflowCount: workflowFiles.length,
262
+ checklistCount: checklistFiles.length,
263
+ orphanAgents,
264
+ unreferencedTasks,
265
+ suggestions,
266
+ };
267
+ }
268
+ // ─────────────────────────────────────────────────────────
269
+ // v1.3 placeholders — stable surface, return clear "not implemented"
270
+ // so callers can wire UI / CLI today and the real implementation
271
+ // arrives behind the same API.
272
+ // ─────────────────────────────────────────────────────────
273
+ /**
274
+ * Propose a SquadProposal from a free-text brief.
275
+ *
276
+ * Story 3.1 — OpenLife v1.3.
277
+ *
278
+ * Heuristic mode: produces a minimum-viable squad that the caller can
279
+ * pass directly to create(). No API call — works offline, no keys
280
+ * needed. Returns the proposal; caller decides whether to call create()
281
+ * with it or refine first. The heuristic picks 3 default agents
282
+ * (lead, executor, reviewer) and one task; for richer drafts, the
283
+ * CapabilityGenesisEngine wires this together with deep-research-style
284
+ * patterns.
285
+ *
286
+ * Brain-mode (live LLM proposal) lands in v1.4; the signature stays
287
+ * stable so callers don't change.
288
+ */
289
+ design(brief, opts = {}) {
290
+ const trimmed = (brief || '').trim();
291
+ if (!trimmed)
292
+ return { ok: false, error: 'invalid_brief' };
293
+ const mode = opts.mode || 'professional';
294
+ const id = opts.id || slugifyForId(trimmed).slice(0, 50);
295
+ if (!/^[a-z0-9][a-z0-9._-]+$/i.test(id))
296
+ return { ok: false, error: 'invalid_squad_id', };
297
+ // Heuristic agent roster — same shape SquadCreator.create accepts.
298
+ const agents = [
299
+ { id: `${id}-lead`, name: `${id}-lead`, role: 'orchestrator' },
300
+ { id: `${id}-executor`, name: `${id}-executor`, role: 'executor' },
301
+ ];
302
+ if (mode === 'professional' || mode === 'elite') {
303
+ agents.push({ id: `${id}-reviewer`, name: `${id}-reviewer`, role: 'reviewer' });
304
+ }
305
+ if (mode === 'elite') {
306
+ agents.push({ id: `${id}-strategist`, name: `${id}-strategist`, role: 'strategist' });
307
+ }
308
+ const tasks = [
309
+ { id: `${id}-default`, ownerAgentId: agents[0].id, purpose: trimmed },
310
+ ];
311
+ const checklists = mode === 'elite' ? [{
312
+ id: `${id}-quality-gate`,
313
+ purpose: `quality gate for ${id}`,
314
+ items: ['Brief understood', 'Agents assigned', 'Output validated'],
315
+ }] : [];
316
+ const proposal = {
317
+ id,
318
+ name: id,
319
+ description: trimmed,
320
+ version: '0.1.0',
321
+ author: 'squad-creator.design',
322
+ agents,
323
+ tasks,
324
+ checklists,
325
+ };
326
+ return { ok: true, proposal };
327
+ }
328
+ /**
329
+ * Story 8.1 — LLM-driven design.
330
+ *
331
+ * If `brain.isAnyProviderAvailable()` returns true, asks the Brain for a
332
+ * structured JSON proposal and parses it. On any parse / API failure,
333
+ * falls back to the heuristic `design()` so the call is never lossy.
334
+ *
335
+ * Signature is additive: existing callers continue using sync `design()`.
336
+ * No env flag — the presence of an API key IS the opt-in (locked decision
337
+ * 2 of the v1.4 plan).
338
+ */
339
+ async designWithBrain(brain, brief, opts = {}) {
340
+ if (!brain.isAnyProviderAvailable()) {
341
+ const r = this.design(brief, opts);
342
+ return r.ok ? { ok: true, proposal: r.proposal, source: 'heuristic' } : r;
343
+ }
344
+ const trimmed = (brief || '').trim();
345
+ if (!trimmed)
346
+ return { ok: false, error: 'invalid_brief' };
347
+ const mode = opts.mode || 'professional';
348
+ const id = opts.id || slugifyForId(trimmed).slice(0, 50);
349
+ if (!/^[a-z0-9][a-z0-9._-]+$/i.test(id))
350
+ return { ok: false, error: 'invalid_squad_id' };
351
+ const systemPrompt = `You are SquadCreator. Given a brief and an authoring mode (quick|professional|elite), return a STRICT JSON object describing a squad. The output MUST be a single JSON object — no prose, no markdown fences. Shape:
352
+ {
353
+ "agents": [{"id":"<slug>","role":"<role>"}],
354
+ "tasks": [{"id":"<slug>","ownerAgentId":"<agent-id>","purpose":"<one-line>"}],
355
+ "checklists": [{"id":"<slug>","purpose":"<one-line>","items":["..."]}]
356
+ }
357
+ Rules:
358
+ - quick mode: 2 agents (lead, executor), 1 task, no checklist
359
+ - professional: + reviewer (3 agents), 1-2 tasks, optional checklist
360
+ - elite: + strategist (4 agents), 2-3 tasks, mandatory quality-gate checklist
361
+ - All ids must be lowercase a-z0-9 with hyphens
362
+ - Prefix ids with "${id}-" so they're unique within the squad`;
363
+ const userMessage = `Brief: ${trimmed}\nMode: ${mode}\nSquad id: ${id}`;
364
+ try {
365
+ const raw = await brain.think(systemPrompt, userMessage);
366
+ const parsed = extractFirstJson(raw);
367
+ if (!parsed || typeof parsed !== 'object')
368
+ throw new Error('no_json_in_response');
369
+ const p = parsed;
370
+ if (!Array.isArray(p.agents) || p.agents.length < 2)
371
+ throw new Error('missing_or_too_few_agents');
372
+ const proposal = {
373
+ id, name: id, description: trimmed,
374
+ version: '0.1.0',
375
+ author: 'squad-creator.designWithBrain',
376
+ agents: p.agents.map((a) => ({ id: a.id, name: a.id, role: a.role })),
377
+ tasks: Array.isArray(p.tasks) ? p.tasks : [{ id: `${id}-default`, ownerAgentId: p.agents[0].id, purpose: trimmed }],
378
+ checklists: Array.isArray(p.checklists) ? p.checklists : [],
379
+ };
380
+ return { ok: true, proposal, source: 'brain' };
381
+ }
382
+ catch {
383
+ // Any failure (network, parse, schema) → heuristic fallback. Never lossy.
384
+ const r = this.design(brief, opts);
385
+ return r.ok ? { ok: true, proposal: r.proposal, source: 'heuristic' } : r;
386
+ }
387
+ }
388
+ // ─────────────────────────────────────────────────────────
389
+ // migrate — rewrite SQUAD.md frontmatter version atomically
390
+ // ─────────────────────────────────────────────────────────
391
+ migrate(squadId, fromVersion, toVersion) {
392
+ if (!this.isValidId(squadId))
393
+ return { ok: false, squadId, error: 'invalid_squad_id' };
394
+ if (!this.isValidVersion(fromVersion) || !this.isValidVersion(toVersion)) {
395
+ return { ok: false, squadId, error: 'invalid_version', detail: 'expect semver-like X.Y or X.Y.Z' };
396
+ }
397
+ const squadFile = path.join(this.catalogRoot, squadId, 'SQUAD.md');
398
+ if (!fs.existsSync(squadFile))
399
+ return { ok: false, squadId, error: 'squad_not_found' };
400
+ const content = fs.readFileSync(squadFile, 'utf-8');
401
+ const current = this.findSquadVersion(content);
402
+ if (current && current !== fromVersion) {
403
+ return { ok: false, squadId, error: 'version_mismatch', detail: `current=${current} expected=${fromVersion}` };
404
+ }
405
+ const next = this.rewriteSquadVersion(content, toVersion);
406
+ (0, AtomicWriter_1.writeStringAtomic)(squadFile, next);
407
+ return { ok: true, squadId, fromVersion, toVersion, filesChanged: [squadFile] };
408
+ }
409
+ findSquadVersion(content) {
410
+ const fm = this.parseFrontmatter(content);
411
+ if (fm.version)
412
+ return fm.version.replace(/^["']|["']$/g, '');
413
+ // Fall back to an embedded yaml `version: "X.Y.Z"` line.
414
+ const m = content.match(/^version:\s*"?([^\n"']+?)"?\s*$/m);
415
+ return m ? m[1] : null;
416
+ }
417
+ rewriteSquadVersion(content, toVersion) {
418
+ // 1. Replace the embedded yaml version line (if any), outside frontmatter.
419
+ const fmMatch = content.match(/^---\n[\s\S]*?\n---\n/);
420
+ const head = fmMatch ? content.slice(0, fmMatch[0].length) : '';
421
+ const body = fmMatch ? content.slice(fmMatch[0].length) : content;
422
+ const bodyReplaced = body.replace(/^version:\s*"?[^\n"']+"?\s*$/m, `version: "${toVersion}"`);
423
+ // 2. Update or insert the frontmatter version field.
424
+ return this.rewriteFrontmatterField(head + bodyReplaced, 'version', `"${toVersion}"`);
425
+ }
426
+ // ─────────────────────────────────────────────────────────
427
+ // extend — append component without re-rendering the whole squad
428
+ // ─────────────────────────────────────────────────────────
429
+ extend(squadId, component) {
430
+ if (!this.isValidId(squadId))
431
+ return { ok: false, squadId, error: 'invalid_squad_id' };
432
+ const squadDir = path.join(this.catalogRoot, squadId);
433
+ const squadFile = path.join(squadDir, 'SQUAD.md');
434
+ if (!fs.existsSync(squadFile))
435
+ return { ok: false, squadId, error: 'squad_not_found' };
436
+ const fm = this.parseFrontmatter(fs.readFileSync(squadFile, 'utf-8'));
437
+ const squadName = fm.name || squadId;
438
+ const filesAdded = [];
439
+ try {
440
+ if (component.kind === 'agent') {
441
+ fs.mkdirSync(path.join(squadDir, 'agents'), { recursive: true });
442
+ const proposalLike = { id: squadId, name: squadName, description: fm.description || '', agents: [component.spec] };
443
+ const vars = this.buildAgentVars(component.spec, proposalLike);
444
+ const out = (0, TemplateRenderer_1.renderTemplateFile)(path.join(this.templateRoot, 'agent-template.md'), vars);
445
+ const file = path.join(squadDir, 'agents', `${component.spec.id}.md`);
446
+ if (fs.existsSync(file))
447
+ return { ok: false, squadId, error: 'component_exists', detail: file };
448
+ (0, AtomicWriter_1.writeStringAtomic)(file, out);
449
+ filesAdded.push(file);
450
+ }
451
+ else if (component.kind === 'task') {
452
+ fs.mkdirSync(path.join(squadDir, 'tasks'), { recursive: true });
453
+ const proposalLike = { id: squadId, name: squadName, description: fm.description || '', agents: [] };
454
+ const vars = this.buildTaskVars(component.spec, proposalLike);
455
+ const out = (0, TemplateRenderer_1.renderTemplateFile)(path.join(this.templateRoot, 'task-template.md'), vars);
456
+ const file = path.join(squadDir, 'tasks', `${component.spec.id}.md`);
457
+ if (fs.existsSync(file))
458
+ return { ok: false, squadId, error: 'component_exists', detail: file };
459
+ (0, AtomicWriter_1.writeStringAtomic)(file, out);
460
+ filesAdded.push(file);
461
+ }
462
+ else if (component.kind === 'checklist') {
463
+ fs.mkdirSync(path.join(squadDir, 'checklists'), { recursive: true });
464
+ const ckVars = {
465
+ CHECKLIST_NAME: component.spec.id,
466
+ SQUAD_NAME: squadName,
467
+ PURPOSE: component.spec.purpose,
468
+ ITEM_1: component.spec.items[0] || '',
469
+ ITEM_2: component.spec.items[1] || '',
470
+ ITEM_3: component.spec.items[2] || '',
471
+ ITEM_4: component.spec.items[3] || '',
472
+ ITEM_5: component.spec.items[4] || '',
473
+ };
474
+ const out = (0, TemplateRenderer_1.renderTemplateFile)(path.join(this.templateRoot, 'checklist-template.md'), ckVars);
475
+ const file = path.join(squadDir, 'checklists', `${component.spec.id}.md`);
476
+ if (fs.existsSync(file))
477
+ return { ok: false, squadId, error: 'component_exists', detail: file };
478
+ (0, AtomicWriter_1.writeStringAtomic)(file, out);
479
+ filesAdded.push(file);
480
+ }
481
+ else if (component.kind === 'workflow') {
482
+ fs.mkdirSync(path.join(squadDir, 'workflows'), { recursive: true });
483
+ const file = path.join(squadDir, 'workflows', `${component.id}.yaml`);
484
+ if (fs.existsSync(file))
485
+ return { ok: false, squadId, error: 'component_exists', detail: file };
486
+ (0, AtomicWriter_1.writeStringAtomic)(file, component.content);
487
+ filesAdded.push(file);
488
+ }
489
+ else {
490
+ return { ok: false, squadId, error: 'unknown_component_kind' };
491
+ }
492
+ this.appendExtensionLog(squadFile, component.kind, filesAdded);
493
+ return { ok: true, squadId, kind: component.kind, filesAdded };
494
+ }
495
+ catch (err) {
496
+ return { ok: false, squadId, error: 'extend_failed', detail: err instanceof Error ? err.message : String(err) };
497
+ }
498
+ }
499
+ // ─────────────────────────────────────────────────────────
500
+ // publish — hash + ledger append + status flip to active
501
+ // ─────────────────────────────────────────────────────────
502
+ publish(squadId) {
503
+ if (!this.isValidId(squadId))
504
+ return { ok: false, squadId, error: 'invalid_squad_id' };
505
+ const squadFile = path.join(this.catalogRoot, squadId, 'SQUAD.md');
506
+ if (!fs.existsSync(squadFile))
507
+ return { ok: false, squadId, error: 'squad_not_found' };
508
+ let content = fs.readFileSync(squadFile, 'utf-8');
509
+ const fm = this.parseFrontmatter(content);
510
+ if (fm.status === 'archived') {
511
+ return { ok: false, squadId, error: 'squad_archived', detail: 'cannot publish archived squad' };
512
+ }
513
+ if (fm.status !== 'active') {
514
+ content = this.rewriteFrontmatterField(content, 'status', 'active');
515
+ (0, AtomicWriter_1.writeStringAtomic)(squadFile, content);
516
+ }
517
+ const sha256 = crypto.createHash('sha256').update(content).digest('hex');
518
+ const stateDir = process.env.OPENLIFE_STATE_DIR || path.join(process.cwd(), '.openlife');
519
+ fs.mkdirSync(stateDir, { recursive: true });
520
+ const ledger = path.join(stateDir, 'published-assets.jsonl');
521
+ const entry = JSON.stringify({ kind: 'squad', id: squadId, sha256, file: squadFile, publishedAt: new Date().toISOString() }) + '\n';
522
+ fs.appendFileSync(ledger, entry, 'utf-8');
523
+ return { ok: true, squadId, sha256, ledgerEntry: entry.trim(), status: 'active' };
524
+ }
525
+ /**
526
+ * Story 14.1 (v1.5) — Publish + push to a remote registry.
527
+ *
528
+ * Composes the existing local-ledger publish with RemotePublisher.
529
+ * The local seal lands first (so callers still have a sealed asset
530
+ * if the remote push fails). The returned envelope carries both
531
+ * results: `ok` reflects the LOCAL publish; the remote outcome lives
532
+ * on the `remote` field so failures can be inspected without
533
+ * losing the local seal.
534
+ *
535
+ * Refuses to attempt the remote push if RemotePublisher is not
536
+ * configured — returns `remote.error='remote_publish_not_configured'`.
537
+ */
538
+ async publishWithRemote(squadId) {
539
+ const local = this.publish(squadId);
540
+ if (!local.ok || !local.sha256)
541
+ return local;
542
+ const squadFile = path.join(this.catalogRoot, squadId, 'SQUAD.md');
543
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
544
+ const { RemotePublisher } = require('./RemotePublisher');
545
+ const remote = await new RemotePublisher().publishAsset('squad', squadId, local.sha256, squadFile);
546
+ return { ...local, remote };
547
+ }
548
+ // ─────────────────────────────────────────────────────────
549
+ // Helpers — used by migrate/extend/publish
550
+ // ─────────────────────────────────────────────────────────
551
+ isValidVersion(v) {
552
+ return /^\d+\.\d+(\.\d+)?$/.test(v);
553
+ }
554
+ rewriteFrontmatterField(content, field, value) {
555
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---\n/);
556
+ if (!fmMatch) {
557
+ // No frontmatter — prepend one.
558
+ return `---\n${field}: ${value}\n---\n${content}`;
559
+ }
560
+ const block = fmMatch[1];
561
+ const lines = block.split('\n');
562
+ const idx = lines.findIndex((l) => l.match(new RegExp(`^${field}:`)));
563
+ if (idx >= 0)
564
+ lines[idx] = `${field}: ${value}`;
565
+ else
566
+ lines.push(`${field}: ${value}`);
567
+ const newBlock = lines.join('\n');
568
+ return content.replace(fmMatch[0], `---\n${newBlock}\n---\n`);
569
+ }
570
+ appendExtensionLog(squadFile, kind, files) {
571
+ try {
572
+ const marker = '\n## Extensions\n';
573
+ let content = fs.readFileSync(squadFile, 'utf-8');
574
+ if (!content.includes('## Extensions'))
575
+ content += marker;
576
+ const ts = new Date().toISOString();
577
+ content += `- ${ts} added ${kind}: ${files.map((f) => path.basename(f)).join(', ')}\n`;
578
+ (0, AtomicWriter_1.writeStringAtomic)(squadFile, content);
579
+ }
580
+ catch { /* extension log is best-effort */ }
581
+ }
582
+ // ─────────────────────────────────────────────────────────
583
+ // Internals
584
+ // ─────────────────────────────────────────────────────────
585
+ buildSquadVars(p) {
586
+ const agentRows = p.agents.map((a) => `| ${a.id} | ${a.role} |`).join('\n');
587
+ const tagsList = (p.tags || []).map((t) => ` - ${t}`).join('\n');
588
+ const componentAgents = p.agents.map((a) => ` - ${a.id}.md`).join('\n');
589
+ const componentTasks = (p.tasks || []).map((t) => ` - ${t.id}.md`).join('\n');
590
+ const componentWorkflows = (p.workflows || []).map((w) => ` - ${w}`).join('\n');
591
+ const componentChecklists = (p.checklists || []).map((c) => ` - ${c.id}.md`).join('\n');
592
+ return {
593
+ SQUAD_ID: p.id,
594
+ SQUAD_NAME: p.name,
595
+ SOURCE: p.source || 'aiobuilder-built',
596
+ STATUS: p.status || 'draft',
597
+ DESCRIPTION: p.description,
598
+ VERSION: p.version || '1.0.0',
599
+ SHORT_TITLE: p.shortTitle || p.name,
600
+ AUTHOR: p.author || 'OpenLife',
601
+ LICENSE: p.license || 'MIT',
602
+ SLASH_PREFIX: p.slashPrefix || p.id,
603
+ TAGS_LIST: tagsList || ' - squad',
604
+ AGENTS_TABLE: agentRows,
605
+ COMPONENT_AGENTS: componentAgents,
606
+ COMPONENT_TASKS: componentTasks || ' []',
607
+ COMPONENT_WORKFLOWS: componentWorkflows || ' []',
608
+ COMPONENT_CHECKLISTS: componentChecklists || ' []',
609
+ };
610
+ }
611
+ buildAgentVars(a, p) {
612
+ const base = {
613
+ AGENT_ID: a.id,
614
+ AGENT_NAME: a.name,
615
+ AGENT_ROLE: a.role,
616
+ AGENT_TITLE: a.name,
617
+ SQUAD_NAME: p.name,
618
+ ICON: '🤖',
619
+ WHEN_TO_USE: `when ${a.role} is needed`,
620
+ DESCRIPTION: `${a.name} — ${a.role}`,
621
+ ROLE: a.role,
622
+ STYLE: 'analytical',
623
+ IDENTITY: `Specialist in ${a.role}`,
624
+ FOCUS: a.role,
625
+ PRINCIPLE_1: 'Respect tool permissions',
626
+ PRINCIPLE_2: 'Emit audit events',
627
+ PRINCIPLE_3: 'Defer to human approval beyond autonomy budget',
628
+ COMMAND_1: 'execute',
629
+ COMMAND_1_DESC: 'Execute the canonical task for this role',
630
+ CAPABILITIES_LIST: '- TBD',
631
+ };
632
+ return { ...base, ...(a.vars || {}) };
633
+ }
634
+ buildTaskVars(t, p) {
635
+ const base = {
636
+ TASK_NAME: t.id,
637
+ OWNER_AGENT: t.ownerAgentId,
638
+ SQUAD_NAME: p.name,
639
+ PURPOSE: t.purpose,
640
+ INPUT_1: 'TBD',
641
+ INPUT_2: 'TBD',
642
+ OUTPUT_1: 'TBD',
643
+ OUTPUT_2: 'TBD',
644
+ STEP_1: 'Load context',
645
+ STEP_2: 'Execute primary action',
646
+ STEP_3: 'Record evidence and exit',
647
+ VALIDATION_1: 'Output exists and is non-empty',
648
+ VALIDATION_2: 'Audit event emitted',
649
+ NOTES: '',
650
+ };
651
+ return { ...base, ...(t.vars || {}) };
652
+ }
653
+ parseFrontmatter(content) {
654
+ const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
655
+ if (!match)
656
+ return {};
657
+ const out = {};
658
+ for (const line of match[1].split('\n')) {
659
+ const m = line.match(/^([\w-]+):\s*(.*)$/);
660
+ if (m)
661
+ out[m[1]] = m[2].trim();
662
+ }
663
+ return out;
664
+ }
665
+ parseComponentRefs(content) {
666
+ // Look for the embedded squad.yaml block; parse components: lists.
667
+ const out = { agents: [], tasks: [], workflows: [], checklists: [] };
668
+ const section = content.match(/components:\s*\n([\s\S]*?)(?=\nconfig:|\n```|$)/);
669
+ if (!section)
670
+ return out;
671
+ let current = null;
672
+ for (const line of section[1].split('\n')) {
673
+ const keyMatch = line.match(/^\s\s(agents|tasks|workflows|checklists):/);
674
+ if (keyMatch) {
675
+ current = keyMatch[1];
676
+ continue;
677
+ }
678
+ const itemMatch = line.match(/^\s\s\s\s-\s+(.+)$/);
679
+ if (itemMatch && current) {
680
+ const v = itemMatch[1].trim();
681
+ if (v && v !== '[]')
682
+ out[current].push(v);
683
+ }
684
+ }
685
+ return out;
686
+ }
687
+ isValidId(id) {
688
+ return /^[a-z0-9][a-z0-9._-]+$/i.test(id);
689
+ }
690
+ }
691
+ exports.SquadCreator = SquadCreator;
692
+ function slugifyForId(s) {
693
+ return s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
694
+ }
695
+ /**
696
+ * Story 8.1 helper — extract the first JSON object from raw model output.
697
+ * Tolerates markdown fences (```json ... ```) and surrounding prose.
698
+ * Returns the parsed object or null. Never throws.
699
+ */
700
+ function extractFirstJson(raw) {
701
+ if (typeof raw !== 'string')
702
+ return null;
703
+ // Strip common markdown fences first.
704
+ let s = raw.replace(/```(?:json)?\s*\n?/gi, '').replace(/```/g, '');
705
+ const start = s.indexOf('{');
706
+ if (start === -1)
707
+ return null;
708
+ // Find matching closing brace by depth counting (handles nested).
709
+ let depth = 0;
710
+ for (let i = start; i < s.length; i++) {
711
+ const c = s[i];
712
+ if (c === '{')
713
+ depth++;
714
+ else if (c === '}') {
715
+ depth--;
716
+ if (depth === 0) {
717
+ try {
718
+ return JSON.parse(s.slice(start, i + 1));
719
+ }
720
+ catch {
721
+ return null;
722
+ }
723
+ }
724
+ }
725
+ }
726
+ return null;
727
+ }