oh-my-opencode 4.19.1 → 4.19.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/.agents/command/publish.md +95 -28
  2. package/.agents/skills/publish/SKILL.md +20 -6
  3. package/.opencode/command/publish.md +95 -28
  4. package/README.ja.md +2 -2
  5. package/README.ko.md +2 -2
  6. package/README.md +2 -2
  7. package/README.ru.md +2 -2
  8. package/README.zh-cn.md +2 -2
  9. package/THIRD-PARTY-NOTICES.md +7 -7
  10. package/dist/agents/atlas/agent.d.ts +4 -2
  11. package/dist/agents/explore.d.ts +4 -2
  12. package/dist/agents/hephaestus/agent.d.ts +4 -2
  13. package/dist/agents/librarian.d.ts +4 -2
  14. package/dist/agents/metis.d.ts +4 -2
  15. package/dist/agents/momus.d.ts +3 -2
  16. package/dist/agents/multimodal-looker.d.ts +4 -2
  17. package/dist/agents/oracle.d.ts +4 -2
  18. package/dist/agents/sisyphus/claude-opus-5.d.ts +33 -0
  19. package/dist/agents/sisyphus/index.d.ts +2 -0
  20. package/dist/agents/sisyphus-agent-factory.d.ts +5 -2
  21. package/dist/agents/sisyphus-junior/agent.d.ts +4 -1
  22. package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +1 -1
  23. package/dist/agents/types.d.ts +2 -2
  24. package/dist/cli/config-migrate.d.ts +8 -0
  25. package/dist/cli/doctor/checks/legacy-config-leftovers.d.ts +10 -0
  26. package/dist/cli/doctor/checks/model-resolution-config.d.ts +1 -1
  27. package/dist/cli/doctor/checks/tools-lsp.d.ts +1 -1
  28. package/dist/cli/doctor/framework/constants.d.ts +1 -1
  29. package/dist/cli/index.js +95391 -88524
  30. package/dist/cli-node/index.js +95504 -88637
  31. package/dist/config/schema/agent-names.d.ts +26 -26
  32. package/dist/config/schema/agent-overrides.d.ts +400 -400
  33. package/dist/config/schema/browser-automation.d.ts +2 -2
  34. package/dist/config/schema/categories.d.ts +36 -36
  35. package/dist/config/schema/commands.d.ts +2 -2
  36. package/dist/config/schema/dynamic-context-pruning.d.ts +1 -1
  37. package/dist/config/schema/experimental.d.ts +1 -1
  38. package/dist/config/schema/fallback-models.d.ts +25 -25
  39. package/dist/config/schema/hooks.d.ts +43 -43
  40. package/dist/config/schema/internal/permission.d.ts +9 -9
  41. package/dist/config/schema/keyword-detector.d.ts +6 -6
  42. package/dist/config/schema/oh-my-opencode-config.d.ts +402 -402
  43. package/dist/config/schema/tmux.d.ts +6 -6
  44. package/dist/config/validate.d.ts +2 -1
  45. package/dist/config-migration/deep-diff.d.ts +1 -0
  46. package/dist/config-migration/discovery-paths.d.ts +11 -0
  47. package/dist/config-migration/discovery-roots.d.ts +7 -0
  48. package/dist/config-migration/discovery.d.ts +4 -0
  49. package/dist/config-migration/index.d.ts +9 -0
  50. package/dist/config-migration/legacy-history.d.ts +3 -0
  51. package/dist/config-migration/migration-executor.d.ts +4 -0
  52. package/dist/config-migration/migration-plans.d.ts +14 -0
  53. package/dist/config-migration/record-values.d.ts +4 -0
  54. package/dist/config-migration/schema-url.d.ts +1 -0
  55. package/dist/config-migration/transform-config-jsonc.d.ts +2 -0
  56. package/dist/config-migration/transform-opencode.d.ts +2 -0
  57. package/dist/config-migration/transform-types.d.ts +24 -0
  58. package/dist/config-migration/types.d.ts +39 -0
  59. package/dist/create-hooks.d.ts +35 -35
  60. package/dist/features/background-agent/spawner/tmux-callback-invoker.d.ts +11 -0
  61. package/dist/features/builtin-commands/templates/hyperplan.d.ts +1 -1
  62. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
  63. package/dist/features/claude-tasks/types.d.ts +4 -4
  64. package/dist/features/team-mode/team-runtime/shutdown-helpers.d.ts +1 -1
  65. package/dist/features/team-mode/team-runtime/shutdown-test-fixtures.d.ts +4 -4
  66. package/dist/features/team-mode/tools/lifecycle-test-fixture.d.ts +42 -42
  67. package/dist/features/tmux-subagent/environment-eligibility.d.ts +2 -0
  68. package/dist/features/tmux-subagent/index.d.ts +1 -0
  69. package/dist/features/tmux-subagent/tracked-session-state.d.ts +1 -0
  70. package/dist/features/tui-sidebar/snapshot-schema.d.ts +6 -6
  71. package/dist/help/schema/acp.d.ts +3 -3
  72. package/dist/help/schema/doctor.d.ts +4 -4
  73. package/dist/help/schema/status.d.ts +3 -3
  74. package/dist/hooks/auto-update-checker/constants.d.ts +3 -3
  75. package/dist/hooks/goal/types.d.ts +5 -5
  76. package/dist/hooks/non-interactive-env/constants.d.ts +4 -1
  77. package/dist/hooks/start-work/parse-user-request.d.ts +2 -0
  78. package/dist/hooks/start-work/worktree-block.d.ts +5 -0
  79. package/dist/index.js +35450 -28257
  80. package/dist/mcp/types.d.ts +3 -3
  81. package/dist/oh-my-opencode.schema.json +1 -1
  82. package/dist/plugin/chat-message/loop-commands.d.ts +1 -0
  83. package/dist/plugin/command-execute-before.d.ts +3 -3
  84. package/dist/plugin/hooks/create-core-hooks.d.ts +25 -25
  85. package/dist/plugin-config/omo-config-chain.d.ts +14 -0
  86. package/dist/plugin-config/unknown-key-diagnostics.d.ts +5 -0
  87. package/dist/plugin-config.d.ts +2 -2
  88. package/dist/shared/agent-display-names.d.ts +1 -1
  89. package/dist/shared/jsonc-parser.d.ts +1 -1
  90. package/dist/shared/migration.d.ts +5 -1
  91. package/dist/shared/opencode-config-dir-types.d.ts +0 -1
  92. package/dist/shared/plugin-identity.d.ts +6 -8
  93. package/dist/shared/project-discovery-dirs.d.ts +0 -1
  94. package/dist/shared/tmux/tmux-utils/environment.d.ts +1 -1
  95. package/dist/shared/tmux/tmux-utils.d.ts +1 -1
  96. package/dist/shared/typescript-native-source-parser.d.ts +7 -0
  97. package/dist/skills/coding-agent-sessions/SKILL.md +5 -2
  98. package/dist/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  99. package/dist/skills/coding-agent-sessions/references/senpi.md +15 -5
  100. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  101. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  102. package/dist/skills/debugging/SKILL.md +2 -1
  103. package/dist/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  104. package/dist/skills/frontend/ATTRIBUTION.md +7 -0
  105. package/dist/skills/frontend/SKILL.md +4 -1
  106. package/dist/skills/frontend/references/design/README.md +8 -0
  107. package/dist/skills/frontend/references/design/_INDEX.md +14 -1
  108. package/dist/skills/frontend/references/design/interaction-skill.md +144 -0
  109. package/dist/skills/programming/SKILL.md +11 -1
  110. package/dist/skills/programming/references/logging.md +6 -1
  111. package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.ts +51 -17
  112. package/dist/skills/start-work/SKILL.md +12 -2
  113. package/dist/skills/ulw-plan/SKILL.md +1 -1
  114. package/dist/skills/ulw-plan/references/full-workflow.md +12 -1
  115. package/dist/skills/ulw-plan/references/intent-clear.md +1 -1
  116. package/dist/startup-migration.d.ts +28 -0
  117. package/dist/testing/create-plugin-module.d.ts +4 -0
  118. package/dist/tools/task/types.d.ts +10 -10
  119. package/dist/tui.js +31812 -26849
  120. package/package.json +14 -14
  121. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +21 -5
  122. package/packages/lsp-core/src/lsp/fixtures/workspace-edit-server.mjs +11 -2
  123. package/packages/omo-codex/THIRD-PARTY-NOTICES.md +2 -2
  124. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  125. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +8 -4
  126. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  127. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  128. package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +11 -5
  129. package/packages/omo-codex/plugin/components/codegraph/NOTICE +1 -1
  130. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +10272 -2600
  131. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +7341 -562
  132. package/packages/omo-codex/plugin/components/codegraph/package.json +2 -2
  133. package/packages/omo-codex/plugin/components/codegraph/src/hook-input.ts +33 -0
  134. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +36 -10
  135. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +170 -186
  136. package/packages/omo-codex/plugin/components/codegraph/src/post-tool-use-hook.ts +34 -0
  137. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +22 -5
  138. package/packages/omo-codex/plugin/components/codegraph/src/session-start-command.ts +106 -0
  139. package/packages/omo-codex/plugin/components/codegraph/src/session-start-cooldown.ts +145 -0
  140. package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +21 -0
  141. package/packages/omo-codex/plugin/components/codegraph/src/session-start-lock.ts +139 -0
  142. package/packages/omo-codex/plugin/components/codegraph/src/session-start-outcome.ts +15 -0
  143. package/packages/omo-codex/plugin/components/codegraph/src/session-start-paths.ts +32 -0
  144. package/packages/omo-codex/plugin/components/codegraph/src/session-start-project.ts +109 -0
  145. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker-result.ts +148 -0
  146. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +126 -186
  147. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +9 -4
  148. package/packages/omo-codex/plugin/components/codegraph/test/hook-session-start-guard.test.ts +160 -0
  149. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +12 -110
  150. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +29 -20
  151. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +3 -3
  152. package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +2 -2
  153. package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +11 -5
  154. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +3 -3
  155. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +2 -1
  156. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +50 -5
  157. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +3 -2
  158. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +24 -13
  159. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +70 -13
  160. package/packages/omo-codex/plugin/components/codegraph/test/session-start-project.test.ts +58 -0
  161. package/packages/omo-codex/plugin/components/codegraph/test/session-start-state.test.ts +104 -0
  162. package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +4 -2
  163. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts +116 -0
  164. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +114 -119
  165. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  166. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  167. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  168. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  169. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  170. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  171. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  172. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  173. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  174. package/packages/omo-codex/plugin/components/rules/dist/cli.js +31 -14
  175. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  176. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  177. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +1 -1
  178. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  179. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  180. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  181. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  182. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  183. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  184. package/packages/omo-codex/plugin/components/ultrawork/directive.md +12 -7
  185. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  186. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  187. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +12 -7
  188. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +1 -1
  189. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +12 -1
  190. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +1 -1
  191. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +12 -7
  192. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  193. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  194. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +19 -1
  195. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  196. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  197. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  198. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  199. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  200. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  201. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  202. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  203. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  204. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  205. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  206. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  207. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  208. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  209. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  210. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  211. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  212. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  213. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  214. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  215. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  216. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  217. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  218. package/packages/omo-codex/plugin/package-lock.json +42 -41
  219. package/packages/omo-codex/plugin/package.json +1 -1
  220. package/packages/omo-codex/plugin/shared/src/config-loader.ts +165 -16
  221. package/packages/omo-codex/plugin/shared/src/config-migration.ts +162 -0
  222. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +196 -18
  223. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +5 -2
  224. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  225. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +15 -5
  226. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  227. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  228. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -1
  229. package/packages/omo-codex/plugin/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  230. package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +7 -0
  231. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +4 -1
  232. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +8 -0
  233. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +14 -1
  234. package/packages/omo-codex/plugin/skills/frontend/references/design/interaction-skill.md +144 -0
  235. package/packages/omo-codex/plugin/skills/programming/SKILL.md +11 -1
  236. package/packages/omo-codex/plugin/skills/programming/references/logging.md +6 -1
  237. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +51 -17
  238. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +12 -2
  239. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +12 -7
  240. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +19 -1
  241. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +1 -1
  242. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +12 -1
  243. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +1 -1
  244. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +22 -0
  245. package/packages/omo-codex/scripts/install-dist/install-local.mjs +1 -1
  246. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +5 -2
  247. package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  248. package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +15 -5
  249. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  250. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  251. package/packages/shared-skills/skills/debugging/SKILL.md +2 -1
  252. package/packages/shared-skills/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  253. package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +7 -0
  254. package/packages/shared-skills/skills/frontend/SKILL.md +4 -1
  255. package/packages/shared-skills/skills/frontend/references/design/README.md +8 -0
  256. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +14 -1
  257. package/packages/shared-skills/skills/frontend/references/design/interaction-skill.md +144 -0
  258. package/packages/shared-skills/skills/programming/SKILL.md +11 -1
  259. package/packages/shared-skills/skills/programming/references/logging.md +6 -1
  260. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +51 -17
  261. package/packages/shared-skills/skills/start-work/SKILL.md +12 -2
  262. package/packages/shared-skills/skills/ulw-plan/SKILL.md +1 -1
  263. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +12 -1
  264. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +1 -1
  265. package/dist/plugin-config/layered-config-loader.d.ts +0 -2
  266. package/dist/plugin-config/single-config-loader.d.ts +0 -4
  267. package/dist/shared/migrate-legacy-config-file.d.ts +0 -1
  268. package/dist/shared/migration/config-migration.d.ts +0 -1
@@ -1,9 +1,14 @@
1
1
  import { afterEach, describe, expect, it } from "bun:test"
2
- import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"
2
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs"
3
3
  import { tmpdir } from "node:os"
4
- import { join } from "node:path"
4
+ import { join, posix } from "node:path"
5
5
 
6
- import { getCodexOmoConfig } from "../src/config-loader.ts"
6
+ import { parse } from "jsonc-parser"
7
+
8
+ import { runMigrations, type MigrationBoundary } from "../../../../omo-config-core/src/index.ts"
9
+ import { createLegacyConfigMigrationPlans } from "../../../../omo-opencode/src/config-migration/index.ts"
10
+
11
+ import { getCodexOmoConfig, runCodexStartupMigration } from "../src/config-loader.ts"
7
12
 
8
13
  const temporaryDirectories: string[] = []
9
14
 
@@ -14,11 +19,51 @@ function createTemporaryDirectory(prefix: string): string {
14
19
  }
15
20
 
16
21
  function writeOmoConfig(homeDir: string, content: string): void {
22
+ const configDir = join(homeDir, ".omo")
23
+ mkdirSync(configDir, { recursive: true })
24
+ writeFileSync(join(configDir, "omo.jsonc"), content)
25
+ }
26
+
27
+ function writeLegacyOmoConfig(homeDir: string, content: string): void {
17
28
  const configDir = join(homeDir, ".omo")
18
29
  mkdirSync(configDir, { recursive: true })
19
30
  writeFileSync(join(configDir, "config.jsonc"), content)
20
31
  }
21
32
 
33
+ function isRecord(value: unknown): value is Record<string, unknown> {
34
+ return typeof value === "object" && value !== null && !Array.isArray(value)
35
+ }
36
+
37
+ function readOmoJson(homeDir: string): Record<string, unknown> {
38
+ const value: unknown = parse(readFileSync(join(homeDir, ".omo", "omo.jsonc"), "utf-8"))
39
+ if (!isRecord(value)) throw new Error("Expected an omo JSONC object")
40
+ return value
41
+ }
42
+
43
+ function writeOpenCodeConfig(homeDir: string): void {
44
+ const configDir = join(homeDir, ".config", "opencode")
45
+ mkdirSync(configDir, { recursive: true })
46
+ writeFileSync(join(configDir, "oh-my-openagent.jsonc"), '{"agents":{"finder":{"model":"provider/finder"}}}')
47
+ }
48
+
49
+ function runOpenCodeMigration(homeDir: string, cwd: string, onBoundary?: (boundary: MigrationBoundary) => void): void {
50
+ runMigrations({
51
+ discover: () => createLegacyConfigMigrationPlans({
52
+ cwd,
53
+ environment: { HOME: homeDir, XDG_CONFIG_HOME: join(homeDir, ".config") },
54
+ homeDir,
55
+ pathOperations: posix,
56
+ }),
57
+ env: { HOME: homeDir },
58
+ ...(onBoundary === undefined ? {} : { onBoundary }),
59
+ })
60
+ }
61
+
62
+ function migrationIds(homeDir: string): readonly string[] {
63
+ const migrations = readOmoJson(homeDir)["_migrations"]
64
+ return Array.isArray(migrations) ? migrations.filter((entry): entry is string => typeof entry === "string") : []
65
+ }
66
+
22
67
  afterEach(() => {
23
68
  for (const directory of temporaryDirectories.splice(0)) {
24
69
  rmSync(directory, { recursive: true, force: true })
@@ -45,6 +90,7 @@ describe("getCodexOmoConfig", () => {
45
90
  // then
46
91
  expect(result.codegraph).toEqual({
47
92
  auto_provision: true,
93
+ daemon: true,
48
94
  enabled: false,
49
95
  install_dir: "/base",
50
96
  telemetry: false,
@@ -85,7 +131,21 @@ describe("getCodexOmoConfig", () => {
85
131
  expect(result.codegraph?.excluded_roots).toEqual(["/tmp/omo-research", "/private/tmp/omo-research"])
86
132
  })
87
133
 
88
- it("#given no codegraph.daemon key #when loading config #then daemon defaults to off", () => {
134
+ it("#given codex SOT sets the SessionStart cooldown #when loading config #then the configured base interval is returned", () => {
135
+ // given
136
+ const homeDir = createTemporaryDirectory("omo-codex-shared-cooldown-home-")
137
+ const cwd = createTemporaryDirectory("omo-codex-shared-cooldown-project-")
138
+ writeOmoConfig(homeDir, JSON.stringify({ "[codex]": { codegraph: { session_start_cooldown_ms: 900_000 } } }))
139
+
140
+ // when
141
+ const result = getCodexOmoConfig({ cwd, homeDir, env: {} })
142
+
143
+ // then
144
+ expect(result.codegraph?.session_start_cooldown_ms).toBe(900_000)
145
+ expect(result.warnings).toEqual([])
146
+ })
147
+
148
+ it("#given no codegraph.daemon key #when loading config #then daemon defaults to on", () => {
89
149
  // given
90
150
  const homeDir = createTemporaryDirectory("omo-codex-shared-daemon-default-home-")
91
151
  const cwd = createTemporaryDirectory("omo-codex-shared-daemon-default-project-")
@@ -95,22 +155,21 @@ describe("getCodexOmoConfig", () => {
95
155
  const result = getCodexOmoConfig({ cwd, homeDir, env: {} })
96
156
 
97
157
  // then
98
- expect(result.codegraph?.daemon).toBeUndefined()
99
- expect(result.codegraph?.daemon === true).toBe(false)
158
+ expect(result.codegraph?.daemon).toBe(true)
100
159
  expect(result.warnings).toEqual([])
101
160
  })
102
161
 
103
- it("#given codex SOT sets codegraph.daemon=true #when loading config #then daemon opt-in is returned", () => {
162
+ it("#given codex SOT sets codegraph.daemon=false #when loading config #then daemon opt-out is returned", () => {
104
163
  // given
105
- const homeDir = createTemporaryDirectory("omo-codex-shared-daemon-on-home-")
106
- const cwd = createTemporaryDirectory("omo-codex-shared-daemon-on-project-")
107
- writeOmoConfig(homeDir, JSON.stringify({ "[codex]": { codegraph: { daemon: true } } }))
164
+ const homeDir = createTemporaryDirectory("omo-codex-shared-daemon-off-home-")
165
+ const cwd = createTemporaryDirectory("omo-codex-shared-daemon-off-project-")
166
+ writeOmoConfig(homeDir, JSON.stringify({ "[codex]": { codegraph: { daemon: false } } }))
108
167
 
109
168
  // when
110
169
  const result = getCodexOmoConfig({ cwd, homeDir, env: {} })
111
170
 
112
171
  // then
113
- expect(result.codegraph?.daemon).toBe(true)
172
+ expect(result.codegraph?.daemon).toBe(false)
114
173
  expect(result.warnings).toEqual([])
115
174
  })
116
175
 
@@ -124,25 +183,25 @@ describe("getCodexOmoConfig", () => {
124
183
  const result = getCodexOmoConfig({ cwd, homeDir, env: {} })
125
184
 
126
185
  // then
127
- expect(result.codegraph?.daemon).toBeUndefined()
128
- expect(result.warnings).toContain("config.[codex].codegraph.daemon must be a boolean")
186
+ expect(result.codegraph?.daemon).toBe(true)
187
+ expect(result.warnings).toContain(`Invalid omo config at ${join(homeDir, ".omo", "omo.jsonc")}: [codex].codegraph.daemon`)
129
188
  })
130
189
 
131
190
  it("#given legacy env override and SOT value #when loading config #then env wins over the SOT", () => {
132
191
  // given
133
192
  const homeDir = createTemporaryDirectory("omo-codex-shared-env-")
134
193
  const cwd = createTemporaryDirectory("omo-codex-project-env-")
135
- writeOmoConfig(homeDir, JSON.stringify({ codegraph: { enabled: true } }))
194
+ writeOmoConfig(homeDir, JSON.stringify({ codegraph: { enabled: false } }))
136
195
 
137
196
  // when
138
197
  const result = getCodexOmoConfig({
139
198
  cwd,
140
199
  homeDir,
141
- env: { CODEX_CODEGRAPH_ENABLED: "0" },
200
+ env: { CODEX_CODEGRAPH_ENABLED: "1" },
142
201
  })
143
202
 
144
203
  // then
145
- expect(result.codegraph?.enabled).toBe(false)
204
+ expect(result.codegraph?.enabled).toBe(true)
146
205
  })
147
206
 
148
207
  it("#given no SOT files #when loading config #then returns built-in defaults and missing global source", () => {
@@ -156,14 +215,15 @@ describe("getCodexOmoConfig", () => {
156
215
  // then
157
216
  expect(result.codegraph).toEqual({
158
217
  auto_provision: true,
218
+ daemon: true,
159
219
  enabled: true,
160
220
  telemetry: false,
161
221
  })
162
222
  expect(result.sources).toContainEqual({
163
223
  exists: false,
164
224
  loaded: false,
165
- path: join(homeDir, ".omo", "config.jsonc"),
166
- scope: "global",
225
+ path: join(homeDir, ".omo", "omo.jsonc"),
226
+ scope: "user",
167
227
  })
168
228
  })
169
229
 
@@ -179,4 +239,122 @@ describe("getCodexOmoConfig", () => {
179
239
  // then
180
240
  expect(result.warnings).toContain("codegraph.watch_debounce_ms is not supported for harness codex")
181
241
  })
242
+
243
+ it("#given only legacy config.jsonc #when codex starts #then migrates once with a backup before loading the unified codex view", () => {
244
+ // given
245
+ const homeDir = createTemporaryDirectory("omo-codex-legacy-upgrade-")
246
+ writeLegacyOmoConfig(homeDir, JSON.stringify({ "[codex]": { codegraph: { daemon: false } } }))
247
+ const legacyPath = join(homeDir, ".omo", "config.jsonc")
248
+
249
+ // when
250
+ const first = getCodexOmoConfig({ cwd: homeDir, homeDir, env: {} })
251
+ const backupDirectories = readdirSync(join(homeDir, ".omo")).filter((entry) => entry.startsWith("migration-backup-"))
252
+ const second = getCodexOmoConfig({ cwd: homeDir, homeDir, env: {} })
253
+
254
+ // then
255
+ expect(first.codegraph?.daemon).toBe(false)
256
+ expect(first.warnings.some((warning) => warning.startsWith("omo-codex: migrated legacy configuration from ")
257
+ && warning.endsWith("/.omo/config.jsonc"))).toBe(true)
258
+ expect(readOmoJson(homeDir)["_migrations"]).toEqual(["2026-07-codex-config-jsonc"])
259
+ expect(existsSync(legacyPath)).toBe(false)
260
+ expect(backupDirectories).toHaveLength(1)
261
+ expect(existsSync(join(homeDir, ".omo", backupDirectories[0] ?? "", ".omo", "config.jsonc"))).toBe(true)
262
+ expect(second.warnings.some((warning) => warning.startsWith("omo-codex: migrated legacy configuration from "))).toBe(false)
263
+ expect(readdirSync(join(homeDir, ".omo")).filter((entry) => entry.startsWith("migration-backup-"))).toEqual(backupDirectories)
264
+ })
265
+
266
+ it("#given a legacy migration conflict #when codex starts #then exposes the migration summary and conflict through loader warnings", () => {
267
+ // given
268
+ const homeDir = createTemporaryDirectory("omo-codex-legacy-conflict-")
269
+ writeOmoConfig(homeDir, JSON.stringify({ codegraph: { enabled: true } }))
270
+ writeLegacyOmoConfig(homeDir, JSON.stringify({ codegraph: { enabled: false } }))
271
+
272
+ // when
273
+ const result = getCodexOmoConfig({ cwd: homeDir, homeDir, env: {} })
274
+
275
+ // then
276
+ expect(result.warnings.some((warning) => warning.startsWith("omo-codex: migrated legacy configuration from ")
277
+ && warning.endsWith("/.omo/config.jsonc"))).toBe(true)
278
+ expect(result.warnings).toContain("omo-codex: configuration migration: skipped: codegraph.enabled legacy=false kept=true")
279
+ })
280
+
281
+ it("#given overlapping [omo] and [senpi] blocks in legacy config #when Codex migrates #then the transform conflict is reported", () => {
282
+ // given
283
+ const homeDir = createTemporaryDirectory("omo-codex-legacy-senpi-conflict-")
284
+ writeLegacyOmoConfig(homeDir, JSON.stringify({
285
+ "[omo]": { agents: { oracle: { model: "legacy" } } },
286
+ "[senpi]": { agents: { oracle: { model: "current" } } },
287
+ }))
288
+
289
+ // when
290
+ const result = runCodexStartupMigration({ cwd: homeDir, environment: { HOME: homeDir }, homeDir })
291
+
292
+ // then
293
+ expect(result.results[0]?.diagnostics).toContain("conflict: [senpi] legacy [omo] kept [senpi]")
294
+ })
295
+
296
+ it("#given a malformed migration journal #when codex starts #then exposes the recovery failure through loader warnings", () => {
297
+ // given
298
+ const homeDir = createTemporaryDirectory("omo-codex-recovery-warning-")
299
+ const migrationDir = join(homeDir, ".omo")
300
+ mkdirSync(migrationDir, { recursive: true })
301
+ writeFileSync(join(migrationDir, ".migration-journal.json"), "not-json")
302
+
303
+ // when
304
+ const result = getCodexOmoConfig({ cwd: homeDir, homeDir, env: {} })
305
+
306
+ // then
307
+ expect(result.warnings.some((warning) => warning.startsWith("omo-codex: configuration migration: "))).toBe(true)
308
+ })
309
+
310
+ it("#given codex starts before opencode #when both legacy source groups exist #then each distinct migration id is applied once", () => {
311
+ // given
312
+ const homeDir = createTemporaryDirectory("omo-codex-order-codex-first-")
313
+ writeLegacyOmoConfig(homeDir, JSON.stringify({ "[codex]": { codegraph: { daemon: false } } }))
314
+ writeOpenCodeConfig(homeDir)
315
+ const openCodeSource = join(homeDir, ".config", "opencode", "oh-my-openagent.jsonc")
316
+
317
+ // when
318
+ getCodexOmoConfig({ cwd: homeDir, homeDir, env: {} })
319
+ const remainsAfterCodexStartup = existsSync(openCodeSource)
320
+ runOpenCodeMigration(homeDir, homeDir)
321
+
322
+ // then
323
+ expect(remainsAfterCodexStartup).toBe(true)
324
+ expect(existsSync(openCodeSource)).toBe(false)
325
+ expect(migrationIds(homeDir)).toEqual(["2026-07-codex-config-jsonc", "2026-07-opencode-config-unification"])
326
+ })
327
+
328
+ it("#given opencode starts before codex #when both legacy source groups exist #then each distinct migration id is applied once", () => {
329
+ // given
330
+ const homeDir = createTemporaryDirectory("omo-codex-order-opencode-first-")
331
+ writeLegacyOmoConfig(homeDir, JSON.stringify({ "[codex]": { codegraph: { daemon: false } } }))
332
+ writeOpenCodeConfig(homeDir)
333
+
334
+ // when
335
+ runOpenCodeMigration(homeDir, homeDir)
336
+ getCodexOmoConfig({ cwd: homeDir, homeDir, env: {} })
337
+
338
+ // then
339
+ expect(migrationIds(homeDir)).toEqual(["2026-07-opencode-config-unification", "2026-07-codex-config-jsonc"])
340
+ })
341
+
342
+ it("#given concurrent codex and opencode starts #when opencode owns the shared lock #then both migration ids are applied exactly once", () => {
343
+ // given
344
+ const homeDir = createTemporaryDirectory("omo-codex-order-concurrent-")
345
+ writeLegacyOmoConfig(homeDir, JSON.stringify({ "[codex]": { codegraph: { daemon: false } } }))
346
+ writeOpenCodeConfig(homeDir)
347
+ let codexResult: ReturnType<typeof runCodexStartupMigration> | undefined
348
+
349
+ // when
350
+ runOpenCodeMigration(homeDir, homeDir, (boundary) => {
351
+ if (boundary !== "journal-written" || codexResult !== undefined) return
352
+ codexResult = runCodexStartupMigration({ cwd: homeDir, homeDir })
353
+ })
354
+
355
+ // then
356
+ if (codexResult === undefined) throw new Error("Expected concurrent Codex migration attempt")
357
+ expect(codexResult.error).toBe("Configuration migration is already running")
358
+ expect(migrationIds(homeDir)).toEqual(["2026-07-opencode-config-unification", "2026-07-codex-config-jsonc"])
359
+ })
182
360
  })
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: coding-agent-sessions
3
- description: "MUST USE when asked to find, read, list, search, inspect, fetch, export, or reconstruct coding-agent sessions across Codex, Claude Code/Desktop, OpenCode, Senpi/pi, OpenClaw, Factory Droid, Amp, Gemini/Kimi/Qwen CLIs, Codebuff, Roo/Kilo/Cline, Kodu, Cursor CLI, Aider, or unknown local agent logs. Covers transcripts, session IDs, rollout JSONL, state SQLite, Claude projects/pre-compact histories, OpenCode messages/parts, child/subagent linkage, cwd/model/time/token filters, archives, and cost clues. Expands fuzzy recall into parallel query lanes and first probes known stores so absent platforms are skipped cheaply. Triggers: coding agent sessions, Codex/Claude/OpenCode/Senpi/pi/OpenClaw/Droid/Amp/Kodu/Cursor/Aider sessions, transcript search, session history, session ID, read transcript, token usage, subagent sessions, what did I do yesterday, did we already do this."
3
+ description: "MUST USE when asked to find, read, list, search, inspect, fetch, export, or reconstruct coding-agent sessions across Codex, Claude Code/Desktop, OpenCode, Senpi/pi, oh-my-pi (omp), gajae-code (gjc), OpenClaw, Factory Droid, Amp, Gemini/Kimi/Qwen CLIs, Codebuff, Roo/Kilo/Cline, Kodu, Cursor CLI, Aider, or unknown local agent logs. Covers transcripts, session IDs, rollout JSONL, state SQLite, Claude projects/pre-compact histories, OpenCode messages/parts, child/subagent linkage, cwd/model/time/token filters, archives, and cost clues. Expands fuzzy recall into parallel query lanes and first probes known stores so absent platforms are skipped cheaply. Triggers: coding agent sessions, Codex/Claude/OpenCode/Senpi/pi/oh-my-pi/omp/gajae-code/gjc/OpenClaw/Droid/Amp/Kodu/Cursor/Aider sessions, transcript search, session history, session ID, read transcript, token usage, subagent sessions, what did I do yesterday, did we already do this."
4
4
  ---
5
5
 
6
6
  # Coding Agent Sessions
@@ -16,6 +16,7 @@ Find local coding-agent sessions across agent products before answering from mem
16
16
  | Codex / OpenAI Codex CLI | `references/codex.md` |
17
17
  | Claude Code / Claude Desktop histories | `references/claude.md` |
18
18
  | Senpi / pi coding-agent logs | `references/senpi.md` |
19
+ | oh-my-pi (`omp`, `~/.omp`) and gajae-code (`gjc`, `~/.gjc`) logs | `references/senpi.md` |
19
20
  | OpenCode / oh-my-openagent (formerly oh-my-opencode) storage | `references/opencode.md` |
20
21
  | OpenClaw, Droid, Amp, Gemini, Kimi, Qwen, Codebuff, Roo/Kilo/Cline, Kodu, Cursor CLI, Aider, Kiro, Goose, Hermes, Crush, Zed | `references/all-platforms.md` |
21
22
  | Unknown / "any session" / cross-agent search | `references/all-platforms.md` |
@@ -28,6 +29,7 @@ When the user remembers a task vaguely ("that OpenCode bug", "the dashboard PR",
28
29
  python3 scripts/find-agent-sessions.py list --limit 20
29
30
  python3 scripts/find-agent-sessions.py find "commit" --from 7d --platform senpi --platform opencode
30
31
  python3 scripts/find-agent-sessions.py find "proxy" --platform openclaw --platform droid --platform amp
32
+ python3 scripts/find-agent-sessions.py find "refactor" --platform oh-my-pi --platform gajae-code
31
33
  python3 scripts/find-agent-sessions.py find --query "deploy" --query "token usage" --workers 64
32
34
  python3 scripts/find-agent-sessions.py find --query "opencode bug" --query "fix opencode" --query "OpenCode parent session" --include-subagents --workers 64
33
35
  python3 scripts/find-agent-sessions.py read <session-id>
@@ -49,7 +51,7 @@ The finder prints JSON for stdout and `jq`. Every result includes:
49
51
 
50
52
  | Field | Meaning |
51
53
  |---|---|
52
- | `platform` | Registered platform key such as `codex`, `claude`, `opencode`, `openclaw`, `droid`, `amp`, `kodu`, `cursor-cli`, `aider`, `roo-code`, `kilo-code`, `kilo-cli`, or `kiro` |
54
+ | `platform` | Registered platform key such as `codex`, `claude`, `senpi`, `oh-my-pi`, `gajae-code`, `opencode`, `openclaw`, `droid`, `amp`, `kodu`, `cursor-cli`, `aider`, `roo-code`, `kilo-code`, `kilo-cli`, or `kiro` |
53
55
  | `id` | Session ID or stable file-derived ID |
54
56
  | `path` | Raw transcript/index file |
55
57
  | `cwd` | Working directory when recoverable |
@@ -117,6 +119,7 @@ Use `references/codex.md` for Codex storage details.
117
119
  | Problem | Fix |
118
120
  |---|---|
119
121
  | Missing Codex sessions | Set `CODEX_HOME` or pass `--root /path/to/.codex`. |
122
+ | Missing oh-my-pi / gajae-code sessions | Those stores live in `~/.omp/agent/sessions` and `~/.gjc/agent/sessions`. For a custom `PI_CONFIG_DIR` / `PI_CODING_AGENT_DIR`, pass that agent dir with `--root`. |
120
123
  | Missing OpenCode sessions | Pass the data dir that contains `messages/` and `parts/`, often `~/.opencode` or `~/.local/share/opencode`. |
121
124
  | Missing Claude sessions | Search `~/.claude/projects`, `~/.claude/transcripts`, and `~/.claude/pre-compact-session-histories`; use `--root` for nonstandard config dirs. |
122
125
  | Missing optional platform sessions | Check `references/all-platforms.md` for the exact local store. For project-local tools such as Aider, pass `--root /path/to/workspace` if the repo is outside the bounded default roots. |
@@ -4,13 +4,15 @@
4
4
 
5
5
  Search these first, then add user-supplied roots with `--root`:
6
6
 
7
- Registered platform keys: `codex`, `claude`, `senpi`, `opencode`, `openclaw`, `droid`, `amp`, `gemini`, `kimi`, `qwen`, `codebuff`, `roo-code`, `kilo-code`, `cline`, `kodu`, `cursor-cli`, `aider`, `kilo-cli`, `hermes`, `goose`, `crush`, `zed`, `kiro`.
7
+ Registered platform keys: `codex`, `claude`, `senpi`, `oh-my-pi`, `gajae-code`, `opencode`, `openclaw`, `droid`, `amp`, `gemini`, `kimi`, `qwen`, `codebuff`, `roo-code`, `kilo-code`, `cline`, `kodu`, `cursor-cli`, `aider`, `kilo-cli`, `hermes`, `goose`, `crush`, `zed`, `kiro`.
8
8
 
9
9
  | Platform | Unix/macOS | Windows |
10
10
  |---|---|---|
11
11
  | Codex | `$CODEX_HOME`, `~/.codex` | `%CODEX_HOME%`, `%USERPROFILE%\.codex` |
12
12
  | Claude | `~/.claude` | `%USERPROFILE%\.claude`, `%APPDATA%\Claude` |
13
13
  | Senpi / pi | `~/.senpi/agent`, `~/.pi/agent` | `%USERPROFILE%\.senpi\agent`, `%USERPROFILE%\.pi\agent` |
14
+ | oh-my-pi (`omp`) | `~/.omp/agent`, `~/.omp/profiles/*/agent`, `$XDG_DATA_HOME/omp` | `%USERPROFILE%\.omp\agent` |
15
+ | gajae-code (`gjc`) | `~/.gjc/agent`, `~/.gjc/profiles/*/agent`, `$XDG_DATA_HOME/gjc` | `%USERPROFILE%\.gjc\agent` |
14
16
  | OpenCode | `$OPENCODE_HOME`, `~/.opencode`, `~/.local/share/opencode` | `%OPENCODE_HOME%`, `%APPDATA%\opencode`, `%USERPROFILE%\.opencode` |
15
17
  | OpenClaw | `~/.openclaw/agents/*/sessions`, `~/.openclaw/session-backups` | pass `--root` |
16
18
  | Factory Droid | `~/.factory/sessions/*/*.jsonl` | pass `--root` |
@@ -1,10 +1,20 @@
1
- # Senpi / pi Coding-Agent Sessions
1
+ # Senpi / pi Family Coding-Agent Sessions
2
2
 
3
- Observed Senpi layout:
3
+ The pi family (Senpi, oh-my-pi, gajae-code) shares one session format, so one scanner serves all three under separate platform keys.
4
4
 
5
- - `~/.senpi/agent/sessions/<encoded-cwd>/<timestamp>_<uuid>.jsonl`
6
- - `~/.senpi/agent/settings.json`, `models.json`, and `auth.json` provide environment context.
7
- - `~/.pi/agent/sessions/**` can use the same family of JSONL formats.
5
+ | Platform key | Aliases | Config root | Sessions |
6
+ |---|---|---|---|
7
+ | `senpi` | - | `~/.senpi`, `~/.pi` | `<root>/agent/sessions/<encoded-cwd>/<timestamp>_<uuid>.jsonl` |
8
+ | `oh-my-pi` | `omp`, `ohmypi` | `~/.omp` | `~/.omp/agent/sessions/<encoded-cwd>/<timestamp>_<uuid>.jsonl` |
9
+ | `gajae-code` | `gjc`, `gajae` | `~/.gjc` | `~/.gjc/agent/sessions/<encoded-cwd>/<timestamp>_<uuid>.jsonl` |
10
+
11
+ Extra roots scanned for every pi-family platform:
12
+
13
+ - Named profiles: `<config-root>/profiles/<profile>/agent/sessions/**`.
14
+ - XDG stores (macOS/Linux, default profile): `$XDG_DATA_HOME/<app>/sessions/**` and `$XDG_DATA_HOME/<app>/profiles/<profile>/sessions/**`, where `<app>` is `senpi`, `omp`, or `gjc`. XDG flattens the `agent/` path segment.
15
+ - A custom `PI_CONFIG_DIR` / `PI_CODING_AGENT_DIR` / `GJC_CONFIG_DIR` store: pass that agent directory with `--root`.
16
+
17
+ `~/.senpi/agent/settings.json`, `models.json`, and `auth.json` provide environment context; oh-my-pi and gajae-code keep the same files plus `config.yml` and `models.yml` next to their sessions directory.
8
18
 
9
19
  Common event types:
10
20
 
@@ -0,0 +1,46 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+
5
+ from .transcript import env_path, existing, jsonl_parallel, recent, stem_id
6
+ from .types import Session
7
+
8
+ SENPI_CONFIG_DIRS = (".senpi", ".pi")
9
+ OH_MY_PI_CONFIG_DIRS = (".omp",)
10
+ GAJAE_CODE_CONFIG_DIRS = (".gjc",)
11
+
12
+ __all__ = ["scan_gajae_code", "scan_oh_my_pi", "scan_senpi"]
13
+
14
+
15
+ def scan_senpi(extra_roots: tuple[Path, ...], workers: int) -> list[Session]:
16
+ return _scan_pi_family("senpi", SENPI_CONFIG_DIRS, "senpi", extra_roots, workers)
17
+
18
+
19
+ def scan_oh_my_pi(extra_roots: tuple[Path, ...], workers: int) -> list[Session]:
20
+ return _scan_pi_family("oh-my-pi", OH_MY_PI_CONFIG_DIRS, "omp", extra_roots, workers)
21
+
22
+
23
+ def scan_gajae_code(extra_roots: tuple[Path, ...], workers: int) -> list[Session]:
24
+ return _scan_pi_family("gajae-code", GAJAE_CODE_CONFIG_DIRS, "gjc", extra_roots, workers)
25
+
26
+
27
+ def _scan_pi_family(platform: str, config_dirs: tuple[str, ...], xdg_app: str, extra_roots: tuple[Path, ...], workers: int) -> list[Session]:
28
+ roots = _pi_family_roots(config_dirs, xdg_app, extra_roots)
29
+ paths = [path for root in roots for path in (root / "sessions").rglob("*.jsonl")]
30
+ return jsonl_parallel(recent(paths), workers, platform, lambda path: stem_id(path, "_"))
31
+
32
+
33
+ def _pi_family_roots(config_dirs: tuple[str, ...], xdg_app: str, extra_roots: tuple[Path, ...]) -> list[Path]:
34
+ home = Path.home()
35
+ roots: list[Path] = []
36
+ for config_dir in config_dirs:
37
+ base = home / config_dir
38
+ roots.append(base / "agent")
39
+ roots.extend(sorted(base.glob("profiles/*/agent")))
40
+ xdg_data = env_path("XDG_DATA_HOME")
41
+ if xdg_data is not None:
42
+ app_root = xdg_data / xdg_app
43
+ roots.append(app_root)
44
+ roots.extend(sorted(app_root.glob("profiles/*")))
45
+ roots.extend(extra_roots)
46
+ return existing(roots)
@@ -21,9 +21,9 @@ from .file_scanners import (
21
21
  )
22
22
  from .kiro_scanner import scan_kiro
23
23
  from .opencode import scan_opencode
24
+ from .pi_family import scan_gajae_code, scan_oh_my_pi, scan_senpi
24
25
  from .sqlite_optional_scanners import scan_crush, scan_goose, scan_hermes, scan_kilo_cli, scan_zed
25
26
  from .sqlite_scanners import scan_cursor_cli, scan_kodu
26
- from .transcript import existing, jsonl_parallel, recent, stem_id
27
27
  from .types import Session
28
28
 
29
29
  Scanner: TypeAlias = Callable[[tuple[Path, ...], int], list[Session]]
@@ -31,7 +31,9 @@ Scanner: TypeAlias = Callable[[tuple[Path, ...], int], list[Session]]
31
31
  PLATFORM_SCANNERS: dict[str, Scanner] = {
32
32
  "codex": scan_codex,
33
33
  "claude": scan_claude,
34
- "senpi": lambda roots, workers: scan_senpi(roots, workers),
34
+ "senpi": scan_senpi,
35
+ "oh-my-pi": scan_oh_my_pi,
36
+ "gajae-code": scan_gajae_code,
35
37
  "opencode": scan_opencode,
36
38
  "openclaw": scan_openclaw,
37
39
  "droid": scan_droid,
@@ -54,9 +56,22 @@ PLATFORM_SCANNERS: dict[str, Scanner] = {
54
56
  "kiro": scan_kiro,
55
57
  }
56
58
  DEFAULT_PLATFORMS = frozenset(PLATFORM_SCANNERS)
57
- PLATFORM_ALIASES = {"cursor": "cursor-cli", "factory": "droid", "roo": "roo-code", "roocode": "roo-code", "kilocode": "kilo-code", "kilo": "kilo-cli"}
59
+ PLATFORM_ALIASES = {
60
+ "cursor": "cursor-cli",
61
+ "factory": "droid",
62
+ "roo": "roo-code",
63
+ "roocode": "roo-code",
64
+ "kilocode": "kilo-code",
65
+ "kilo": "kilo-cli",
66
+ "omp": "oh-my-pi",
67
+ "ohmypi": "oh-my-pi",
68
+ "oh_my_pi": "oh-my-pi",
69
+ "gjc": "gajae-code",
70
+ "gajae": "gajae-code",
71
+ "gajaecode": "gajae-code",
72
+ }
58
73
 
59
- __all__ = ["DEFAULT_PLATFORMS", "PLATFORM_SCANNERS", "scan", "scan_claude", "scan_codex", "scan_opencode", "scan_senpi"]
74
+ __all__ = ["DEFAULT_PLATFORMS", "PLATFORM_SCANNERS", "scan", "scan_claude", "scan_codex", "scan_gajae_code", "scan_oh_my_pi", "scan_opencode", "scan_senpi"]
60
75
 
61
76
 
62
77
  def scan(platforms: frozenset[str], roots: tuple[Path, ...], workers: int) -> list[Session]:
@@ -72,12 +87,6 @@ def scan(platforms: frozenset[str], roots: tuple[Path, ...], workers: int) -> li
72
87
  return _dedupe(sessions)
73
88
 
74
89
 
75
- def scan_senpi(extra_roots: tuple[Path, ...], workers: int) -> list[Session]:
76
- roots = existing([Path.home() / ".senpi" / "agent", Path.home() / ".pi" / "agent", *extra_roots])
77
- paths = [path for root in roots for path in (root / "sessions").rglob("*.jsonl")]
78
- return jsonl_parallel(recent(paths), workers, "senpi", lambda path: stem_id(path, "_"))
79
-
80
-
81
90
  def _dedupe(sessions: list[Session]) -> list[Session]:
82
91
  found: dict[tuple[str, str], Session] = {}
83
92
  for session in sessions:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: debugging
3
- description: "MUST USE for any real runtime debugging across ANY language or binary — crashes, silent failures, wrong responses, stuck processes, memory leaks, async misbehavior, unexplained timing, reverse engineering. Runs a hypothesis-driven loop: form ≥3 hypotheses, investigate in parallel, after 2 failed rounds spawn Oracles from orthogonal angles, confirm root cause, lock with a failing test, fix minimally, QA by actually USING the system, scrub artifacts. The actual HOW lives in `references/` — READ THEM. Triggers: 'debug this', 'why is X not working', 'hanging', 'attach a debugger', 'reverse engineer', 'pwndbg', 'gdb', 'lldb', 'node inspect', 'tsx debug', 'pdb', 'dlv', 'delve', 'rust-gdb', 'set a breakpoint', 'context window exploded', 'why is the response empty', 'attach the debugger', 'debug it', 'why is this happening', 'trace this bug', 'reproduce and fix', 'silent failure', 'HTTP 200 but empty', 'why did it stop', 'inspect the binary', 'reverse engineering', 'playwright'."
3
+ description: "MUST USE for any real runtime debugging across ANY language or binary — crashes, silent failures, wrong responses, stuck processes, memory leaks, async misbehavior, unexplained timing, reverse engineering. Runs a hypothesis-driven loop: form ≥3 hypotheses, investigate in parallel, after 2 failed rounds spawn Oracles from orthogonal angles, confirm root cause, lock with a failing test, fix minimally, QA by actually USING the system, scrub artifacts. The actual HOW lives in `references/` — READ THEM. Triggers: 'debug this', 'why is X not working', 'hanging', 'attach a debugger', 'reverse engineer', 'pwndbg', 'gdb', 'lldb', 'node inspect', 'tsx debug', 'pdb', 'dlv', 'delve', 'rust-gdb', 'set a breakpoint', 'context window exploded', 'why is the response empty', 'why is this happening', 'trace this bug', 'reproduce and fix', 'silent failure', 'HTTP 200 but empty', 'why did it stop', 'inspect the binary', 'playwright', 'flaky test', 'fails intermittently', 'passes in isolation', 'only fails in CI'."
4
4
  ---
5
5
 
6
6
  # Debugging
@@ -84,6 +84,7 @@ These are not phases — read them when the situation calls for them:
84
84
 
85
85
  | Situation | Reference |
86
86
  |---|---|
87
+ | The failure is intermittent — fails sometimes, a different test each run, passes in isolation, or only fails in CI | 📖 **[references/methodology/03-flaky-triage.md](references/methodology/03-flaky-triage.md)** — read BEFORE Phase 2; the failure signature usually collapses the search space in one round |
87
88
  | You cannot run the actual operation (paid API, blocked network, missing hardware) but still need runtime evidence | 📖 **[references/methodology/partial-runtime-evidence.md](references/methodology/partial-runtime-evidence.md)** |
88
89
  | You're about to declare an extraction / audit / reverse-engineering task done and want a skeptical pass | 📖 **[references/methodology/partial-runtime-evidence.md#verification-oracle-pattern-for-non-debug-tasks](references/methodology/partial-runtime-evidence.md#verification-oracle-pattern-for-non-debug-tasks)** (Verification Oracle is *not* the same as Oracle Triple — read the file) |
89
90
 
@@ -0,0 +1,47 @@
1
+ # Intermittent / Flaky Failure Triage
2
+
3
+ Read this when a failure does not reproduce on every run — "fails sometimes", "a different test each run", "passes in isolation", "only fails in CI". Do not enter the hypothesis loop blind: **intermittence itself is evidence.** This triage usually collapses the search space in one round, before Phase 2 hypothesis formation.
4
+
5
+ ---
6
+
7
+ ## Step 1 — Capture the failure signature (three cheap reruns)
8
+
9
+ Run these before forming any hypothesis. Journal each result.
10
+
11
+ | Rerun | Command shape | Question it answers |
12
+ |---|---|---|
13
+ | Same scope, same command | exactly what just failed | Does the SAME test fail again, or a different one? |
14
+ | Failing test in isolation | single file / test filter | Does it pass alone? |
15
+ | Full scope on a quiet machine | stop concurrent builds, suites, background agents first | Does the whole suite go green when nothing else runs? |
16
+ | (When order is suspect) shuffled | `-shuffle=on` / `pytest-randomly` / runner's random seed | Does a specific order reproduce it? Record the seed. |
17
+
18
+ ## Step 2 — Read the signature
19
+
20
+ | Signature | Dominant hypothesis | Next move |
21
+ |---|---|---|
22
+ | Same test fails intermittently, everywhere | Real race in the code under test, or an async test bug (fixed sleep, unawaited promise, poll-for-time) | Standard phase loop from `02-investigate.md`; reproduce deterministically by subscribing to the completion event or injecting a clock |
23
+ | **A different test/file each run; each passes in isolation; quiet machine is green** | **Environment contention between concurrent runs — not the code** | Step 3 checklist |
24
+ | Always the same test, but only in the full suite; isolation green | Test-order dependence / fixture leak (unreset module state, leaked env var, shared singleton) | Bisect with the shuffle seed; find the test that leaks, fix its teardown |
25
+ | Fails only on CI, never locally | Resource ceilings (slower disk/CPU → timeouts), different parallelism defaults, container clock | Reproduce locally under constraint (`taskset`, low `--maxWorkers`); raise the *signal* not the sleep |
26
+ | Green on plain rerun of the same commit | Still a flake — classify it with this table before ignoring it; an unclassified flake is a hidden bug report | Step 1 again with journaling |
27
+
28
+ ## Step 3 — Concurrent-run contention checklist
29
+
30
+ The classic modern cause: **two checkouts or worktrees of the same repo — or one checkout plus a background agent — running suites at the same time while sharing a global mutable resource.** Multi-agent workstations make this the default failure mode, not an exotic one. Check each:
31
+
32
+ - **Shared tmp roots** — a sandbox/cache dir derived from a *fixed* tmpdir path (`$TMPDIR/<project>-fixed-name`) instead of a per-run `mktemp`. Both runs read/write the same tree; the loser sees half-deleted state.
33
+ - **Fixed ports** — hardcoded listen ports in test servers. Two suites race to bind; the loser gets 404/ECONNREFUSED mid-run, in whichever file happened to be running.
34
+ - **Global env / config mutation** — tests writing process-external state (dotfiles, shared config, global env) the other run reads.
35
+ - **Shared containers / databases** — same-named containers, same schema, same volume.
36
+ - **Caches and locks** — package-manager caches, lockfiles, `.git` index contention.
37
+
38
+ Evidence to capture while it is live: `lsof -i :<port>` during the failure window, a listing of the shared tmp path, a process list showing the concurrent runners.
39
+
40
+ ## Step 4 — Fix policy
41
+
42
+ - **Environment contention** → fix the **test infrastructure**, never the individual test: namespace every suite-global resource per run — `mktemp` for roots, port `0`/ephemeral allocation, unique container names. The bar: *two checkouts of this repo running the suite concurrently must not interfere.* (The programming skill's test-isolation rules own this bar.)
43
+ - **Order dependence** → find the leaking fixture via the recorded shuffle seed; reset at teardown; re-run shuffled until the seed class is clean.
44
+ - **Real race** → normal phase loop (`02-investigate.md` onward); the fix ships with a failing-first test that reproduces deterministically.
45
+ - **Forbidden regardless of cause**: retry wrappers around the test, enlarged sleeps, `.retry(N)`, quarantining, or deleting the test. Each one buries a bug report.
46
+
47
+ A flake you classified but did not fix is a **finding to report**, not to hide: journal the signature, the evidence, and the classification, and say it in your final report.
@@ -210,6 +210,13 @@ no Lazyweb source, documentation text, or screenshot content is vendored. Lazywe
210
210
  remain the property of their owner, and the guide grants no license to ship, trace, or
211
211
  commit reference screenshots harvested through it.
212
212
 
213
+ `frontend/references/design/interaction-skill.md` is a project-original, curl-only
214
+ operating guide for consulting the beui.dev animated-component registry during interaction
215
+ and motion work, written from live endpoint verification; no beui.dev source code,
216
+ documentation text, or component implementations are vendored. beui.dev names remain the
217
+ property of their owner, and the guide instructs reading component source for mechanism
218
+ extraction only, not vendoring it into references or projects.
219
+
213
220
  `frontend/references/design/clone-from-url.md` is a project-original runtime-extraction
214
221
  workflow guide. Its browser + `getComputedStyle` clone approach follows the same
215
222
  MIT-licensed `JCodesMore/ai-website-cloner-template` clone-website workflow that `aside.md`
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: frontend
3
- description: "MUST USE for frontend/web UI/UX/visual work: building, styling, redesigning pages/components, React setup, performance audits, visual QA, taste, and polish. Routes four rulesets: design taste router and brand references; perfection for Playwright/Chromium Lighthouse/Core Web Vitals; ui-ux-db palettes/fonts/guidelines; designpowers personas/accessibility/critique/handoff; plus curl-only lazyweb real-app-screen research for design direction. Triggers: frontend, UI, UX, design, redesign, styling, layout, animation, motion, premium, luxury, minimal, brutalist, Awwwards, DESIGN.md, mockup, React, Lighthouse, accessibility, WCAG, Core Web Vitals, looks generic, make it pretty, like X brand, lazyweb, design research."
3
+ description: "MUST USE for frontend/web UI/UX/visual work: building, styling, redesigning pages/components, React setup, performance audits, visual QA, taste, and polish. Routes four rulesets: design taste router and brand references; perfection for Playwright/Chromium Lighthouse/Core Web Vitals; ui-ux-db palettes/fonts/guidelines; designpowers personas/accessibility/critique/handoff; plus curl-only lazyweb real-app-screen research and the beui.dev interaction catalog. Triggers: frontend, UI, UX, design, redesign, styling, layout, animation, motion, interaction, micro-interaction, make it feel alive, premium, luxury, minimal, brutalist, Awwwards, DESIGN.md, mockup, React, Lighthouse, accessibility, WCAG, Core Web Vitals, looks generic, make it pretty, like X brand, lazyweb, design research."
4
4
  ---
5
5
 
6
6
  # Frontend
@@ -14,6 +14,7 @@ This file is a router, not a rulebook. The rules live in four rulesets under `re
14
14
  | Request involves… | Read |
15
15
  |---|---|
16
16
  | ANY UI implementation, styling, redesign, mockup, or visual decision | `references/design/README.md` FIRST. It enforces two mandatory gates — the Design System Gate (a `DESIGN.md` must exist before any component is written) and the React Dev Tooling Gate (react-grab / react-scan / react-doctor installed by default) — then routes to the taste and brand references below. |
17
+ | Interaction or motion work — micro-interactions, animated components, transitions, gestures, hover/press/state feedback, "make it feel alive" | ALSO `references/design/interaction-skill.md`. The beui.dev catalog is the mandatory interaction reference: find the nearest pattern, read its real source through the file's curl recipe, and adapt the mechanism to `DESIGN.md` motion tokens. It stacks on the routed style skill — never replaces it. |
17
18
  | Writing or modifying frontend code, OR auditing performance / SEO / accessibility / quality | ALSO `references/perfection/README.md`. Lighthouse 100 in every category, measured on real Playwright Chromium (never the `lighthouse` CLI), achieved through architecture — never by dropping animations or hiding content. |
18
19
  | Looking up a concrete style, color palette, font pairing, chart type, landing-page structure, or UX guideline — or generating a project design system from keywords | `references/ui-ux-db/README.md`. A searchable CSV database with a CLI; a lookup tool, not a posture. Load on demand; `design` stays the source of truth for taste and the `DESIGN.md` contract. |
19
20
  | ANY implementation or redesign that creates or updates `DESIGN.md` — plus explicit operating-layer asks (personas, critique, debt, handoff, synthetic user testing) | `references/designpowers/README.md` + `references/designpowers/lane-c-review.md`. An internal frontend ruleset, not a separate skill: lane-c is the Phase Final flatness/critique reviewer, and its accessibility-constraints and accepted-debt language fills the required `DESIGN.md` sections. Load other lanes only when their phase applies. |
@@ -61,6 +62,7 @@ The reference library has one architecture file, 12 taste skills (Layer A — *h
61
62
  | `image-to-code-skill.md` | "Generate the design first, then code it." Pair with one imagegen file below. |
62
63
  | `output-skill.md` | Stacks on any style skill when output is incomplete — placeholders, `// TODO`, half-done components. |
63
64
  | `stitch-skill.md` | Stacks on any style skill for Google Stitch compatibility or a `DESIGN.md` doc export. A complete worked export ships as `stitch-design-example.md`. |
65
+ | `interaction-skill.md` | Stacks on any style skill when work adds or changes interaction or motion. beui.dev-anchored: read the mapped component's source before designing an interaction; reduced motion always. |
64
66
  | `imagegen-frontend-web.md` / `imagegen-frontend-mobile.md` / `imagegen-brandkit.md` | Image-only output (mockup, app-screen concepts, brand board). These NEVER write code — switch to `image-to-code-skill.md` if code is wanted. |
65
67
 
66
68
  ### Layer B — brand design systems (orthogonal to Layer A; stack freely)
@@ -113,6 +115,7 @@ Domains: `product` `style` `typography` `color` `landing` `chart` `ux` `react` `
113
115
  | "Linear-style landing page" | `design/README.md` + `design/linear.app.md` + `design/taste-skill.md` + `perfection/README.md` |
114
116
  | "Premium SaaS hero like Stripe" | `design/README.md` + `design/stripe.md` + `design/soft-skill.md` + `perfection/README.md` |
115
117
  | "Improve this existing dashboard" | `design/README.md` + `design/redesign-skill.md` + `perfection/README.md` |
118
+ | "Add micro-interactions" / "animate this" / "make it feel alive" / "polish the interactions" | `design/README.md` + `design/interaction-skill.md` on top of the current style skill + `perfection/README.md` |
116
119
  | "Build this screenshot / Imagen mock / Stitch output exactly" | `design/README.md` + `design/image-to-code-skill.md` + `perfection/README.md` + `/visual-qa` reference-fidelity mode |
117
120
  | "Audit my site" / "make this page faster" | `perfection/README.md` (+ `perfection/react-perf-tooling.md` if React) |
118
121
  | "Mockup image of a fintech app" — no code | `design/imagegen-frontend-mobile.md` (+ a Layer B brand if named) |