@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,134 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AutonomousInstaller = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ class AutonomousInstaller {
40
+ root;
41
+ constructor(root = process.cwd()) {
42
+ this.root = root;
43
+ }
44
+ install() {
45
+ const filesCreated = [];
46
+ const openlifeDir = path.join(this.root, '.openlife');
47
+ fs.mkdirSync(openlifeDir, { recursive: true });
48
+ const runtimeFile = path.join(openlifeDir, 'agent-runtime.json');
49
+ if (!fs.existsSync(runtimeFile)) {
50
+ fs.writeFileSync(runtimeFile, JSON.stringify({ running: false, mode: 'autonomous' }, null, 2), 'utf-8');
51
+ filesCreated.push(runtimeFile);
52
+ }
53
+ const queueFile = path.join(openlifeDir, 'agent-queue.json');
54
+ if (!fs.existsSync(queueFile)) {
55
+ fs.writeFileSync(queueFile, JSON.stringify({ queuedObjectives: [], updatedAt: new Date().toISOString() }, null, 2), 'utf-8');
56
+ filesCreated.push(queueFile);
57
+ }
58
+ const policyFile = path.join(openlifeDir, 'autonomous-policy.json');
59
+ if (!fs.existsSync(policyFile)) {
60
+ fs.writeFileSync(policyFile, JSON.stringify({
61
+ maxConcurrentMissions: 1,
62
+ requireGovernanceRiskCheck: true,
63
+ autoPersistMemory: true,
64
+ autoRunEvolution: true
65
+ }, null, 2), 'utf-8');
66
+ filesCreated.push(policyFile);
67
+ }
68
+ const systemdFile = path.join(this.root, 'scripts', 'openlife-agent.service.example');
69
+ fs.mkdirSync(path.dirname(systemdFile), { recursive: true });
70
+ fs.writeFileSync(systemdFile, this.systemdTemplate(), 'utf-8');
71
+ filesCreated.push(systemdFile);
72
+ const supervisorFile = path.join(this.root, 'scripts', 'openlife-agent.supervisord.conf.example');
73
+ fs.writeFileSync(supervisorFile, this.supervisorTemplate(), 'utf-8');
74
+ filesCreated.push(supervisorFile);
75
+ const launcherFile = path.join(this.root, 'scripts', 'openlife-agent-start.sh');
76
+ fs.writeFileSync(launcherFile, this.launcherTemplate(), 'utf-8');
77
+ fs.chmodSync(launcherFile, 0o755);
78
+ filesCreated.push(launcherFile);
79
+ const installManifest = path.join(openlifeDir, 'autonomous-install-manifest.json');
80
+ fs.writeFileSync(installManifest, JSON.stringify({
81
+ installedAt: new Date().toISOString(),
82
+ root: this.root,
83
+ filesCreated
84
+ }, null, 2), 'utf-8');
85
+ filesCreated.push(installManifest);
86
+ return {
87
+ installedAt: new Date().toISOString(),
88
+ root: this.root,
89
+ filesCreated,
90
+ nextCommands: [
91
+ 'openlife mode set autonomous --host claude-code',
92
+ 'openlife agent start',
93
+ 'openlife agent status'
94
+ ]
95
+ };
96
+ }
97
+ launcherTemplate() {
98
+ return `#!/usr/bin/env bash
99
+ set -euo pipefail
100
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
101
+ cd "$ROOT"
102
+ node dist/index.js mode set autonomous --host claude-code
103
+ node dist/index.js agent start
104
+ `;
105
+ }
106
+ systemdTemplate() {
107
+ return `[Unit]
108
+ Description=OpenLife Autonomous Agent
109
+ After=network.target
110
+
111
+ [Service]
112
+ Type=simple
113
+ WorkingDirectory=${this.root}
114
+ ExecStart=/usr/bin/node ${this.root}/dist/index.js start --daemon
115
+ Restart=always
116
+ RestartSec=5
117
+
118
+ [Install]
119
+ WantedBy=multi-user.target
120
+ `;
121
+ }
122
+ supervisorTemplate() {
123
+ return `[program:openlife-agent]
124
+ command=/usr/bin/node ${this.root}/dist/index.js start --daemon
125
+ directory=${this.root}
126
+ autostart=true
127
+ autorestart=true
128
+ startsecs=5
129
+ stderr_logfile=${this.root}/.openlife/logs/agent.err.log
130
+ stdout_logfile=${this.root}/.openlife/logs/agent.out.log
131
+ `;
132
+ }
133
+ }
134
+ exports.AutonomousInstaller = AutonomousInstaller;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.DreamOrganizer = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ class DreamOrganizer {
40
+ root;
41
+ constructor(root = process.cwd()) {
42
+ this.root = root;
43
+ }
44
+ organize(raw) {
45
+ const normalized = raw.toLowerCase();
46
+ const categories = [];
47
+ const addCategory = (value) => {
48
+ if (!categories.includes(value))
49
+ categories.push(value);
50
+ };
51
+ if (/(ideia|criar|build|produto|projeto)/.test(normalized))
52
+ addCategory('ideias');
53
+ if (/(estudar|aprendi|aprender|pesquisa|ler)/.test(normalized))
54
+ addCategory('aprendizado');
55
+ if (/(preciso|fazer|implementar|entregar|todo)/.test(normalized))
56
+ addCategory('tarefas');
57
+ if (/(refleti|senti|mente|foco|disciplina|emoç|emoc)/.test(normalized))
58
+ addCategory('reflexoes');
59
+ if (categories.length === 0)
60
+ addCategory('geral');
61
+ const summary = raw.length > 180 ? `${raw.slice(0, 177)}...` : raw;
62
+ return {
63
+ createdAt: new Date().toISOString(),
64
+ raw,
65
+ summary,
66
+ categories,
67
+ tags: ['dream', ...categories]
68
+ };
69
+ }
70
+ save(note) {
71
+ const dreamDir = path.join(this.root, '.openlife', 'dreams');
72
+ fs.mkdirSync(dreamDir, { recursive: true });
73
+ const day = note.createdAt.slice(0, 10);
74
+ const filePath = path.join(dreamDir, `${day}.md`);
75
+ const block = [
76
+ `## /dream ${note.createdAt}`,
77
+ `- summary: ${note.summary}`,
78
+ `- categories: ${note.categories.join(', ')}`,
79
+ `- tags: ${note.tags.join(', ')}`,
80
+ '',
81
+ note.raw,
82
+ ''
83
+ ].join('\n');
84
+ fs.appendFileSync(filePath, `${block}\n`, 'utf-8');
85
+ return filePath;
86
+ }
87
+ }
88
+ exports.DreamOrganizer = DreamOrganizer;
@@ -0,0 +1,426 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.HostInstaller = exports.HostNotYetSupportedError = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const ToolsetGuard_1 = require("../orchestrator/toolset/ToolsetGuard");
40
+ class HostNotYetSupportedError extends Error {
41
+ host;
42
+ code = 'HOST_NOT_YET_SUPPORTED';
43
+ constructor(host) {
44
+ super(`HOST_NOT_YET_SUPPORTED: install for "${host}" is not implemented yet. ` +
45
+ `Story 3.3 ships claude-code only; gemini-cli and codex follow in a later v1.1 story. ` +
46
+ `Use --host claude-code for now, or set CLAUDECODE=1 to auto-detect.`);
47
+ this.host = host;
48
+ }
49
+ }
50
+ exports.HostNotYetSupportedError = HostNotYetSupportedError;
51
+ class HostInstaller {
52
+ templatesRoot;
53
+ constructor(opts = {}) {
54
+ this.templatesRoot = opts.templatesRoot || HostInstaller.defaultTemplatesRoot();
55
+ }
56
+ /**
57
+ * Resolves the dist-templates/ directory relative to this compiled file.
58
+ * Source: src/cli/HostInstaller.ts → compiled: dist/cli/HostInstaller.js
59
+ * Going up twice from dist/cli/ lands on the package root where dist-templates/ lives.
60
+ * Works in both repo-dev (npm run build) and consumer-installed (node_modules/@open-life/cli/) layouts.
61
+ */
62
+ static defaultTemplatesRoot() {
63
+ return path.resolve(__dirname, '..', '..', 'dist-templates');
64
+ }
65
+ /**
66
+ * Dispatch on validated Host. Throws HostNotYetSupportedError for hosts without an installer.
67
+ */
68
+ install(host, options) {
69
+ (0, ToolsetGuard_1.assertToolsetAllowed)('file', 'HostInstaller.install');
70
+ switch (host) {
71
+ case 'claude-code':
72
+ return this.installForClaudeCode(options);
73
+ case 'gemini-cli':
74
+ return this.installForGeminiCli(options);
75
+ case 'codex':
76
+ return this.installForCodex(options);
77
+ default:
78
+ // Should be unreachable because Host is a validated union; defensive throw.
79
+ throw new HostNotYetSupportedError(host);
80
+ }
81
+ }
82
+ installForClaudeCode(options) {
83
+ const targetRoot = options.targetRoot;
84
+ const sourceRoot = path.join(this.templatesRoot, 'claude-code');
85
+ if (!fs.existsSync(sourceRoot)) {
86
+ throw new Error(`DIST_TEMPLATES_MISSING: expected templates at ${sourceRoot}. ` +
87
+ `Run "npm run build" or reinstall @open-life/cli.`);
88
+ }
89
+ const files = [];
90
+ const notes = [];
91
+ // 1. Agents → <root>/.claude/agents/openlife-*.md
92
+ const agentsSrc = path.join(sourceRoot, 'agents');
93
+ const agentsDst = path.join(targetRoot, '.claude', 'agents');
94
+ files.push(...this.copyDir(agentsSrc, agentsDst));
95
+ // 2. Slash commands → <root>/.claude/commands/openlife/*.md
96
+ const commandsSrc = path.join(sourceRoot, 'commands', 'openlife');
97
+ const commandsDst = path.join(targetRoot, '.claude', 'commands', 'openlife');
98
+ files.push(...this.copyDir(commandsSrc, commandsDst));
99
+ // 3. MCP manifest → .openlife/install-mcp-snippet.json (non-invasive: user merges into ~/.claude.json manually)
100
+ const mcpSrc = path.join(sourceRoot, 'mcp', 'openlife-orchestrator.json');
101
+ let mcpSnippetPath;
102
+ if (fs.existsSync(mcpSrc)) {
103
+ const stateDir = path.join(targetRoot, '.openlife');
104
+ if (!fs.existsSync(stateDir))
105
+ fs.mkdirSync(stateDir, { recursive: true });
106
+ mcpSnippetPath = path.join(stateDir, 'install-mcp-snippet.json');
107
+ const action = this.copyFile(mcpSrc, mcpSnippetPath);
108
+ files.push(action);
109
+ notes.push(`MCP manifest staged at ${mcpSnippetPath}. ` +
110
+ `To enable, merge its "mcpServers" entry into ~/.claude.json under the "mcpServers" key. ` +
111
+ `Note: bin/openlife-mcp.js (the server) is not yet implemented — manifest is informational until a later v1.1 story.`);
112
+ }
113
+ return {
114
+ host: 'claude-code',
115
+ targetRoot,
116
+ files,
117
+ mcpSnippetPath,
118
+ notes
119
+ };
120
+ }
121
+ /**
122
+ * Story 9.3 — Real implementation for the `gemini-cli` host.
123
+ *
124
+ * Mirrors `installForClaudeCode` exactly, swapping `.claude/` for
125
+ * `.gemini/` and the source template directory for
126
+ * `dist-templates/gemini-cli/`. Same uninstall pattern.
127
+ */
128
+ installForGeminiCli(options) {
129
+ return this.installForHost('gemini-cli', '.gemini', options);
130
+ }
131
+ /**
132
+ * Story 9.4 — Real implementation for the `codex` host.
133
+ *
134
+ * Mirrors `installForClaudeCode`, swapping `.claude/` for `.codex/`
135
+ * and template root for `dist-templates/codex/`.
136
+ */
137
+ installForCodex(options) {
138
+ return this.installForHost('codex', '.codex', options);
139
+ }
140
+ /**
141
+ * Shared implementation extracted so gemini-cli and codex don't drift
142
+ * from the claude-code pattern. Same shape as installForClaudeCode.
143
+ */
144
+ installForHost(host, hostDirName, options) {
145
+ const targetRoot = options.targetRoot;
146
+ const sourceRoot = path.join(this.templatesRoot, host);
147
+ if (!fs.existsSync(sourceRoot)) {
148
+ throw new Error(`DIST_TEMPLATES_MISSING: expected templates at ${sourceRoot}. ` +
149
+ `Run "npm run build" or reinstall @open-life/cli.`);
150
+ }
151
+ const files = [];
152
+ const notes = [];
153
+ // 1. Agents → <root>/<hostDir>/agents/openlife-*.md
154
+ const agentsSrc = path.join(sourceRoot, 'agents');
155
+ if (fs.existsSync(agentsSrc)) {
156
+ const agentsDst = path.join(targetRoot, hostDirName, 'agents');
157
+ files.push(...this.copyDir(agentsSrc, agentsDst));
158
+ }
159
+ // 2. Slash commands → <root>/<hostDir>/commands/openlife/*.md
160
+ const commandsSrc = path.join(sourceRoot, 'commands', 'openlife');
161
+ if (fs.existsSync(commandsSrc)) {
162
+ const commandsDst = path.join(targetRoot, hostDirName, 'commands', 'openlife');
163
+ files.push(...this.copyDir(commandsSrc, commandsDst));
164
+ }
165
+ // 3. MCP manifest staged for manual merge
166
+ const mcpSrc = path.join(sourceRoot, 'mcp', 'openlife-orchestrator.json');
167
+ let mcpSnippetPath;
168
+ if (fs.existsSync(mcpSrc)) {
169
+ const stateDir = path.join(targetRoot, '.openlife');
170
+ if (!fs.existsSync(stateDir))
171
+ fs.mkdirSync(stateDir, { recursive: true });
172
+ mcpSnippetPath = path.join(stateDir, `install-mcp-snippet-${host}.json`);
173
+ const action = this.copyFile(mcpSrc, mcpSnippetPath);
174
+ files.push(action);
175
+ notes.push(`MCP manifest staged at ${mcpSnippetPath}. ` +
176
+ `To enable, merge its "mcpServers" entry into the ${host} configuration file.`);
177
+ }
178
+ return {
179
+ host,
180
+ targetRoot,
181
+ files,
182
+ mcpSnippetPath,
183
+ notes
184
+ };
185
+ }
186
+ // --- Story 3.4: reversible uninstall ---
187
+ /**
188
+ * Dispatch on validated Host for uninstall. Throws HostNotYetSupportedError for hosts
189
+ * without an uninstaller (currently only claude-code is supported, mirroring install).
190
+ */
191
+ uninstall(host, options) {
192
+ switch (host) {
193
+ case 'claude-code':
194
+ return this.uninstallForClaudeCode(options);
195
+ case 'gemini-cli':
196
+ return this.uninstallForGeminiCli(options);
197
+ case 'codex':
198
+ return this.uninstallForCodex(options);
199
+ default:
200
+ throw new HostNotYetSupportedError(host);
201
+ }
202
+ }
203
+ uninstallForClaudeCode(options) {
204
+ const targetRoot = options.targetRoot;
205
+ const files = [];
206
+ const notes = [];
207
+ // 1. Agents — remove only files prefixed with "openlife-" (user files untouched).
208
+ // If a .bak exists next to it, the user had edited the file before reinstall:
209
+ // restore the .bak by renaming it back over the destination.
210
+ const agentsDir = path.join(targetRoot, '.claude', 'agents');
211
+ if (fs.existsSync(agentsDir)) {
212
+ // Snapshot entries first — removeFileWithBakRestore mutates the directory
213
+ // (rename .bak → base) which could race with a live readdirSync iterator.
214
+ // Skip .bak entries: they're handled implicitly when we process the base file.
215
+ const entries = fs.readdirSync(agentsDir);
216
+ for (const entry of entries) {
217
+ if (!entry.startsWith('openlife-'))
218
+ continue;
219
+ if (entry.endsWith('.bak'))
220
+ continue;
221
+ const dst = path.join(agentsDir, entry);
222
+ if (!fs.existsSync(dst))
223
+ continue;
224
+ const stat = fs.statSync(dst);
225
+ if (!stat.isFile())
226
+ continue;
227
+ files.push(this.removeFileWithBakRestore(dst));
228
+ }
229
+ }
230
+ else {
231
+ files.push({ destination: agentsDir, action: 'skipped-not-found' });
232
+ }
233
+ // 2. Commands namespace — the whole .claude/commands/openlife/ directory is ours.
234
+ // Iterate files (.bak restore applies the same way), then rmdir the now-empty dir.
235
+ const commandsDir = path.join(targetRoot, '.claude', 'commands', 'openlife');
236
+ if (fs.existsSync(commandsDir)) {
237
+ const entries = fs.readdirSync(commandsDir);
238
+ // Remove .md files first (handle .bak restore), .bak entries are handled by removeFileWithBakRestore
239
+ // when it processes the matching .md file. Any orphan files left after .md pass also get removed.
240
+ const handled = new Set();
241
+ for (const entry of entries) {
242
+ if (entry.endsWith('.bak'))
243
+ continue; // handled via base file
244
+ const dst = path.join(commandsDir, entry);
245
+ const stat = fs.statSync(dst);
246
+ if (!stat.isFile())
247
+ continue;
248
+ files.push(this.removeFileWithBakRestore(dst));
249
+ handled.add(entry);
250
+ }
251
+ // Now sweep any remaining files (orphan .bak entries whose .md was already gone — rare).
252
+ for (const entry of fs.readdirSync(commandsDir)) {
253
+ if (handled.has(entry))
254
+ continue;
255
+ const dst = path.join(commandsDir, entry);
256
+ const stat = fs.statSync(dst);
257
+ if (!stat.isFile())
258
+ continue;
259
+ fs.unlinkSync(dst);
260
+ files.push({ destination: dst, action: 'removed' });
261
+ }
262
+ // Only rmdir if empty (after .bak restore there may still be user-edited files left).
263
+ const remaining = fs.readdirSync(commandsDir);
264
+ if (remaining.length === 0) {
265
+ fs.rmdirSync(commandsDir);
266
+ notes.push(`Removed empty namespace directory: ${commandsDir}`);
267
+ }
268
+ else {
269
+ notes.push(`Kept ${commandsDir} — still contains ${remaining.length} file(s) ` +
270
+ `(restored user edits or unexpected entries).`);
271
+ }
272
+ }
273
+ else {
274
+ files.push({ destination: commandsDir, action: 'skipped-not-found' });
275
+ }
276
+ // 3. MCP snippet — single file in .openlife/. Do NOT remove .openlife/ itself
277
+ // (it holds runtime state: governance consents, mission state, etc.).
278
+ const mcpSnippet = path.join(targetRoot, '.openlife', 'install-mcp-snippet.json');
279
+ if (fs.existsSync(mcpSnippet)) {
280
+ fs.unlinkSync(mcpSnippet);
281
+ files.push({ destination: mcpSnippet, action: 'removed' });
282
+ }
283
+ else {
284
+ files.push({ destination: mcpSnippet, action: 'skipped-not-found' });
285
+ }
286
+ notes.push(`.openlife/ runtime state directory intentionally preserved (governance consents, mission state, etc.). ` +
287
+ `Use a future --purge flag to remove it.`);
288
+ return {
289
+ host: 'claude-code',
290
+ targetRoot,
291
+ files,
292
+ notes
293
+ };
294
+ }
295
+ /** Story 9.3 uninstall — mirrors uninstallForClaudeCode for `.gemini/`. */
296
+ uninstallForGeminiCli(options) {
297
+ return this.uninstallForHost('gemini-cli', '.gemini', options);
298
+ }
299
+ /** Story 9.4 uninstall — mirrors uninstallForClaudeCode for `.codex/`. */
300
+ uninstallForCodex(options) {
301
+ return this.uninstallForHost('codex', '.codex', options);
302
+ }
303
+ uninstallForHost(host, hostDirName, options) {
304
+ const targetRoot = options.targetRoot;
305
+ const files = [];
306
+ const notes = [];
307
+ // 1. Agents — only files prefixed with "openlife-".
308
+ const agentsDir = path.join(targetRoot, hostDirName, 'agents');
309
+ if (fs.existsSync(agentsDir)) {
310
+ const entries = fs.readdirSync(agentsDir);
311
+ for (const entry of entries) {
312
+ if (!entry.startsWith('openlife-'))
313
+ continue;
314
+ if (entry.endsWith('.bak'))
315
+ continue;
316
+ const dst = path.join(agentsDir, entry);
317
+ if (!fs.existsSync(dst))
318
+ continue;
319
+ const stat = fs.statSync(dst);
320
+ if (!stat.isFile())
321
+ continue;
322
+ files.push(this.removeFileWithBakRestore(dst));
323
+ }
324
+ }
325
+ else {
326
+ files.push({ destination: agentsDir, action: 'skipped-not-found' });
327
+ }
328
+ // 2. Commands namespace.
329
+ const commandsDir = path.join(targetRoot, hostDirName, 'commands', 'openlife');
330
+ if (fs.existsSync(commandsDir)) {
331
+ const entries = fs.readdirSync(commandsDir);
332
+ const handled = new Set();
333
+ for (const entry of entries) {
334
+ if (entry.endsWith('.bak'))
335
+ continue;
336
+ const dst = path.join(commandsDir, entry);
337
+ const stat = fs.statSync(dst);
338
+ if (!stat.isFile())
339
+ continue;
340
+ files.push(this.removeFileWithBakRestore(dst));
341
+ handled.add(entry);
342
+ }
343
+ const remaining = fs.readdirSync(commandsDir);
344
+ if (remaining.length === 0) {
345
+ fs.rmdirSync(commandsDir);
346
+ notes.push(`Removed empty namespace directory: ${commandsDir}`);
347
+ }
348
+ else {
349
+ notes.push(`Kept ${commandsDir} — still contains ${remaining.length} file(s).`);
350
+ }
351
+ }
352
+ else {
353
+ files.push({ destination: commandsDir, action: 'skipped-not-found' });
354
+ }
355
+ // 3. MCP snippet (host-specific name).
356
+ const mcpSnippet = path.join(targetRoot, '.openlife', `install-mcp-snippet-${host}.json`);
357
+ if (fs.existsSync(mcpSnippet)) {
358
+ fs.unlinkSync(mcpSnippet);
359
+ files.push({ destination: mcpSnippet, action: 'removed' });
360
+ }
361
+ else {
362
+ files.push({ destination: mcpSnippet, action: 'skipped-not-found' });
363
+ }
364
+ notes.push('.openlife/ runtime state directory intentionally preserved.');
365
+ return { host, targetRoot, files, notes };
366
+ }
367
+ // --- file ops (private) ---
368
+ copyDir(src, dst) {
369
+ if (!fs.existsSync(src)) {
370
+ return [{ source: src, destination: dst, action: 'skipped-not-found' }];
371
+ }
372
+ if (!fs.existsSync(dst))
373
+ fs.mkdirSync(dst, { recursive: true });
374
+ const actions = [];
375
+ for (const entry of fs.readdirSync(src)) {
376
+ const srcFile = path.join(src, entry);
377
+ const dstFile = path.join(dst, entry);
378
+ const stat = fs.statSync(srcFile);
379
+ if (stat.isFile()) {
380
+ actions.push(this.copyFile(srcFile, dstFile));
381
+ }
382
+ // Subdirs intentionally not recursed at this layer — host layouts are flat-by-design.
383
+ }
384
+ return actions;
385
+ }
386
+ /**
387
+ * Story 3.4 — Remove a file installed by Story 3.3, restoring the user's edit
388
+ * from .bak if one exists. Returns the action descriptor for the result envelope.
389
+ *
390
+ * Behavior:
391
+ * - dst exists, dst.bak exists: rename dst.bak → dst (user's edit survives), action='restored-from-bak'
392
+ * - dst exists, no .bak: unlink dst, action='removed'
393
+ * - dst missing: action='skipped-not-found'
394
+ */
395
+ removeFileWithBakRestore(dst) {
396
+ if (!fs.existsSync(dst)) {
397
+ return { destination: dst, action: 'skipped-not-found' };
398
+ }
399
+ const backupPath = `${dst}.bak`;
400
+ if (fs.existsSync(backupPath)) {
401
+ // Restore user's edit. fs.renameSync overwrites the target atomically on POSIX/NTFS.
402
+ fs.unlinkSync(dst);
403
+ fs.renameSync(backupPath, dst);
404
+ return { destination: dst, action: 'restored-from-bak', backupPath };
405
+ }
406
+ fs.unlinkSync(dst);
407
+ return { destination: dst, action: 'removed' };
408
+ }
409
+ copyFile(src, dst) {
410
+ const srcContent = fs.readFileSync(src, 'utf-8');
411
+ if (!fs.existsSync(dst)) {
412
+ fs.writeFileSync(dst, srcContent, 'utf-8');
413
+ return { source: src, destination: dst, action: 'created' };
414
+ }
415
+ const existing = fs.readFileSync(dst, 'utf-8');
416
+ if (existing === srcContent) {
417
+ return { source: src, destination: dst, action: 'skipped-identical' };
418
+ }
419
+ // Different content — back up the existing file before overwriting.
420
+ const backupPath = `${dst}.bak`;
421
+ fs.writeFileSync(backupPath, existing, 'utf-8');
422
+ fs.writeFileSync(dst, srcContent, 'utf-8');
423
+ return { source: src, destination: dst, action: 'updated', backupPath };
424
+ }
425
+ }
426
+ exports.HostInstaller = HostInstaller;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.installationBanner = installationBanner;
4
+ function installationBanner() {
5
+ const purple = '\x1b[1;95m';
6
+ const reset = '\x1b[0m';
7
+ const title = [
8
+ '██████╗ ██████╗ ███████╗███╗ ██╗██╗ ██╗███████╗███████╗',
9
+ '██╔═══██╗██╔══██╗██╔════╝████╗ ██║██║ ██║██╔════╝██╔════╝',
10
+ '██║ ██║██████╔╝█████╗ ██╔██╗ ██║██║ ██║█████╗ █████╗ ',
11
+ '██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║██║ ██║██╔══╝ ██╔══╝ ',
12
+ '╚██████╔╝██║ ███████╗██║ ╚████║███████╗██║██║ ███████╗',
13
+ ' ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝╚══════╝╚═╝╚═╝ ╚══════╝'
14
+ ].join('\n');
15
+ return `${purple}${title}${reset}`;
16
+ }