@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,172 @@
1
+ import { stat } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { DEFAULT_CONTEXT_BUDGET, measureContextCost, } from "@ocean/context/context/context-cost.js";
4
+ import { BRAIN_RECORD_DIRS, oceanRoot, PERSONAL_DIR, PROJECTS_DIR, projectDir, SYSTEM_DIR, } from "@ocean/core/shared/paths.js";
5
+ import { projectRules, projectVerify, readProjectManifest, resolveProject, } from "@ocean/core/shared/project-resolution.js";
6
+ import { z } from "zod";
7
+ import { oceanVersion } from "../../version.js";
8
+ import { listTasks } from "./tasks-command.js";
9
+ // The MEMORY.md files a session in this project reads: the personal index, then the project's.
10
+ async function existingMemoryFiles(project) {
11
+ const candidates = [path.posix.join(PERSONAL_DIR, "MEMORY.md")];
12
+ if (project)
13
+ candidates.push(path.posix.join(projectDir(project), "MEMORY.md"));
14
+ const found = [];
15
+ for (const relative of candidates) {
16
+ try {
17
+ if ((await stat(path.join(oceanRoot(), relative))).isFile())
18
+ found.push(relative);
19
+ }
20
+ catch {
21
+ // Missing is normal.
22
+ }
23
+ }
24
+ return found;
25
+ }
26
+ export async function runContextCommand(json = false) {
27
+ const version = await oceanVersion();
28
+ const resolution = await resolveProject(process.cwd());
29
+ const project = resolution.status === "bound" ? resolution.projectId : null;
30
+ const tasks = project
31
+ ? (await listTasks(undefined, project)).filter((task) => task.state === "active" || task.state === "blocked")
32
+ : [];
33
+ // Unreadable rules are shown as such, never as an empty list.
34
+ const problems = [];
35
+ const manifest = project
36
+ ? await readProjectManifest(project).catch((error) => {
37
+ problems.push(error instanceof Error ? error.message : String(error));
38
+ return null;
39
+ })
40
+ : null;
41
+ const read = (load) => {
42
+ try {
43
+ return manifest ? load(manifest) : [];
44
+ }
45
+ catch (error) {
46
+ problems.push(error instanceof Error ? error.message : String(error));
47
+ return [];
48
+ }
49
+ };
50
+ const rules = read(projectRules);
51
+ const verify = read(projectVerify);
52
+ const context = {
53
+ project,
54
+ projectResolution: resolution,
55
+ rules,
56
+ verify,
57
+ ...(problems.length ? { problems } : {}),
58
+ version,
59
+ roots: [...BRAIN_RECORD_DIRS, PROJECTS_DIR, SYSTEM_DIR],
60
+ memory: await existingMemoryFiles(project),
61
+ tasks,
62
+ };
63
+ if (json) {
64
+ console.log(JSON.stringify(context, null, 2));
65
+ return;
66
+ }
67
+ console.log(`Ocean context\nversion: ${version}\nroots: ${[...BRAIN_RECORD_DIRS, PROJECTS_DIR, SYSTEM_DIR].join(", ")}`);
68
+ if (resolution.status !== "bound")
69
+ console.log(`project: ${resolution.status} — no Ocean binding for this directory; run 'ocean project bind <name> <path>'`);
70
+ else
71
+ console.log(`project: ${resolution.projectId} (confidence: ${resolution.confidence})`);
72
+ if (rules.length)
73
+ console.log(`rules:\n${rules.map((rule) => `- ${rule}`).join("\n")}`);
74
+ if (verify.length)
75
+ console.log(`verify:\n${verify.map((command) => `- ${command}`).join("\n")}`);
76
+ for (const problem of problems)
77
+ console.log(`unreadable: ${problem}`);
78
+ console.log(`memory: ${context.memory.join(", ") || "none"}`);
79
+ if (!tasks.length)
80
+ console.log("active tasks: none");
81
+ else
82
+ for (const task of tasks)
83
+ console.log(`${task.id} [${task.state}] ${task.title} — ${task.goal}`);
84
+ }
85
+ const costUsage = "Usage: ocean context cost [--json] [--budget <bytes>] [--project <dir>]";
86
+ const budgetSchema = z.coerce.number().int().positive();
87
+ function parseCostArgs(args) {
88
+ let json = false;
89
+ let budget = DEFAULT_CONTEXT_BUDGET;
90
+ let project = process.cwd();
91
+ for (let index = 0; index < args.length; index += 1) {
92
+ const arg = args[index];
93
+ if (arg === "--json")
94
+ json = true;
95
+ else if (arg === "--budget" || arg === "--project") {
96
+ const value = args[index + 1];
97
+ if (value === undefined || value.startsWith("--"))
98
+ return null;
99
+ index += 1;
100
+ if (arg === "--project")
101
+ project = value;
102
+ else {
103
+ const parsed = budgetSchema.safeParse(value);
104
+ if (!parsed.success)
105
+ return null;
106
+ budget = parsed.data;
107
+ }
108
+ }
109
+ else
110
+ return null;
111
+ }
112
+ return { json, budget, project: path.resolve(project) };
113
+ }
114
+ function costStatus(client) {
115
+ if (!client.skills.present &&
116
+ client.rules.every((file) => file.missing) &&
117
+ client.memory.every((file) => file.missing))
118
+ return "absent";
119
+ return client.overBudget ? "OVER" : "ok";
120
+ }
121
+ // `ocean context cost`: a read-only report of each client's always-on context bytes. Exits 0
122
+ // even when a client is over budget — it is a report, not a gate.
123
+ export async function runContextCostCommand(args) {
124
+ const options = parseCostArgs(args);
125
+ if (!options) {
126
+ console.error(costUsage);
127
+ process.exitCode = 1;
128
+ return;
129
+ }
130
+ const report = await measureContextCost({
131
+ projectDir: options.project,
132
+ budget: options.budget,
133
+ });
134
+ if (options.json) {
135
+ console.log(JSON.stringify(report, null, 2));
136
+ return;
137
+ }
138
+ const sum = (files) => files.reduce((total, file) => total + file.bytes, 0);
139
+ const header = [
140
+ "client",
141
+ "rules",
142
+ "memory",
143
+ "skills",
144
+ "skill-fm",
145
+ "skill-body",
146
+ "always-on",
147
+ "status",
148
+ ];
149
+ const rows = report.clients.map((client) => [
150
+ client.shared ? `${client.client} (shared)` : client.client,
151
+ String(sum(client.rules)),
152
+ String(sum(client.memory)),
153
+ String(client.skills.count),
154
+ String(client.skills.frontmatterBytes),
155
+ String(client.skills.bodyBytes),
156
+ String(client.alwaysOnBytes),
157
+ costStatus(client),
158
+ ]);
159
+ const widths = header.map((title, column) => Math.max(title.length, ...rows.map((row) => row[column].length)));
160
+ const format = (cells) => cells.map((cell, column) => cell.padEnd(widths[column])).join(" ");
161
+ console.log(`Always-on context by client (budget ${report.budget} bytes)`);
162
+ console.log(format(header));
163
+ report.clients.forEach((client, index) => {
164
+ console.log(format(rows[index]));
165
+ for (const file of [...client.rules, ...client.memory, ...client.extras])
166
+ console.log(` ${file.path} ${file.bytes}${file.via ? ` (via ${file.via})` : ""}${file.missing ? " missing" : ""}${file.unreadable ? " unreadable" : ""}`);
167
+ console.log(` skills: ${client.skills.root}${client.skills.present ? "" : " absent"}${client.skills.hidden ? ` (${client.skills.hidden} hidden from the model, ${client.skills.hiddenFrontmatterBytes} bytes not loaded)` : ""}`);
168
+ for (const note of client.notes)
169
+ console.log(` note: ${note}`);
170
+ });
171
+ }
172
+ //# sourceMappingURL=context-command.js.map
@@ -0,0 +1,131 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { createInterface } from "node:readline/promises";
4
+ import { listLessons, setLessonStatus } from "@ocean/brain/memory/lessons.js";
5
+ import { withFileLock } from "@ocean/core/shared/fs-utils.js";
6
+ import { localDate } from "@ocean/core/shared/local-date.js";
7
+ import { DAILY_DIR, oceanPath } from "@ocean/core/shared/paths.js";
8
+ import { openSessionStore } from "@ocean/loop/infrastructure/persistence/session-store.js";
9
+ import { listTasks } from "./tasks-command.js";
10
+ /**
11
+ * Interactive human-in-the-loop gate for candidate lessons (see lessons.ts). Only runs on a
12
+ * real TTY, so headless and scheduled invocations of `ocean daily start` never block on input.
13
+ */
14
+ const lessonGateLimit = 5;
15
+ async function runLessonGate() {
16
+ if (!(process.stdin.isTTY && process.stdout.isTTY))
17
+ return;
18
+ const allPending = await listLessons({ status: "candidate" });
19
+ if (!allPending.length)
20
+ return;
21
+ const pending = allPending.slice(-lessonGateLimit);
22
+ const prompt = createInterface({
23
+ input: process.stdin,
24
+ output: process.stdout,
25
+ });
26
+ try {
27
+ console.log(allPending.length > pending.length
28
+ ? `\n🤖 Ocean: ${pending.length} most recent of ${allPending.length} candidate lesson(s) awaiting review.`
29
+ : `\n🤖 Ocean: ${pending.length} candidate lesson(s) awaiting review.`);
30
+ for (const lesson of pending) {
31
+ console.log(`\n[${lesson.hits} verified hit(s)] ${lesson.title}`);
32
+ const answer = (await prompt.question("Activate this lesson? (y = activate, n = retire, Enter = later): "))
33
+ .trim()
34
+ .toLowerCase();
35
+ // Only an explicit answer changes anything: Enter or EOF leaves it a candidate.
36
+ if (answer !== "y" && answer !== "n") {
37
+ console.log("→ left as candidate");
38
+ continue;
39
+ }
40
+ await setLessonStatus(lesson.id, answer === "y" ? "active" : "retired");
41
+ console.log(answer === "y" ? "→ active" : "→ retired");
42
+ }
43
+ }
44
+ finally {
45
+ prompt.close();
46
+ }
47
+ }
48
+ export async function runDailyCommand(action, args) {
49
+ if (action !== "start") {
50
+ console.error("Usage: ocean daily start [--apply] [--news <bounded-news-summary>]");
51
+ process.exitCode = 1;
52
+ return;
53
+ }
54
+ await runLessonGate();
55
+ const apply = args.includes("--apply");
56
+ const newsIndex = args.indexOf("--news");
57
+ const news = newsIndex >= 0
58
+ ? args
59
+ .slice(newsIndex + 1)
60
+ .join(" ")
61
+ .slice(0, 4_000)
62
+ : "";
63
+ const tasks = await listTasks();
64
+ const store = await openSessionStore();
65
+ let sessions;
66
+ try {
67
+ sessions = store
68
+ .list()
69
+ .slice(0, 5)
70
+ .map((session) => ({
71
+ sessionId: session.sessionId,
72
+ title: session.title,
73
+ provider: session.provider,
74
+ status: session.status,
75
+ nextAction: session.nextAction,
76
+ }));
77
+ }
78
+ finally {
79
+ store.close();
80
+ }
81
+ const date = localDate();
82
+ const file = oceanPath(DAILY_DIR, `${date}.md`);
83
+ const content = `${[
84
+ `# Daily brief — ${date}`,
85
+ "",
86
+ "## Brief",
87
+ "",
88
+ tasks.length
89
+ ? tasks
90
+ .map((task) => `- ${task.id}: ${task.title} — ${task.goal}`)
91
+ .join("\n")
92
+ : "- No active tasks.",
93
+ "",
94
+ "## Check-in",
95
+ "",
96
+ sessions.length
97
+ ? sessions
98
+ .map((session) => `- ${session.sessionId}: ${session.title || session.provider} — ${session.status}${session.nextAction ? `; next: ${session.nextAction}` : ""}`)
99
+ .join("\n")
100
+ : "- No recent sessions.",
101
+ "",
102
+ "## News",
103
+ "",
104
+ news ||
105
+ "- No news supplied. The active AI client may research only the requested topics and pass a bounded summary with `--news`.",
106
+ ]
107
+ .join("\n")
108
+ .slice(0, 12_000)}\n`;
109
+ if (apply) {
110
+ await mkdir(path.dirname(file), { recursive: true });
111
+ // Same lock as the session-closeout writers: a closeout landing between the check and
112
+ // the write would otherwise be overwritten (T-257).
113
+ await withFileLock(file, async () => {
114
+ const existing = await readFile(file, "utf8").catch(() => "");
115
+ if (existing.trim())
116
+ throw new Error(`Daily file already has content: ${file}`);
117
+ await writeFile(file, content, "utf8");
118
+ });
119
+ }
120
+ console.log(JSON.stringify({
121
+ apply,
122
+ date,
123
+ file,
124
+ bytes: Buffer.byteLength(content),
125
+ tasks: tasks.length,
126
+ sessions: sessions.length,
127
+ news: Boolean(news),
128
+ content,
129
+ }, null, 2));
130
+ }
131
+ //# sourceMappingURL=daily-command.js.map
@@ -0,0 +1,55 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import { CHARTER_DIR, oceanPath, POLICIES_DIR, resolveWithin, } from "@ocean/core/shared/paths.js";
3
+ const policyRoot = () => oceanPath(POLICIES_DIR);
4
+ const rulesFile = () => oceanPath(CHARTER_DIR, "core.md");
5
+ async function policyNames() {
6
+ return (await readdir(policyRoot(), { withFileTypes: true }))
7
+ .filter((entry) => entry.isFile() &&
8
+ entry.name.endsWith(".md") &&
9
+ entry.name !== "README.md")
10
+ .map((entry) => entry.name.slice(0, -3))
11
+ .sort();
12
+ }
13
+ export async function runPolicyCommand(name = "list") {
14
+ const names = await policyNames();
15
+ if (name === "list") {
16
+ console.log(JSON.stringify({ policies: names }, null, 2));
17
+ return;
18
+ }
19
+ if (name === "doctor") {
20
+ const core = await readFile(rulesFile(), "utf8");
21
+ const referenced = new Set([...core.matchAll(/ocean policy ([a-z-]+)/g)]
22
+ .map((match) => match[1])
23
+ .filter((item) => item !== "list"));
24
+ const missing = [...referenced].filter((item) => !names.includes(item));
25
+ console.log(JSON.stringify({ ok: missing.length === 0, policies: names.length, missing }, null, 2));
26
+ if (missing.length)
27
+ process.exitCode = 1;
28
+ return;
29
+ }
30
+ if (!/^[a-z][a-z-]*$/.test(name) || !names.includes(name))
31
+ throw new Error(`Unknown policy: ${name}`);
32
+ process.stdout.write(await readFile(resolveWithin(policyRoot(), `${name}.md`), "utf8"));
33
+ }
34
+ export async function runLifecycleCommand(args) {
35
+ const taskIndex = args.indexOf("--task");
36
+ const taskId = taskIndex >= 0 ? args[taskIndex + 1] : undefined;
37
+ const verificationIndex = args.indexOf("--verification");
38
+ const verification = verificationIndex >= 0 ? args[verificationIndex + 1] : undefined;
39
+ const complete = args.includes("--complete");
40
+ const decision = complete && verification === "passed" ? "CHECKPOINT" : "CONTINUE";
41
+ const result = {
42
+ decision,
43
+ taskId: taskId ?? null,
44
+ complete,
45
+ verification: verification ?? "unknown",
46
+ reason: decision === "CHECKPOINT"
47
+ ? "completed work with passing verification must be persisted"
48
+ : "no verified completion boundary was supplied",
49
+ };
50
+ if (args.includes("--json"))
51
+ console.log(JSON.stringify(result, null, 2));
52
+ else
53
+ console.log(`${result.decision}: ${result.reason}`);
54
+ }
55
+ //# sourceMappingURL=governance-command.js.map
@@ -0,0 +1,35 @@
1
+ import { createHandoff, getHandoff, listHandoffs, } from "@ocean/loop/handoff/handoff-service.js";
2
+ import { defaultSessionStoreFactory } from "../../composition/runtime.js";
3
+ export async function runHandoffCommand(action, args) {
4
+ if (action === "create") {
5
+ const taskIndex = args.indexOf("--task");
6
+ const sessionIndex = args.indexOf("--session");
7
+ const nextIndex = args.indexOf("--next");
8
+ const providerIndex = args.indexOf("--provider");
9
+ const handoff = await createHandoff({
10
+ taskId: taskIndex >= 0 ? args[taskIndex + 1] : undefined,
11
+ sessionId: sessionIndex >= 0 ? args[sessionIndex + 1] : undefined,
12
+ nextAction: nextIndex >= 0 ? args.slice(nextIndex + 1).join(" ") : undefined,
13
+ provider: providerIndex >= 0 ? args[providerIndex + 1] : undefined,
14
+ }, defaultSessionStoreFactory);
15
+ console.log(JSON.stringify(handoff, null, 2));
16
+ return;
17
+ }
18
+ if (action === "show" || action === "context") {
19
+ const id = args[0];
20
+ if (!id)
21
+ throw new Error(`Usage: ocean handoff ${action} <handoff-id>`);
22
+ const handoff = await getHandoff(id, defaultSessionStoreFactory, action === "context" ? 8_000 : 16_000);
23
+ console.log(JSON.stringify(handoff, null, 2));
24
+ return;
25
+ }
26
+ if (action === "list") {
27
+ const taskIndex = args.indexOf("--task");
28
+ const projectIndex = args.indexOf("--project");
29
+ console.log(JSON.stringify(await listHandoffs(defaultSessionStoreFactory, taskIndex >= 0 ? args[taskIndex + 1] : undefined, projectIndex >= 0 ? args[projectIndex + 1] : undefined), null, 2));
30
+ return;
31
+ }
32
+ console.error("Usage: ocean handoff create [--task <id>] [--session <id>] [--next <action>]|show <id>|context <id>|list [--task <id>] [--project <id>]");
33
+ process.exitCode = 1;
34
+ }
35
+ //# sourceMappingURL=handoff-command.js.map
@@ -0,0 +1,207 @@
1
+ const commandGroups = [
2
+ [
3
+ "Workspace",
4
+ "setup, onboard, context, project, tasks, loop, policy, lifecycle, doctor, repair",
5
+ ],
6
+ [
7
+ "Execution",
8
+ "run, profiles, session, service, intercept, operate, intent, gateway, schedule",
9
+ ],
10
+ [
11
+ "Providers",
12
+ "client, clients, install, update, remove, auth, mcp, market, browser",
13
+ ],
14
+ [
15
+ "Knowledge",
16
+ "memory, pull, observe, capture, handoff, idea, daily, skill, catalog",
17
+ ],
18
+ ["Integrations", "obsidian, hook, migrate, layout, env"],
19
+ ];
20
+ export function renderHelp() {
21
+ const groups = commandGroups
22
+ .map(([label, commands]) => ` ${label.padEnd(12)} ${commands}`)
23
+ .join("\n");
24
+ return `Usage: ocean <command> [options]\n\nCommands:\n${groups}\n\nGlobal options:\n -h, --help Show this help\n -v, --version Show the installed version\n\nRun \`ocean <command> --help\` for one command's usage.`;
25
+ }
26
+ // One entry per command in commandRegistry (a test keeps the two in step): what it does, and
27
+ // its usage line as the command itself prints it on a bad argument.
28
+ export const commandHelp = {
29
+ setup: [
30
+ "Create the private workspace, the AI CLI shims, the shell profile entry and the login service.",
31
+ "ocean setup [--obsidian <vault-path>] [--read-write]",
32
+ ],
33
+ onboard: [
34
+ "Run the pending first-run steps; --status only shows them.",
35
+ "ocean onboard [--yes] [--status] [--reset <step>]",
36
+ ],
37
+ context: [
38
+ "Print the workspace context for the current folder, or each client's always-on context cost.",
39
+ "ocean context [--json] | cost [--json] [--budget <bytes>] [--project <dir>]",
40
+ ],
41
+ project: [
42
+ "Resolve, bind, register, rename and index projects.",
43
+ "ocean project resolve [path]|bind <name> <path> [--add]|register [path]|unbind <path>|rename <id> <new-id>|list|migrate [--write]|index [--write]",
44
+ ],
45
+ tasks: [
46
+ "List, create, claim, checkpoint, verify and complete tasks.",
47
+ "ocean tasks list [state] [--project <id>] [--pretty]|new <title> [--project <id>]|doctor [--all]|index [--write]|checkpoint <id> --note <text> [--next <text>]|verify <id>|complete <id>|claim <id> --by <name> [--paths a,b] [--force]|release <id> [--by <name>] [--force]|archive [--apply|--auto]|renumber --project <id> --prefix <PREFIX> [--write]",
48
+ ],
49
+ loop: [
50
+ "Start, inspect and stop task loops (repeated agent runs on one task).",
51
+ "ocean loop start <task-id> <profile> --prompt <text> --approve [--max-iterations N] [--interval-ms N] [--max-attempts N]|status|stop <loop-id>|worker-once|worker",
52
+ ],
53
+ policy: [
54
+ "List the charter's policies, check them, or print one.",
55
+ "ocean policy [list|doctor|<name>]",
56
+ ],
57
+ lifecycle: [
58
+ "Decide whether a unit of work should checkpoint now.",
59
+ "ocean lifecycle [--task <id>] [--verification <result>] [--complete] [--json]",
60
+ ],
61
+ doctor: [
62
+ "Check the workspace, clients and integrations; exits 1 on any FAIL.",
63
+ "ocean doctor [--json]",
64
+ ],
65
+ repair: [
66
+ "Show what doctor can fix; --apply fixes it.",
67
+ "ocean repair [--apply]",
68
+ ],
69
+ run: [
70
+ "Run a headless agent with a profile and record the session.",
71
+ "ocean run --profile <name> [--client <client>] [--task <id>] [--handoff <id>] --prompt <text>",
72
+ ],
73
+ profiles: [
74
+ "Validate, upgrade or suggest agent profiles.",
75
+ "ocean profiles validate | upgrade --check | --apply | --rollback | suggest --task <id> [--profile <name>]",
76
+ ],
77
+ session: [
78
+ "List, show, resume, promote and compact recorded sessions.",
79
+ "ocean session list|show <session-id>|summary <session-id>|events <session-id>|resume <session-id> <prompt>|promote <session-id> [knowledge/<kind>] --approve|doctor [hours] [--apply]|compact [--keep-days N] [--simulate]|compact --apply --before <iso> --plan <fingerprint>",
80
+ ],
81
+ service: [
82
+ "Run the background service in the foreground (setup's login entry starts it).",
83
+ "ocean service",
84
+ ],
85
+ intercept: [
86
+ "Run an AI CLI through Ocean's session capture (the shims call this).",
87
+ "ocean intercept --client <provider> -- [args]",
88
+ ],
89
+ operate: [
90
+ "Classify a plain-language request and run the matching Ocean operation.",
91
+ "ocean operate <text> | -- <text containing -h>",
92
+ ],
93
+ intent: [
94
+ "Classify a plain-language request without running anything.",
95
+ "ocean intent classify <text>",
96
+ ],
97
+ gateway: [
98
+ "Serve the local webhook gateway on 127.0.0.1 (needs OCEAN_GATEWAY_TOKEN).",
99
+ "ocean gateway",
100
+ ],
101
+ schedule: [
102
+ "Add, list and run scheduled agent runs.",
103
+ "ocean schedule list|add <id> <profile> <interval-ms> <prompt>|enable|disable|run-due|run-now|worker-once|worker",
104
+ ],
105
+ client: [
106
+ "Inspect, open, register and sync AI clients.",
107
+ "ocean client list|status|test [provider] [--json]|open <provider> [provider-args] [-- provider-args]|vscode-wrapper [--settings <path>] [--apply]|sync|register <id> [command]|enable <id>|disable <id>|manage|doctor [absolute-provider-path]",
108
+ ],
109
+ clients: [
110
+ "Connect installed AI clients to Ocean's MCP server and hooks; apply shows the plan until --yes.",
111
+ "ocean clients detect|plan [--json] | apply [--client <id>…] [--yes] | verify [<id>…] | confirm <id>… --label in-app|headless|connected|blocked [--via <evidence>] [--reason <why>] | ledger | repair | restore [--batch <id>]",
112
+ ],
113
+ install: [
114
+ "Install a supported AI client CLI.",
115
+ "ocean install <client> [--yes]",
116
+ ],
117
+ update: ["Update an installed AI client CLI.", "ocean update <client> --yes"],
118
+ remove: ["Remove an installed AI client CLI.", "ocean remove <client> --yes"],
119
+ auth: [
120
+ "Show or start an AI client's login.",
121
+ "ocean auth status|login <client>",
122
+ ],
123
+ mcp: [
124
+ "Print MCP client configs, or serve Ocean's MCP server and gateway.",
125
+ "ocean mcp config|playwright-config|gateway-config|browser-config|browser-bridge|browser-service install|uninstall|serve|gateway",
126
+ ],
127
+ market: [
128
+ "List, install, update and run marketplace packages; permissions need --yes.",
129
+ "ocean market list|install <name> [--version <v>]|update <name>|uninstall <name>|exec <name> [--index <file>]... [--yes] [--accept-flagged]",
130
+ ],
131
+ browser: [
132
+ "Drive a browser session; uploads and submits need --approve.",
133
+ "ocean browser detect|open|show|events|close|approve|navigate|read|observe|extract|click|type|replace-text|select|scroll|wait|upload|download|submit|run",
134
+ ],
135
+ memory: [
136
+ "Search, read, review and maintain memory records and the brain index.",
137
+ "ocean memory doctor|sync [--apply]|review [list|approve <id> [--to <path>]|reject <id>]|eval <questions.json> [--k N] [--min R]|digest|harvest [--source <id>] [--yes]|import-claude <export-dir> [--yes]|history [path] [--limit N]|restore <id> [--hash <sha256>]|delete <path> --hash <sha256>|purge [--days N] [--yes]|facts <profile> [key] [value]|facts <profile> delete <key>|reindex [--no-vectors]|search <q> [--project <id>|--all] [--json]|read <id|path>|neighbors <id|path> [--depth N] [--project <id>|--all]",
138
+ ],
139
+ pull: [
140
+ "Pull what AI clients hold into Ocean as review candidates; a dry run until --yes.",
141
+ "ocean pull [--yes] [--daily] | search [words…] [--project <id>] [--client <id>] [--limit N] [--json] | report",
142
+ ],
143
+ observe: [
144
+ "Run a command and record its output, or show a recording.",
145
+ "ocean observe -- <command> [args] | show <id> [--grep <pattern>]",
146
+ ],
147
+ capture: [
148
+ "Capture ideas and promote or discard them.",
149
+ "ocean capture add <idea>|scan [session-id]|list [status]|promote <id> <target>|discard <id>",
150
+ ],
151
+ handoff: [
152
+ "Create, show and list handoffs between sessions.",
153
+ "ocean handoff create [--task <id>] [--session <id>] [--next <action>]|show <id>|context <id>|list [--task <id>] [--project <id>]",
154
+ ],
155
+ idea: [
156
+ "Save, list, classify and discard ideas.",
157
+ "ocean idea save <title> <content> [--session <id>]|list [status]|classify <id> <target>|discard <id>",
158
+ ],
159
+ daily: [
160
+ "Prepare today's daily note; --apply writes it.",
161
+ "ocean daily start [--apply] [--news <bounded-news-summary>]",
162
+ ],
163
+ skill: [
164
+ "Sync, list, add, review and learn skills.",
165
+ "ocean skill sync|doctor|list [status|id]|observe [session-id]|add <id> <name> <instructions>|review <id> promoted|rejected|learn <session-id>|migrate",
166
+ ],
167
+ catalog: [
168
+ "List the AI clients Ocean can install, with their installers.",
169
+ "ocean catalog",
170
+ ],
171
+ obsidian: [
172
+ "Connect, sync and write to an Obsidian vault (read-only unless --read-write).",
173
+ "ocean obsidian connect <vault-path> [--read-write]|discover|sync|watch|inbox|write|conflicts resolve <id> --keep=vault|ocean",
174
+ ],
175
+ hook: [
176
+ "Session hooks the AI clients call; session-end reads its payload from stdin.",
177
+ "ocean hook session-start [--client <client>] [--repair] | session-end [--client <client>]",
178
+ ],
179
+ migrate: [
180
+ "Migrate the session store; a dry run until --apply.",
181
+ "ocean migrate [--apply]",
182
+ ],
183
+ layout: [
184
+ "Plan, apply or roll back the workspace layout move.",
185
+ "ocean layout plan | apply --yes | rollback --yes",
186
+ ],
187
+ env: [
188
+ "Print the shell line that puts Ocean's shim folder on PATH; writes nothing.",
189
+ "ocean env",
190
+ ],
191
+ };
192
+ const HELP_FLAGS = new Set(["--help", "-h"]);
193
+ // A help flag anywhere before `--` is Ocean's, for every command: `client sync --help` once ran the
194
+ // sync. Arguments after `--` belong to the wrapped program or the free text, so
195
+ // `ocean client open claude -- --help` reaches Claude.
196
+ export function wantsCommandHelp(args) {
197
+ const end = args.indexOf("--");
198
+ return (end < 0 ? args : args.slice(0, end)).some((arg) => HELP_FLAGS.has(arg));
199
+ }
200
+ export function renderCommandHelp(command) {
201
+ const [summary, usage] = commandHelp[command] ?? [
202
+ "",
203
+ `ocean ${command} [options]`,
204
+ ];
205
+ return `Usage: ${usage}\n\n${summary}`.trimEnd();
206
+ }
207
+ //# sourceMappingURL=help-command.js.map
@@ -0,0 +1,47 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { openSessionStore } from "@ocean/loop/infrastructure/persistence/session-store.js";
3
+ export async function runIdeaCommand(action, args) {
4
+ const store = await openSessionStore();
5
+ try {
6
+ if (action === "save") {
7
+ const title = args[0];
8
+ const sessionIndex = args.indexOf("--session");
9
+ const content = args
10
+ .slice(1, sessionIndex >= 0 ? sessionIndex : undefined)
11
+ .join(" ")
12
+ .trim();
13
+ if (!title || !content)
14
+ throw new Error("Usage: ocean idea save <title> <content> [--session <session-id>]");
15
+ store.saveIdea({
16
+ ideaId: `idea-${randomUUID()}`,
17
+ title,
18
+ content,
19
+ sourceSessionId: sessionIndex >= 0 ? args[sessionIndex + 1] : null,
20
+ });
21
+ console.log(JSON.stringify({ saved: true, status: "raw", title }, null, 2));
22
+ return;
23
+ }
24
+ if (action === "list") {
25
+ console.log(JSON.stringify(store.listIdeas(args[0]), null, 2));
26
+ return;
27
+ }
28
+ if (action === "classify" || action === "discard") {
29
+ const id = args[0];
30
+ if (!id)
31
+ throw new Error(`Usage: ocean idea ${action} <idea-id> [target]`);
32
+ store.updateIdea(id, action === "discard" ? "discarded" : "classified", action === "classify" ? args[1] : undefined);
33
+ console.log(JSON.stringify({
34
+ ideaId: id,
35
+ status: action === "discard" ? "discarded" : "classified",
36
+ target: args[1] ?? null,
37
+ }, null, 2));
38
+ return;
39
+ }
40
+ console.error("Usage: ocean idea save <title> <content> [--session <id>]|list [status]|classify <id> <target>|discard <id>");
41
+ process.exitCode = 1;
42
+ }
43
+ finally {
44
+ store.close();
45
+ }
46
+ }
47
+ //# sourceMappingURL=idea-command.js.map