@amoree-code/ocean 0.0.0-stage → 1.1.0

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 (304) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +284 -2
  3. package/dist/application/auth/auth-orchestrator.js +77 -0
  4. package/dist/application/clients/clients.js +646 -0
  5. package/dist/application/clients/editors.js +398 -0
  6. package/dist/application/clients/hooks.js +335 -0
  7. package/dist/application/clients/native.js +410 -0
  8. package/dist/application/clients/opencode-plugin.js +158 -0
  9. package/dist/application/clients/registry.js +188 -0
  10. package/dist/application/gateway/webhook-gateway.js +137 -0
  11. package/dist/application/install/provider-installer.js +184 -0
  12. package/dist/application/integrations/charter-copies.js +76 -0
  13. package/dist/application/integrations/claude-vscode.js +106 -0
  14. package/dist/application/integrations/engine-entry-repair.js +105 -0
  15. package/dist/application/integrations/skill-filter.js +254 -0
  16. package/dist/application/layout/layout-apply.js +443 -0
  17. package/dist/application/layout/layout-plan.js +236 -0
  18. package/dist/application/layout/workspace-template.js +34 -0
  19. package/dist/application/onboarding/state.js +23 -0
  20. package/dist/application/onboarding/steps.js +249 -0
  21. package/dist/application/profiles/profile-distribution.js +53 -0
  22. package/dist/application/profiles/profile-suggestion.js +39 -0
  23. package/dist/application/profiles/profile-upgrade-service.js +208 -0
  24. package/dist/application/pull/history-index.js +476 -0
  25. package/dist/application/pull/project-match.js +132 -0
  26. package/dist/application/pull/pull.js +202 -0
  27. package/dist/application/pull/server-capture.js +307 -0
  28. package/dist/application/scheduler/local-scheduler.js +210 -0
  29. package/dist/composition/runtime.js +64 -0
  30. package/dist/engine-root.js +9 -0
  31. package/dist/infrastructure/filesystem/profile-loader.js +46 -0
  32. package/dist/infrastructure/filesystem/runtime-config-loader.js +29 -0
  33. package/dist/infrastructure/filesystem/skill-loader.js +84 -0
  34. package/dist/infrastructure/filesystem/workspace-capability.js +37 -0
  35. package/dist/infrastructure/observability/runtime-logger.js +16 -0
  36. package/dist/infrastructure/process/agent-tool-executor.js +99 -0
  37. package/dist/infrastructure/process/cli-process.js +49 -0
  38. package/dist/infrastructure/process/interactive-process.js +145 -0
  39. package/dist/infrastructure/process/process-supervisor.js +194 -0
  40. package/dist/infrastructure/process/service.js +252 -0
  41. package/dist/infrastructure/providers/browser-provider.js +2 -0
  42. package/dist/infrastructure/providers/claude-sdk.js +137 -0
  43. package/dist/infrastructure/providers/client-home.js +14 -0
  44. package/dist/infrastructure/providers/fake-browser-provider.js +146 -0
  45. package/dist/infrastructure/providers/ollama-embedder.js +74 -0
  46. package/dist/infrastructure/providers/openai-compatible.js +268 -0
  47. package/dist/infrastructure/providers/playwright-browser-provider.js +380 -0
  48. package/dist/infrastructure/providers/provider-capabilities.js +50 -0
  49. package/dist/infrastructure/providers/provider-invocation.js +184 -0
  50. package/dist/infrastructure/providers/provider-registry.js +77 -0
  51. package/dist/infrastructure/providers/providers.js +134 -0
  52. package/dist/infrastructure/wrappers/wrapper-manager.js +374 -0
  53. package/dist/interfaces/cli/auth-command.js +54 -0
  54. package/dist/interfaces/cli/browser-bridge-command.js +93 -0
  55. package/dist/interfaces/cli/browser-command.js +119 -0
  56. package/dist/interfaces/cli/capture-command.js +125 -0
  57. package/dist/interfaces/cli/client-test-command.js +133 -0
  58. package/dist/interfaces/cli/clients-command.js +129 -0
  59. package/dist/interfaces/cli/command-registry.js +1211 -0
  60. package/dist/interfaces/cli/context-command.js +172 -0
  61. package/dist/interfaces/cli/daily-command.js +131 -0
  62. package/dist/interfaces/cli/governance-command.js +55 -0
  63. package/dist/interfaces/cli/handoff-command.js +35 -0
  64. package/dist/interfaces/cli/help-command.js +207 -0
  65. package/dist/interfaces/cli/idea-command.js +47 -0
  66. package/dist/interfaces/cli/intercept-command.js +317 -0
  67. package/dist/interfaces/cli/layout-command.js +27 -0
  68. package/dist/interfaces/cli/market-command.js +52 -0
  69. package/dist/interfaces/cli/mcp-gateway-command.js +30 -0
  70. package/dist/interfaces/cli/memory-command.js +317 -0
  71. package/dist/interfaces/cli/migrate-command.js +26 -0
  72. package/dist/interfaces/cli/observe-command.js +78 -0
  73. package/dist/interfaces/cli/onboard-command.js +123 -0
  74. package/dist/interfaces/cli/operate-command.js +59 -0
  75. package/dist/interfaces/cli/profiles-command.js +70 -0
  76. package/dist/interfaces/cli/pull-command.js +54 -0
  77. package/dist/interfaces/cli/setup-command.js +143 -0
  78. package/dist/interfaces/cli/tasks-command.js +249 -0
  79. package/dist/main.js +49 -0
  80. package/dist/node-warnings.js +17 -0
  81. package/dist/version.js +8 -0
  82. package/market/mcp/chrome-devtools/ocean.capability.json +28 -0
  83. package/market/mcp/gateway/ocean.capability.json +21 -0
  84. package/market/mcp/obsidian/ocean.capability.json +21 -0
  85. package/market/mcp/ocean/ocean.capability.json +21 -0
  86. package/market/mcp/playwright/ocean.capability.json +23 -0
  87. package/node_modules/@ocean/brain/dist/brain/brain-eval.js +29 -0
  88. package/node_modules/@ocean/brain/dist/brain/brain-markdown.js +226 -0
  89. package/node_modules/@ocean/brain/dist/brain/brain-reindex.js +247 -0
  90. package/node_modules/@ocean/brain/dist/brain/brain-service.js +320 -0
  91. package/node_modules/@ocean/brain/dist/capture/inbox-sync.js +22 -0
  92. package/node_modules/@ocean/brain/dist/evidence/verification-report.js +13 -0
  93. package/node_modules/@ocean/brain/dist/infrastructure/brain/brain-index.js +285 -0
  94. package/node_modules/@ocean/brain/dist/memory/brain-dump.js +145 -0
  95. package/node_modules/@ocean/brain/dist/memory/daily-narrative.js +142 -0
  96. package/node_modules/@ocean/brain/dist/memory/index-sync.js +124 -0
  97. package/node_modules/@ocean/brain/dist/memory/lesson-activation.js +93 -0
  98. package/node_modules/@ocean/brain/dist/memory/lesson-learning.js +188 -0
  99. package/node_modules/@ocean/brain/dist/memory/lessons.js +321 -0
  100. package/node_modules/@ocean/brain/dist/memory/memory-audit.js +100 -0
  101. package/node_modules/@ocean/brain/dist/memory/memory-digest.js +49 -0
  102. package/node_modules/@ocean/brain/dist/memory/memory-harvest.js +345 -0
  103. package/node_modules/@ocean/brain/dist/memory/memory-paths.js +174 -0
  104. package/node_modules/@ocean/brain/dist/memory/memory-review.js +278 -0
  105. package/node_modules/@ocean/brain/dist/memory/memory-trash.js +152 -0
  106. package/node_modules/@ocean/brain/dist/memory/memory-write.js +216 -0
  107. package/node_modules/@ocean/brain/dist/memory/model-narrative.js +129 -0
  108. package/node_modules/@ocean/brain/dist/memory/profile-facts.js +103 -0
  109. package/node_modules/@ocean/brain/dist/memory/session-promotion.js +61 -0
  110. package/node_modules/@ocean/brain/dist/memory/session-summary.js +113 -0
  111. package/node_modules/@ocean/brain/dist/memory/signal-detection.js +66 -0
  112. package/node_modules/@ocean/brain/package.json +11 -0
  113. package/node_modules/@ocean/context/dist/context/context-compression.js +66 -0
  114. package/node_modules/@ocean/context/dist/context/context-cost.js +587 -0
  115. package/node_modules/@ocean/context/dist/context/context-ladder.js +363 -0
  116. package/node_modules/@ocean/context/dist/context/context-packet.js +213 -0
  117. package/node_modules/@ocean/context/dist/context/context-references.js +255 -0
  118. package/node_modules/@ocean/context/dist/context/intent-router.js +259 -0
  119. package/node_modules/@ocean/context/dist/context/resource-injection.js +36 -0
  120. package/node_modules/@ocean/context/package.json +11 -0
  121. package/node_modules/@ocean/core/dist/domain/brain/brain-record.js +22 -0
  122. package/node_modules/@ocean/core/dist/domain/brain/record-scope.js +22 -0
  123. package/node_modules/@ocean/core/dist/domain/capabilities/browser-contract.js +64 -0
  124. package/node_modules/@ocean/core/dist/domain/capabilities/capability-contract.js +16 -0
  125. package/node_modules/@ocean/core/dist/domain/capabilities/capability-manifest.js +72 -0
  126. package/node_modules/@ocean/core/dist/domain/context/context-validator.js +5 -0
  127. package/node_modules/@ocean/core/dist/domain/context/context.js +34 -0
  128. package/node_modules/@ocean/core/dist/domain/context/project-id.js +30 -0
  129. package/node_modules/@ocean/core/dist/domain/evidence/evidence.js +16 -0
  130. package/node_modules/@ocean/core/dist/domain/mcp/mcp-contract.js +36 -0
  131. package/node_modules/@ocean/core/dist/domain/mcp/memory-contract.js +41 -0
  132. package/node_modules/@ocean/core/dist/domain/ports/brain-index-port.js +7 -0
  133. package/node_modules/@ocean/core/dist/domain/ports/browser-port.js +8 -0
  134. package/node_modules/@ocean/core/dist/domain/ports/embedder-port.js +2 -0
  135. package/node_modules/@ocean/core/dist/domain/ports/platform-ports.js +2 -0
  136. package/node_modules/@ocean/core/dist/domain/ports/runtime-ports.js +2 -0
  137. package/node_modules/@ocean/core/dist/domain/ports/session-store-port.js +2 -0
  138. package/node_modules/@ocean/core/dist/domain/process/process-events.js +5 -0
  139. package/node_modules/@ocean/core/dist/domain/profiles/profile-distribution.js +19 -0
  140. package/node_modules/@ocean/core/dist/domain/profiles/profile-policy.js +34 -0
  141. package/node_modules/@ocean/core/dist/domain/profiles/profile-selection.js +73 -0
  142. package/node_modules/@ocean/core/dist/domain/profiles/profile-upgrade.js +123 -0
  143. package/node_modules/@ocean/core/dist/domain/profiles/profile-validator.js +5 -0
  144. package/node_modules/@ocean/core/dist/domain/profiles/profile.js +218 -0
  145. package/node_modules/@ocean/core/dist/domain/profiles/runtime-config.js +30 -0
  146. package/node_modules/@ocean/core/dist/domain/providers/provider-capability.js +28 -0
  147. package/node_modules/@ocean/core/dist/domain/providers/provider.js +2 -0
  148. package/node_modules/@ocean/core/dist/domain/redaction/redaction.js +86 -0
  149. package/node_modules/@ocean/core/dist/domain/runs/agent-tools.js +92 -0
  150. package/node_modules/@ocean/core/dist/domain/runs/execution-plan.js +71 -0
  151. package/node_modules/@ocean/core/dist/domain/runs/run-contract.js +38 -0
  152. package/node_modules/@ocean/core/dist/domain/sessions/entry-contract.js +31 -0
  153. package/node_modules/@ocean/core/dist/domain/sessions/handoff.js +78 -0
  154. package/node_modules/@ocean/core/dist/domain/sessions/session.js +58 -0
  155. package/node_modules/@ocean/core/dist/domain/skills/default-skills.js +29 -0
  156. package/node_modules/@ocean/core/dist/domain/skills/skill-validator.js +5 -0
  157. package/node_modules/@ocean/core/dist/domain/skills/skill.js +11 -0
  158. package/node_modules/@ocean/core/dist/domain/tasks/task-id.js +85 -0
  159. package/node_modules/@ocean/core/dist/shared/fs-utils.js +212 -0
  160. package/node_modules/@ocean/core/dist/shared/local-date.js +16 -0
  161. package/node_modules/@ocean/core/dist/shared/paths.js +324 -0
  162. package/node_modules/@ocean/core/dist/shared/project-resolution.js +1065 -0
  163. package/node_modules/@ocean/core/dist/shared/task-reference.js +133 -0
  164. package/node_modules/@ocean/core/package.json +14 -0
  165. package/node_modules/@ocean/loop/dist/handoff/handoff-service.js +133 -0
  166. package/node_modules/@ocean/loop/dist/hooks/lifecycle-hooks.js +15 -0
  167. package/node_modules/@ocean/loop/dist/hooks/session-end-hook.js +183 -0
  168. package/node_modules/@ocean/loop/dist/hooks/session-start-hook.js +237 -0
  169. package/node_modules/@ocean/loop/dist/infrastructure/persistence/session-store.js +690 -0
  170. package/node_modules/@ocean/loop/dist/infrastructure/persistence/session-validator.js +5 -0
  171. package/node_modules/@ocean/loop/dist/loops/iteration-graph.js +147 -0
  172. package/node_modules/@ocean/loop/dist/loops/task-loop-record.js +2 -0
  173. package/node_modules/@ocean/loop/dist/loops/task-loop.js +281 -0
  174. package/node_modules/@ocean/loop/dist/operations/memory-knowledge-operations.js +263 -0
  175. package/node_modules/@ocean/loop/dist/operations/operation-contract.js +227 -0
  176. package/node_modules/@ocean/loop/dist/operations/operation-scope.js +28 -0
  177. package/node_modules/@ocean/loop/dist/operations/project-operations.js +93 -0
  178. package/node_modules/@ocean/loop/dist/operations/record-io.js +65 -0
  179. package/node_modules/@ocean/loop/dist/operations/record-operations.js +45 -0
  180. package/node_modules/@ocean/loop/dist/operations/task-linker.js +40 -0
  181. package/node_modules/@ocean/loop/dist/operations/task-operations.js +279 -0
  182. package/node_modules/@ocean/loop/dist/operations/write-guard.js +157 -0
  183. package/node_modules/@ocean/loop/dist/runs/prompt-assembly.js +112 -0
  184. package/node_modules/@ocean/loop/dist/runs/run-agent.js +425 -0
  185. package/node_modules/@ocean/loop/dist/runs/run-authorization.js +24 -0
  186. package/node_modules/@ocean/loop/dist/runs/tool-loop.js +173 -0
  187. package/node_modules/@ocean/loop/dist/sessions/session-closeout.js +150 -0
  188. package/node_modules/@ocean/loop/dist/sessions/session-pointer.js +133 -0
  189. package/node_modules/@ocean/loop/dist/sessions/session-projects.js +26 -0
  190. package/node_modules/@ocean/loop/dist/sessions/session-retention.js +132 -0
  191. package/node_modules/@ocean/loop/dist/tasks/archive-tasks.js +210 -0
  192. package/node_modules/@ocean/loop/dist/tasks/checkpoint-task.js +31 -0
  193. package/node_modules/@ocean/loop/dist/tasks/claim-task.js +126 -0
  194. package/node_modules/@ocean/loop/dist/tasks/list-tasks.js +113 -0
  195. package/node_modules/@ocean/loop/dist/tasks/new-task.js +42 -0
  196. package/node_modules/@ocean/loop/dist/tasks/renumber-tasks.js +134 -0
  197. package/node_modules/@ocean/loop/dist/tasks/verification-readiness.js +78 -0
  198. package/node_modules/@ocean/loop/dist/tasks/verify-task.js +234 -0
  199. package/node_modules/@ocean/loop/package.json +11 -0
  200. package/node_modules/@ocean/market/dist/adapters/mcp-adapter.js +64 -0
  201. package/node_modules/@ocean/market/dist/adapters/owned-directory.js +89 -0
  202. package/node_modules/@ocean/market/dist/adapters/plugin-adapter.js +39 -0
  203. package/node_modules/@ocean/market/dist/adapters/skill-adapter.js +32 -0
  204. package/node_modules/@ocean/market/dist/capability/adapter.js +2 -0
  205. package/node_modules/@ocean/market/dist/capability/catalog.js +63 -0
  206. package/node_modules/@ocean/market/dist/capability/content-digest.js +40 -0
  207. package/node_modules/@ocean/market/dist/capability/registry.js +81 -0
  208. package/node_modules/@ocean/market/dist/install/default-marketplace.js +47 -0
  209. package/node_modules/@ocean/market/dist/install/lock.js +34 -0
  210. package/node_modules/@ocean/market/dist/install/marketplace-service.js +165 -0
  211. package/node_modules/@ocean/market/dist/mcp/browser-bridge.js +263 -0
  212. package/node_modules/@ocean/market/dist/mcp/mcp-connection.js +67 -0
  213. package/node_modules/@ocean/market/dist/mcp/mcp-gateway.js +317 -0
  214. package/node_modules/@ocean/market/dist/mcp/mcp-launch.js +102 -0
  215. package/node_modules/@ocean/market/dist/mcp/mcp-runner.js +32 -0
  216. package/node_modules/@ocean/market/dist/security/description-scan.js +45 -0
  217. package/node_modules/@ocean/market/dist/security/permissions.js +57 -0
  218. package/node_modules/@ocean/market/dist/security/sandbox.js +74 -0
  219. package/node_modules/@ocean/market/dist/skills/core-skill-sync.js +113 -0
  220. package/node_modules/@ocean/market/dist/skills/signal-detection.js +84 -0
  221. package/node_modules/@ocean/market/dist/skills/skill-curation.js +123 -0
  222. package/node_modules/@ocean/market/dist/skills/skill-hub.js +220 -0
  223. package/node_modules/@ocean/market/dist/skills/task-observer.js +165 -0
  224. package/node_modules/@ocean/market/package.json +11 -0
  225. package/node_modules/@ocean/services/dist/browser/browser-service.js +124 -0
  226. package/node_modules/@ocean/services/dist/browser/browser-session.js +287 -0
  227. package/node_modules/@ocean/services/dist/browser/browser-task-runner.js +70 -0
  228. package/node_modules/@ocean/services/dist/doctor/workspace-doctor.js +547 -0
  229. package/node_modules/@ocean/services/dist/infrastructure/mcp/call-ledger.js +114 -0
  230. package/node_modules/@ocean/services/dist/infrastructure/mcp/mcp-client.js +162 -0
  231. package/node_modules/@ocean/services/dist/infrastructure/mcp/obsidian-server.js +251 -0
  232. package/node_modules/@ocean/services/dist/infrastructure/mcp/ocean-server.js +880 -0
  233. package/node_modules/@ocean/services/dist/infrastructure/mcp/server-version.js +20 -0
  234. package/node_modules/@ocean/services/dist/infrastructure/mcp/tool-registry.js +29 -0
  235. package/node_modules/@ocean/services/dist/obsidian/conflict-log.js +68 -0
  236. package/node_modules/@ocean/services/dist/obsidian/inbox-promotion.js +80 -0
  237. package/node_modules/@ocean/services/dist/obsidian/vault-discovery.js +113 -0
  238. package/node_modules/@ocean/services/dist/obsidian/vault-ingestion.js +77 -0
  239. package/node_modules/@ocean/services/dist/obsidian/vault-sync.js +73 -0
  240. package/node_modules/@ocean/services/dist/obsidian/vault-writer.js +75 -0
  241. package/node_modules/@ocean/services/package.json +11 -0
  242. package/ocean-marketplace.json +415 -0
  243. package/package.json +67 -4
  244. package/skills/core/business-logic/SKILL.md +22 -0
  245. package/skills/core/catch-up/SKILL.md +17 -0
  246. package/skills/core/core-thinking/SKILL.md +11 -0
  247. package/skills/core/design-thinking/SKILL.md +19 -0
  248. package/skills/core/graft/SKILL.md +156 -0
  249. package/skills/core/loop/SKILL.md +20 -0
  250. package/skills/core/session-handoff/SKILL.md +15 -0
  251. package/skills/core/use-browser/SKILL.md +69 -0
  252. package/skills/core/verification/SKILL.md +11 -0
  253. package/skills/index.json +56 -0
  254. package/templates/README.md +4 -0
  255. package/templates/profiles/default.json +51 -0
  256. package/templates/profiles/developer.json +51 -0
  257. package/templates/profiles/reviewer.json +51 -0
  258. package/templates/profiles/strategist.json +51 -0
  259. package/templates/workspace/00-inbox/INBOX.md +7 -0
  260. package/templates/workspace/00-inbox/candidates/.gitkeep +0 -0
  261. package/templates/workspace/00-inbox/native/.gitkeep +0 -0
  262. package/templates/workspace/01-daily/.gitkeep +0 -0
  263. package/templates/workspace/02-personal/CONFLICTS.md +7 -0
  264. package/templates/workspace/02-personal/MEMORY.md +15 -0
  265. package/templates/workspace/02-personal/goals/.gitkeep +0 -0
  266. package/templates/workspace/02-personal/identity/.gitkeep +0 -0
  267. package/templates/workspace/02-personal/preferences/.gitkeep +0 -0
  268. package/templates/workspace/03-professional/.gitkeep +0 -0
  269. package/templates/workspace/04-projects/PROJECTS.md +5 -0
  270. package/templates/workspace/04-projects/_template/docs/.gitkeep +0 -0
  271. package/templates/workspace/04-projects/_template/memory/.gitkeep +0 -0
  272. package/templates/workspace/04-projects/_template/tasks/.gitkeep +0 -0
  273. package/templates/workspace/05-knowledge/KNOWLEDGE.md +8 -0
  274. package/templates/workspace/05-knowledge/decisions/.gitkeep +0 -0
  275. package/templates/workspace/05-knowledge/lessons/.gitkeep +0 -0
  276. package/templates/workspace/06-templates/TEMPLATES.md +25 -0
  277. package/templates/workspace/06-templates/decision.md +8 -0
  278. package/templates/workspace/06-templates/intelligence.md +32 -0
  279. package/templates/workspace/06-templates/project-claude.md +48 -0
  280. package/templates/workspace/06-templates/session.md +38 -0
  281. package/templates/workspace/06-templates/task.md +42 -0
  282. package/templates/workspace/MANIFEST.json +51 -0
  283. package/templates/workspace/bridge/config/CONFIG.md +21 -0
  284. package/templates/workspace/bridge/config/runtime.json +4 -0
  285. package/templates/workspace/charter/core.md +104 -0
  286. package/templates/workspace/charter/policies/README.md +31 -0
  287. package/templates/workspace/charter/policies/claude-code-context.md +90 -0
  288. package/templates/workspace/charter/policies/concise-output.md +29 -0
  289. package/templates/workspace/charter/policies/context.md +91 -0
  290. package/templates/workspace/charter/policies/contracts/task.md +189 -0
  291. package/templates/workspace/charter/policies/git.md +60 -0
  292. package/templates/workspace/charter/policies/graph.md +47 -0
  293. package/templates/workspace/charter/policies/knowledge.md +33 -0
  294. package/templates/workspace/charter/policies/lifecycle.md +119 -0
  295. package/templates/workspace/charter/policies/memory.md +67 -0
  296. package/templates/workspace/charter/policies/minimal-change.md +43 -0
  297. package/templates/workspace/charter/policies/models.md +57 -0
  298. package/templates/workspace/charter/policies/privacy-terms.txt +3 -0
  299. package/templates/workspace/charter/policies/response.md +39 -0
  300. package/templates/workspace/charter/policies/skill-observer.md +44 -0
  301. package/templates/workspace/charter/policies/stack.md +23 -0
  302. package/templates/workspace/charter/policies/task.md +139 -0
  303. package/templates/workspace/charter/policies/verification.md +29 -0
  304. package/templates/workspace/sessions/.gitkeep +0 -0
@@ -0,0 +1,145 @@
1
+ import { mkdir, readdir, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { redactRuntimeText } from "@ocean/core/domain/redaction/redaction.js";
4
+ import { localDate, localMoment, localTime, } from "@ocean/core/shared/local-date.js";
5
+ import { INBOX_DIR, oceanPath, oceanRoot } from "@ocean/core/shared/paths.js";
6
+ import { findGitRoot } from "@ocean/core/shared/project-resolution.js";
7
+ // Same fallback title stamped on a session with no explicit title (see
8
+ // daily-narrative.ts) — never meaningful content on its own.
9
+ const GENERIC_TITLE = /^(claude|codex|hermes|kimi|gemini|copilot|kilo|antigravity|openhands) session$/i;
10
+ function safeText(value, max = 400) {
11
+ return redactRuntimeText(value).replace(/\s+/g, " ").trim().slice(0, max);
12
+ }
13
+ function isGenericContent(text) {
14
+ const trimmed = (text ?? "").trim();
15
+ return trimmed.length === 0 || GENERIC_TITLE.test(trimmed);
16
+ }
17
+ const MIN_USEFUL_SLUG_LENGTH = 3;
18
+ // ASCII-only by design: ranks a Latin-alphabet slug of the title over one
19
+ // derived from the (already ASCII) project name, and falls back to the
20
+ // session id only when both are too short to be useful — e.g. a title in a
21
+ // non-Latin script, where this strips down to nothing.
22
+ function slugify(text, maxLength = 60) {
23
+ return text
24
+ .toLowerCase()
25
+ .replace(/[^a-z0-9]+/g, "-")
26
+ .replace(/^-+|-+$/g, "")
27
+ .slice(0, maxLength)
28
+ .replace(/-+$/g, "");
29
+ }
30
+ async function uniqueFilename(directory, base, ext) {
31
+ let existing;
32
+ try {
33
+ existing = new Set(await readdir(directory));
34
+ }
35
+ catch {
36
+ existing = new Set();
37
+ }
38
+ if (!existing.has(`${base}${ext}`))
39
+ return `${base}${ext}`;
40
+ for (let suffix = 2; suffix < 1000; suffix++) {
41
+ const candidate = `${base}-${suffix}${ext}`;
42
+ if (!existing.has(candidate))
43
+ return candidate;
44
+ }
45
+ return `${base}-${Date.now()}${ext}`;
46
+ }
47
+ /**
48
+ * One human-readable Markdown file per session under brain/00-inbox/brain-dump/,
49
+ * separate from the machine-oriented kernel/bridge/sessions/summaries/ dump. Prefers
50
+ * the cheap model narrative (see model-narrative.ts) and falls back to the
51
+ * same deterministic heuristics as daily-narrative.ts when it is unavailable.
52
+ * When lesson-learning.ts already found signals for this session (corrections,
53
+ * repeated procedures, explicit decisions), they're mirrored under
54
+ * "## Signals" — the same events already surfaced in brain/01-daily/, so a
55
+ * later cross-session sweep has one place to look instead of two.
56
+ *
57
+ * Skipped for the same low-value case daily-narrative.ts skips: a generic
58
+ * title with no real (git) project behind it — nothing a human would want to
59
+ * read later.
60
+ */
61
+ export async function writeBrainDump(input) {
62
+ const { session, events, narrative, changedFiles, observations } = input;
63
+ const workLog = narrative?.workLog ??
64
+ (() => {
65
+ const objectiveEvent = events.find((event) => event.type === "user_input" || event.type === "resume_requested");
66
+ return safeText(objectiveEvent?.data ?? session.title, 200);
67
+ })();
68
+ const hasRealProject = findGitRoot(session.workingDirectory) !== null;
69
+ if (isGenericContent(workLog) && !hasRealProject)
70
+ return null;
71
+ const decision = narrative?.decision ??
72
+ events
73
+ .filter((event) => event.type === "provider_output" ||
74
+ event.type === "text" ||
75
+ event.type === "json")
76
+ .map((event) => safeText(event.data, 500))
77
+ .find((text) => /\bdecision\s*:/i.test(text));
78
+ const problem = narrative?.problem ??
79
+ events
80
+ .filter((event) => event.type === "error" || event.type === "provider_blocked")
81
+ .map((event) => safeText(event.data, 500))[0];
82
+ const nextAction = narrative?.next ?? input.nextAction ?? session.nextAction;
83
+ const hasNextAction = nextAction &&
84
+ nextAction !== "Review the summary and verify the next action.";
85
+ const started = localMoment(session.createdAt);
86
+ const time = localTime(started);
87
+ const date = localDate(started);
88
+ const project = path.basename(session.workingDirectory) || session.workingDirectory;
89
+ const status = session.status === "completed" && (input.exitCode ?? 0) === 0
90
+ ? "completed"
91
+ : "failed";
92
+ const title = isGenericContent(workLog) ? project : workLog;
93
+ const lines = [
94
+ `# ${title}`,
95
+ "",
96
+ `- Date: ${date} ${time}`,
97
+ `- Provider: ${session.provider}`,
98
+ `- Project: ${project}`,
99
+ `- Status: ${status}`,
100
+ "",
101
+ "## What happened",
102
+ "",
103
+ workLog || "No objective was captured.",
104
+ ...(decision ? ["", "## Decision", "", decision] : []),
105
+ ...(problem ? ["", "## Problem", "", problem] : []),
106
+ ...(changedFiles.length
107
+ ? [
108
+ "",
109
+ "## Files changed",
110
+ "",
111
+ ...changedFiles.map((f) => `- ${safeText(f, 240)}`),
112
+ ]
113
+ : []),
114
+ ...(hasNextAction
115
+ ? ["", "## Next", "", safeText(nextAction, 300)]
116
+ : []),
117
+ ...(observations?.length
118
+ ? [
119
+ "",
120
+ "## Signals",
121
+ "",
122
+ ...observations.map((o) => `- [${o.signalType}] ${safeText(o.summary, 300)} (confidence ${o.confidence})`),
123
+ ]
124
+ : []),
125
+ "",
126
+ "---",
127
+ "",
128
+ `Session id: ${session.sessionId} · Raw events: \`ocean session events ${session.sessionId}\``,
129
+ ];
130
+ const directory = oceanPath(INBOX_DIR, "brain-dump");
131
+ await mkdir(directory, { recursive: true });
132
+ const titleSlug = slugify(title);
133
+ const slug = titleSlug.length >= MIN_USEFUL_SLUG_LENGTH
134
+ ? titleSlug
135
+ : slugify(project).length >= MIN_USEFUL_SLUG_LENGTH
136
+ ? slugify(project)
137
+ : session.sessionId.slice(0, 8);
138
+ const filename = await uniqueFilename(directory, `${date}-${time.replace(":", "")}-${slug}`, ".md");
139
+ const file = path.join(directory, filename);
140
+ await writeFile(file, `${lines.join("\n")}\n`, "utf8");
141
+ return {
142
+ brainDumpPath: path.relative(oceanRoot(), file).split(path.sep).join("/"),
143
+ };
144
+ }
145
+ //# sourceMappingURL=brain-dump.js.map
@@ -0,0 +1,142 @@
1
+ import { mkdir, readFile, realpath } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { redactRuntimeText } from "@ocean/core/domain/redaction/redaction.js";
4
+ import { atomicWrite, withFileLock } from "@ocean/core/shared/fs-utils.js";
5
+ import { localDate } from "@ocean/core/shared/local-date.js";
6
+ import { DAILY_DIR, oceanPath } from "@ocean/core/shared/paths.js";
7
+ import { findGitRoot } from "@ocean/core/shared/project-resolution.js";
8
+ const dailyTemplate = (date) => `# Daily — ${date}\n\n## Focus\n\n## Work log\n\n## Decisions\n\n## Problems\n\n## Next\n\n## Observations\n`;
9
+ // The literal fallback title stamped on a session with no explicit title
10
+ // (see run request construction) — never meaningful content on its own.
11
+ const GENERIC_TITLE = /^claude session$/i;
12
+ function safeText(value, max = 240) {
13
+ return redactRuntimeText(value).replace(/\s+/g, " ").trim().slice(0, max);
14
+ }
15
+ function isGenericContent(text) {
16
+ const trimmed = (text ?? "").trim();
17
+ return trimmed.length === 0 || GENERIC_TITLE.test(trimmed);
18
+ }
19
+ // Markup a client wraps around a prompt (`<ide_opened_file>…</ide_opened_file>`,
20
+ // `<task-notification>…`) is not what the session was about. Client tags carry `_` or `-`,
21
+ // which HTML tag names never do, so a prompt about `<button>Save</button>` keeps its words.
22
+ const CLIENT_TAG = "[a-z][a-z0-9]*(?:[_-][a-z0-9]+)+";
23
+ function withoutClientMarkup(text) {
24
+ return text
25
+ .replace(new RegExp(`<(${CLIENT_TAG})\\b[^>]*>[\\s\\S]*?<\\/\\1>`, "gi"), " ")
26
+ .replace(new RegExp(`<\\/?${CLIENT_TAG}\\b[^>]*>`, "gi"), " ");
27
+ }
28
+ // Local wall-clock date and time, like the SessionEnd hook's own line: a UTC stamp put one
29
+ // session three hours apart in the same log, and after midnight UTC into another day's file.
30
+ function localStamp(now = new Date()) {
31
+ const pad = (value) => String(value).padStart(2, "0");
32
+ return {
33
+ date: localDate(now),
34
+ time: `${pad(now.getHours())}:${pad(now.getMinutes())}`,
35
+ };
36
+ }
37
+ function insertUnderHeading(content, heading, line) {
38
+ // A client that reports one session end twice must not log it twice.
39
+ if (content.split("\n").includes(line))
40
+ return content;
41
+ const marker = `${heading}\n`;
42
+ const index = content.indexOf(marker);
43
+ if (index < 0)
44
+ return `${content.trimEnd()}\n\n${heading}\n${line}\n`;
45
+ const insertAt = index + marker.length;
46
+ return `${content.slice(0, insertAt)}${line}\n${content.slice(insertAt)}`;
47
+ }
48
+ // Read-modify-write of today's daily file. Two sessions closing out at once would otherwise
49
+ // each write back their own copy and drop the other's lines (T-257), so it runs under the
50
+ // file lock and lands atomically.
51
+ async function updateDailyFile(update) {
52
+ const { date } = localStamp();
53
+ const directory = oceanPath(DAILY_DIR);
54
+ const file = path.join(directory, `${date}.md`);
55
+ await mkdir(directory, { recursive: true });
56
+ await withFileLock(file, async () => {
57
+ let content;
58
+ try {
59
+ content = await readFile(file, "utf8");
60
+ }
61
+ catch (error) {
62
+ // Only a missing file starts from the template: any other read failure must not
63
+ // replace a real day's log with an empty one.
64
+ if (error.code !== "ENOENT")
65
+ throw error;
66
+ content = dailyTemplate(date);
67
+ }
68
+ // A symlinked daily file keeps its link: the write goes to the real file.
69
+ const target = await realpath(file).catch(() => file);
70
+ await atomicWrite(target, update(content));
71
+ });
72
+ }
73
+ /**
74
+ * Human-readable narrative entry appended to today's
75
+ * brain/01-daily/YYYY-MM-DD.md at session closeout. A field from `narrative`
76
+ * (produced by a cheap model call — see model-narrative.ts) is used verbatim
77
+ * when present; any field it omits (including when the model call was
78
+ * skipped or failed entirely) falls back to the deterministic heuristic
79
+ * below, so this never depends on the model call succeeding.
80
+ */
81
+ export async function appendDailyNarrative(input) {
82
+ const { session, events, narrative } = input;
83
+ const inserts = [];
84
+ const { time } = localStamp();
85
+ const project = path.basename(session.workingDirectory) || session.workingDirectory;
86
+ const status = session.status === "completed" && (input.exitCode ?? 0) === 0
87
+ ? "completed"
88
+ : "failed";
89
+ const workLog = narrative?.workLog ??
90
+ (() => {
91
+ const objectiveEvent = events.find((event) => event.type === "user_input" || event.type === "resume_requested");
92
+ // A prompt that was only client markup falls back to the session's title.
93
+ const prompt = safeText(withoutClientMarkup(objectiveEvent?.data ?? ""));
94
+ return safeText(prompt || session.title, 160);
95
+ })();
96
+ // Skip an entry with nothing to say (the SessionEnd hook already notes that a session
97
+ // ended), and the doubly-useless case: only the generic placeholder title AND no real
98
+ // project (root/home session, no git repo). A generic title in a real project, or real
99
+ // content with no project, still gets logged.
100
+ const hasRealProject = findGitRoot(session.workingDirectory) !== null;
101
+ const skipWorkLog = !workLog.trim() || (isGenericContent(workLog) && !hasRealProject);
102
+ if (!skipWorkLog) {
103
+ inserts.push([
104
+ "## Work log",
105
+ `- ${time} ${session.provider} session in ${project}: ${workLog} — ${status}`,
106
+ ]);
107
+ }
108
+ const decisionLine = narrative?.decision ??
109
+ events
110
+ .filter((event) => event.type === "provider_output" ||
111
+ event.type === "text" ||
112
+ event.type === "json")
113
+ .map((event) => safeText(event.data, 500))
114
+ .find((text) => /\bdecision\s*:/i.test(text));
115
+ if (decisionLine)
116
+ inserts.push(["## Decisions", `- ${decisionLine}`]);
117
+ const problemLine = narrative?.problem ??
118
+ events
119
+ .filter((event) => event.type === "error" || event.type === "provider_blocked")
120
+ .map((event) => safeText(event.data, 500))[0];
121
+ if (problemLine)
122
+ inserts.push(["## Problems", `- ${problemLine}`]);
123
+ const nextAction = narrative?.next ?? input.nextAction ?? session.nextAction;
124
+ if (nextAction &&
125
+ nextAction !== "Review the summary and verify the next action.") {
126
+ inserts.push(["## Next", `- [${project}] ${safeText(nextAction, 240)}`]);
127
+ }
128
+ await updateDailyFile((content) => inserts.reduce((next, [heading, line]) => insertUnderHeading(next, heading, line), content));
129
+ }
130
+ /**
131
+ * Appends newly detected observations (corrections, repeated procedures,
132
+ * explicit decisions, proven verifications — see lesson-learning.ts) to
133
+ * today's brain/01-daily/YYYY-MM-DD.md, so they surface next to the
134
+ * session narrative instead of sitting only in 05-knowledge/lessons.
135
+ */
136
+ export async function appendObservations(session, observations) {
137
+ if (!observations.length)
138
+ return;
139
+ const project = path.basename(session.workingDirectory) || session.workingDirectory;
140
+ await updateDailyFile((content) => observations.reduce((next, observation) => insertUnderHeading(next, "## Observations", `- [${observation.signalType}] ${safeText(observation.summary, 300)} _(${project}, confidence ${observation.confidence})_`), content));
141
+ }
142
+ //# sourceMappingURL=daily-narrative.js.map
@@ -0,0 +1,124 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { readdir, readFile, writeFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { oceanPath, STORE_DIR } from "@ocean/core/shared/paths.js";
5
+ import { conflictsFile, lessonsDir } from "./lessons.js";
6
+ const generatedStart = "## Records (generated)";
7
+ async function markdownFiles(directory) {
8
+ const entries = await readdir(directory, { withFileTypes: true });
9
+ const files = [];
10
+ for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
11
+ if (entry.name.startsWith(".") || entry.name === "archive")
12
+ continue;
13
+ const full = path.join(directory, entry.name);
14
+ if (entry.isDirectory())
15
+ files.push(...(await markdownFiles(full)));
16
+ else if (entry.name.endsWith(".md"))
17
+ files.push(full);
18
+ }
19
+ return files;
20
+ }
21
+ function title(content, fallback) {
22
+ const frontmatter = content.match(/^---\n([\s\S]*?)\n---/m)?.[1] ?? "";
23
+ const declared = frontmatter
24
+ .match(/^(?:title|name):\s*["']?(.+?)["']?\s*$/m)?.[1]
25
+ ?.trim();
26
+ if (declared)
27
+ return declared;
28
+ const heading = content.match(/^#\s+(.+)$/m)?.[1]?.trim();
29
+ if (heading &&
30
+ !/^(decision|discovery|failure|solution|research|result|architecture)$/i.test(heading))
31
+ return heading;
32
+ const summary = content
33
+ .replace(/^---[\s\S]*?---\s*/m, "")
34
+ .split("\n")
35
+ .map((line) => line.trim())
36
+ .find((line) => line &&
37
+ !line.startsWith("#") &&
38
+ !line.startsWith("`") &&
39
+ !line.startsWith("|") &&
40
+ !line.startsWith("-"));
41
+ if (summary)
42
+ return summary.replace(/[*_`]/g, "").slice(0, 120);
43
+ return (fallback.split("/").at(-1)?.replace(/\.md$/, "").replace(/[-_]+/g, " ") ??
44
+ fallback);
45
+ }
46
+ function relativeRecord(root, file) {
47
+ return path.relative(root, file).split(path.sep).join("/");
48
+ }
49
+ function links(content) {
50
+ return new Set([...content.matchAll(/\]\(([^)#]+)(?:#[^)]+)?\)/g)].map((match) => match[1]));
51
+ }
52
+ // Lesson records are machine-managed (T-230) and found through the brain index, so the curated
53
+ // KNOWLEDGE.md neither demands nor lists them. CONFLICTS.md beside them waits on a human, so it
54
+ // stays an indexed record.
55
+ function isLessonRecord(store, file) {
56
+ if (store !== "knowledge" || file === conflictsFile())
57
+ return false;
58
+ const relative = path.relative(lessonsDir(), file);
59
+ return (relative !== "" && !relative.startsWith("..") && !path.isAbsolute(relative));
60
+ }
61
+ async function syncStore(store, apply) {
62
+ const root = oceanPath(STORE_DIR[store]);
63
+ const indexName = store === "memory" ? "MEMORY.md" : "KNOWLEDGE.md";
64
+ const index = path.join(root, indexName);
65
+ const current = await readFile(index, "utf8");
66
+ const recordFiles = (await markdownFiles(root)).filter((file) => path.basename(file) !== indexName && !isLessonRecord(store, file));
67
+ const known = links(current);
68
+ const missing = recordFiles.filter((file) => !known.has(relativeRecord(root, file)));
69
+ const broken = [];
70
+ for (const link of known) {
71
+ if (!link.startsWith("http") &&
72
+ !(await awaitedExists(path.resolve(root, link))))
73
+ broken.push(link);
74
+ }
75
+ if (!apply)
76
+ return {
77
+ store,
78
+ missing: missing.map((file) => relativeRecord(root, file)),
79
+ broken,
80
+ changed: false,
81
+ };
82
+ const generated = [
83
+ generatedStart,
84
+ "",
85
+ ...recordFiles.map((file) => {
86
+ const relative = relativeRecord(root, file);
87
+ return `- [${title(readFileSync(file, "utf8"), relative)}](${relative})`;
88
+ }),
89
+ ].join("\n");
90
+ const next = current.includes(generatedStart)
91
+ ? `${current.slice(0, current.indexOf(generatedStart)).trimEnd()}\n\n${generated}\n`
92
+ : `${current.trimEnd()}\n\n${generated}\n`;
93
+ const changed = next !== current;
94
+ if (changed)
95
+ await writeFile(index, next);
96
+ return {
97
+ store,
98
+ missing: missing.map((file) => relativeRecord(root, file)),
99
+ broken,
100
+ changed,
101
+ };
102
+ }
103
+ async function awaitedExists(file) {
104
+ try {
105
+ await readFile(file);
106
+ return true;
107
+ }
108
+ catch {
109
+ return false;
110
+ }
111
+ }
112
+ export async function syncMemoryIndexes(apply) {
113
+ return Promise.all([
114
+ syncStore("memory", apply),
115
+ syncStore("knowledge", apply),
116
+ ]);
117
+ }
118
+ export async function doctorMemoryIndexes() {
119
+ const results = await syncMemoryIndexes(false);
120
+ const missing = results.flatMap((result) => result.missing.map((file) => `${result.store}/${file}`));
121
+ const broken = results.flatMap((result) => result.broken.map((file) => `${result.store}/${file}`));
122
+ return { ok: missing.length === 0 && broken.length === 0, missing, broken };
123
+ }
124
+ //# sourceMappingURL=index-sync.js.map
@@ -0,0 +1,93 @@
1
+ import { truncateUtf8 } from "@ocean/core/shared/fs-utils.js";
2
+ import { brainSearch } from "../brain/brain-service.js";
3
+ import { effectiveConfidence, readLesson } from "./lessons.js";
4
+ // Which lessons a run starts with (T-230 P3). Candidates come from the brain index, not a
5
+ // substring match on the lesson's name; the lesson file then has the last word, so a lesson
6
+ // retired or decayed since the index was built never activates.
7
+ export const MIN_ACTIVE_CONFIDENCE = 0.2;
8
+ const LESSONS_PATH_PREFIX = "knowledge/lessons/";
9
+ const MAX_QUERY_TOKENS = 8;
10
+ const HITS_PER_TOKEN = 5;
11
+ // The index ANDs every token of a query, so a whole prompt would match nothing: each
12
+ // distinctive word is asked separately and a lesson is ranked by how many of them it answers.
13
+ const STOPWORDS = new Set("the and for you are but not can was has how why who all any its our out one see now new did let may way too via per use get about after again also because before being between could does doing from have into just like make more most other should some than that their them then there these they this those through using very want what when where which while with would your".split(" "));
14
+ export function queryTokens(prompt) {
15
+ const seen = new Set();
16
+ for (const match of prompt
17
+ .toLocaleLowerCase()
18
+ .matchAll(/[\p{L}\p{N}][\p{L}\p{N}-]{2,}/gu))
19
+ if (!STOPWORDS.has(match[0]))
20
+ seen.add(match[0]);
21
+ return [...seen]
22
+ .sort((a, b) => b.length - a.length || a.localeCompare(b))
23
+ .slice(0, MAX_QUERY_TOKENS);
24
+ }
25
+ export async function selectActiveLessons(prompt, options) {
26
+ const tokens = queryTokens(prompt);
27
+ if (!tokens.length)
28
+ return [];
29
+ const matched = new Map();
30
+ // A token whose search fails (no index built, one that predates record scopes, a transient
31
+ // lock) is skipped: with no index at all nothing activates, which is the safe default, and
32
+ // `ocean memory reindex` brings lessons back.
33
+ const results = await Promise.all(tokens.map((token) => brainSearch({
34
+ query: token,
35
+ root: options.root,
36
+ limit: HITS_PER_TOKEN,
37
+ types: ["experiential"],
38
+ pathPrefix: LESSONS_PATH_PREFIX,
39
+ scope: { project: null },
40
+ indexPort: options.indexPort,
41
+ }).catch(() => null)));
42
+ for (const result of results)
43
+ for (const hit of result?.results ?? [])
44
+ matched.set(hit.id, (matched.get(hit.id) ?? 0) + 1);
45
+ // A short prompt has few tokens to match; a long one must match more than a stray word.
46
+ const needed = tokens.length >= 3 ? 2 : 1;
47
+ const ranked = [];
48
+ for (const [id, matches] of matched) {
49
+ if (matches < needed)
50
+ continue;
51
+ // A lesson file that cannot be read is skipped: lessons are optional context and one
52
+ // bad file must not fail the run that merely matched it.
53
+ const lesson = await readLesson(id).catch(() => null);
54
+ if (lesson?.status !== "active")
55
+ continue;
56
+ const confidence = effectiveConfidence(lesson, options.now);
57
+ if (confidence < MIN_ACTIVE_CONFIDENCE)
58
+ continue;
59
+ ranked.push({ lesson, matches, confidence });
60
+ }
61
+ ranked.sort((a, b) => b.matches - a.matches ||
62
+ b.confidence - a.confidence ||
63
+ a.lesson.id.localeCompare(b.lesson.id));
64
+ const selected = [];
65
+ let bytes = 0;
66
+ for (const { lesson, confidence } of ranked) {
67
+ const remaining = options.maxBytes - bytes;
68
+ if (remaining <= 0)
69
+ break;
70
+ const ref = {
71
+ id: lesson.id,
72
+ title: lesson.title,
73
+ sourceSessionId: lesson.sourceSessionId,
74
+ confidence,
75
+ };
76
+ const size = Buffer.byteLength(lesson.body);
77
+ if (size <= remaining) {
78
+ selected.push({ ...ref, body: lesson.body, truncated: false });
79
+ bytes += size;
80
+ continue;
81
+ }
82
+ // A usable pointer: the command that prints the full lesson.
83
+ const marker = `\n[truncated to the run budget; full text: \`ocean skill list ${lesson.id}\`]`;
84
+ const markerBytes = Buffer.byteLength(marker);
85
+ if (remaining <= markerBytes)
86
+ break;
87
+ const body = `${truncateUtf8(lesson.body, remaining - markerBytes)}${marker}`;
88
+ selected.push({ ...ref, body, truncated: true });
89
+ bytes += Buffer.byteLength(body);
90
+ }
91
+ return selected;
92
+ }
93
+ //# sourceMappingURL=lesson-activation.js.map