@ripla/godd-mcp 1.0.4-canary.8 → 1.0.4

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 (348) hide show
  1. package/README.md +89 -94
  2. package/dist/godd.cjs +349 -233
  3. package/dist/godd.js +2193 -838
  4. package/dist/index.js +152 -122
  5. package/{notes-api → notes/api}/.env.example +6 -1
  6. package/{notes-api → notes/api}/README.md +6 -5
  7. package/{notes-api → notes/api}/app/main.py +29 -2
  8. package/{notes-api → notes/api}/app/routers/auth.py +6 -1
  9. package/{notes-api → notes/api}/app/routers/issues.py +157 -1
  10. package/{notes-api → notes/api}/app/routers/pr.py +2 -2
  11. package/{notes-api → notes/api}/app/services/github_app_token.py +32 -1
  12. package/{notes-api → notes/api}/app/services/github_issues.py +101 -11
  13. package/{notes-api → notes/api}/app/services/github_pr.py +6 -1
  14. package/{notes-api → notes/api}/tests/test_github_app_token.py +49 -1
  15. package/{notes-api → notes/api}/tests/test_github_service.py +42 -0
  16. package/notes/api/tests/test_health.py +52 -0
  17. package/{notes-api → notes/api}/tests/test_issues.py +216 -0
  18. package/{notes-api → notes/api}/tests/test_pr.py +24 -0
  19. package/{notes-api → notes/api}/tests/test_pr_chain.py +19 -0
  20. package/{notes-api → notes/api}/uv.lock +178 -2
  21. package/notes/app/DESIGN.md +273 -0
  22. package/{notes-app → notes/app}/README.md +4 -1
  23. package/notes/app/docker/Dockerfile.e2e +19 -0
  24. package/notes/app/docker/Dockerfile.prod +15 -0
  25. package/notes/app/docker/Dockerfile.test +17 -0
  26. package/notes/app/e2e/file-tree.spec.ts +26 -0
  27. package/notes/app/e2e/file-view.spec.ts +25 -0
  28. package/notes/app/e2e/fixtures.ts +28 -0
  29. package/{notes-app → notes/app}/e2e/global-setup.ts +5 -7
  30. package/notes/app/e2e/login.spec.ts +25 -0
  31. package/notes/app/e2e/pages/login-page.ts +29 -0
  32. package/notes/app/e2e/pages/main-page.ts +29 -0
  33. package/notes/app/e2e/panel-resize-handle.spec.ts +213 -0
  34. package/{notes-app → notes/app}/eslint.config.js +9 -0
  35. package/{notes-app → notes/app}/package.json +0 -3
  36. package/{notes-app → notes/app}/pnpm-workspace.yaml +1 -0
  37. package/notes/app/src/components/CommentPanel.test.tsx +194 -0
  38. package/{notes-app → notes/app}/src/components/CommentPanel.tsx +119 -10
  39. package/notes/app/src/components/CommentSelectionPopover.tsx +26 -0
  40. package/notes/app/src/components/EditToolbar.test.tsx +102 -0
  41. package/{notes-app → notes/app}/src/components/EditToolbar.tsx +5 -54
  42. package/notes/app/src/components/FileInfoPanel.branch-tab.test.tsx +250 -0
  43. package/notes/app/src/components/FileInfoPanel.history-tab.test.tsx +146 -0
  44. package/notes/app/src/components/FileInfoPanel.test.tsx +101 -0
  45. package/{notes-app → notes/app}/src/components/FileInfoPanel.tsx +135 -20
  46. package/notes/app/src/components/IssueCommentThread.test.tsx +93 -0
  47. package/notes/app/src/components/IssueCommentThread.tsx +156 -0
  48. package/notes/app/src/components/IssueDetailView.test.tsx +1118 -0
  49. package/notes/app/src/components/IssueDetailView.tsx +476 -0
  50. package/notes/app/src/components/IssueList.test.tsx +545 -0
  51. package/notes/app/src/components/IssueList.tsx +374 -0
  52. package/{notes-app → notes/app}/src/components/LabelSelector.test.tsx +94 -8
  53. package/notes/app/src/components/LabelSelector.tsx +452 -0
  54. package/{notes-app → notes/app}/src/components/MarkdownEditor.tsx +140 -2
  55. package/notes/app/src/components/PanelResizeHandle.test.tsx +481 -0
  56. package/notes/app/src/components/PanelResizeHandle.tsx +96 -0
  57. package/{notes-app → notes/app}/src/hooks/useEditSession.test.ts +171 -23
  58. package/{notes-app → notes/app}/src/hooks/useEditSession.ts +49 -62
  59. package/notes/app/src/hooks/useMdUpLayout.test.ts +10 -0
  60. package/notes/app/src/hooks/useMdUpLayout.ts +27 -0
  61. package/notes/app/src/hooks/usePeriodicSync.test.ts +244 -0
  62. package/notes/app/src/hooks/usePeriodicSync.ts +83 -0
  63. package/notes/app/src/hooks/useResizablePanelWidth.test.ts +251 -0
  64. package/notes/app/src/hooks/useResizablePanelWidth.ts +167 -0
  65. package/{notes-app → notes/app}/src/lib/api.test.ts +81 -1
  66. package/{notes-app → notes/app}/src/lib/api.ts +98 -4
  67. package/notes/app/src/lib/commentAnchor.test.ts +22 -0
  68. package/notes/app/src/lib/commentAnchor.ts +28 -0
  69. package/notes/app/src/lib/commentHighlight.test.ts +110 -0
  70. package/notes/app/src/lib/commentHighlight.ts +44 -0
  71. package/notes/app/src/lib/github-sync.test.ts +126 -0
  72. package/notes/app/src/lib/github-sync.ts +89 -0
  73. package/notes/app/src/lib/issue-list-utils.test.ts +275 -0
  74. package/notes/app/src/lib/issue-list-utils.ts +135 -0
  75. package/notes/app/src/lib/issue-mobile-layout.test.ts +17 -0
  76. package/notes/app/src/lib/issue-mobile-layout.ts +20 -0
  77. package/notes/app/src/lib/issue-url-sync.test.ts +73 -0
  78. package/notes/app/src/lib/issue-url-sync.ts +43 -0
  79. package/notes/app/src/lib/main-page-default-view.test.ts +37 -0
  80. package/notes/app/src/lib/main-page-default-view.ts +15 -0
  81. package/notes/app/src/lib/resizable-panel.test.ts +199 -0
  82. package/notes/app/src/lib/resizable-panel.ts +136 -0
  83. package/notes/app/src/pages/LoginPage.test.tsx +17 -0
  84. package/notes/app/src/pages/MainPage.branch-modal.test.tsx +226 -0
  85. package/notes/app/src/pages/MainPage.issue-sync.test.tsx +145 -0
  86. package/notes/app/src/pages/MainPage.sidebar.test.tsx +361 -0
  87. package/{notes-app → notes/app}/src/pages/MainPage.tsx +406 -61
  88. package/{notes-app → notes/app}/src/pages/SettingsPage.test.tsx +32 -23
  89. package/{notes-app → notes/app}/src/pages/UserManagementPage.test.tsx +8 -18
  90. package/notes/app/src/test/mocks.ts +156 -0
  91. package/notes/app/src/test/render.tsx +27 -0
  92. package/package.json +3 -5
  93. package/notes-api/tests/test_health.py +0 -11
  94. package/notes-app/docker/Dockerfile.e2e +0 -14
  95. package/notes-app/docker/Dockerfile.prod +0 -12
  96. package/notes-app/docker/Dockerfile.test +0 -12
  97. package/notes-app/e2e/file-tree.spec.ts +0 -29
  98. package/notes-app/e2e/file-view.spec.ts +0 -24
  99. package/notes-app/e2e/login.spec.ts +0 -32
  100. package/notes-app/src/components/IssueDetailView.test.tsx +0 -201
  101. package/notes-app/src/components/IssueDetailView.tsx +0 -318
  102. package/notes-app/src/components/IssueList.test.tsx +0 -93
  103. package/notes-app/src/components/IssueList.tsx +0 -169
  104. package/notes-app/src/components/LabelSelector.tsx +0 -276
  105. package/notes-app/src/pages/LoginPage.test.tsx +0 -29
  106. package/stacks/django-vue.yaml +0 -33
  107. package/stacks/fastapi-react.yaml +0 -160
  108. package/stacks/flutter-firebase.yaml +0 -58
  109. package/stacks/nextjs-prisma.yaml +0 -33
  110. package/stacks/schema.json +0 -144
  111. package/templates/agents/architect.hbs +0 -183
  112. package/templates/agents/auto-documenter.hbs +0 -36
  113. package/templates/agents/backend-developer.hbs +0 -175
  114. package/templates/agents/code-reviewer.hbs +0 -29
  115. package/templates/agents/database-developer.hbs +0 -52
  116. package/templates/agents/debug-specialist.hbs +0 -39
  117. package/templates/agents/environment-setup.hbs +0 -41
  118. package/templates/agents/frontend-developer.hbs +0 -45
  119. package/templates/agents/integration-qa.hbs +0 -26
  120. package/templates/agents/performance-qa.hbs +0 -24
  121. package/templates/agents/pr-writer.hbs +0 -53
  122. package/templates/agents/quality-lead.hbs +0 -26
  123. package/templates/agents/requirements-analyst.hbs +0 -26
  124. package/templates/agents/security-analyst.hbs +0 -21
  125. package/templates/agents/security-reviewer.hbs +0 -20
  126. package/templates/agents/ssot-updater.hbs +0 -45
  127. package/templates/agents/technical-writer.hbs +0 -28
  128. package/templates/agents/unit-test-engineer.hbs +0 -19
  129. package/templates/agents/user-clone.hbs +0 -43
  130. package/templates/github-actions/aws/deploy-notes.yml.hbs +0 -117
  131. package/templates/github-actions/azure/deploy-notes.yml.hbs +0 -78
  132. package/templates/github-actions/gcp/deploy-notes.yml.hbs +0 -76
  133. package/templates/github-actions/vercel-railway/deploy-notes.yml.hbs +0 -49
  134. package/templates/mindsets/agent-stdio.hbs +0 -51
  135. package/templates/mindsets/dart.hbs +0 -39
  136. package/templates/mindsets/ddd-clean-architecture.hbs +0 -52
  137. package/templates/mindsets/electron.hbs +0 -41
  138. package/templates/mindsets/fastapi.hbs +0 -40
  139. package/templates/mindsets/flutter.hbs +0 -56
  140. package/templates/mindsets/kotlin.hbs +0 -46
  141. package/templates/mindsets/postgresql.hbs +0 -39
  142. package/templates/mindsets/python.hbs +0 -39
  143. package/templates/mindsets/react.hbs +0 -51
  144. package/templates/mindsets/swift.hbs +0 -46
  145. package/templates/mindsets/terraform.hbs +0 -53
  146. package/templates/mindsets/typescript.hbs +0 -34
  147. package/templates/mindsets/vite.hbs +0 -37
  148. package/templates/notes-compose.yml +0 -82
  149. package/templates/partials/cogito-geo.hbs +0 -84
  150. package/templates/partials/cogito-godd.hbs +0 -22
  151. package/templates/partials/cogito-grammar.hbs +0 -105
  152. package/templates/partials/cogito-particle.hbs +0 -76
  153. package/templates/partials/cogito-root-ai.hbs +0 -79
  154. package/templates/partials/cogito-root-arch.hbs +0 -75
  155. package/templates/partials/cogito-root-core.hbs +0 -75
  156. package/templates/partials/cogito-root-daily.hbs +0 -58
  157. package/templates/partials/cogito-root-dev.hbs +0 -71
  158. package/templates/partials/cogito-root-devops.hbs +0 -71
  159. package/templates/partials/cogito-root-framework.hbs +0 -80
  160. package/templates/partials/cogito-root-lang.hbs +0 -74
  161. package/templates/partials/godd-core.hbs +0 -50
  162. package/templates/partials/project-context.hbs +0 -52
  163. package/templates/partials/ssot-header.hbs +0 -40
  164. package/templates/partials/ssot-rules.hbs +0 -30
  165. package/templates/prompts/adr.hbs +0 -39
  166. package/templates/prompts/agent-dev-workflow.hbs +0 -34
  167. package/templates/prompts/analyze-report.hbs +0 -36
  168. package/templates/prompts/auto-documentation.hbs +0 -37
  169. package/templates/prompts/check.hbs +0 -52
  170. package/templates/prompts/commit.hbs +0 -96
  171. package/templates/prompts/dev.hbs +0 -127
  172. package/templates/prompts/docs-init.hbs +0 -101
  173. package/templates/prompts/docs-update.hbs +0 -51
  174. package/templates/prompts/git-workflow.hbs +0 -125
  175. package/templates/prompts/impact-analysis.hbs +0 -43
  176. package/templates/prompts/install.hbs +0 -40
  177. package/templates/prompts/new-branch.hbs +0 -61
  178. package/templates/prompts/notes-deploy.hbs +0 -138
  179. package/templates/prompts/pr-analyze.hbs +0 -44
  180. package/templates/prompts/pr-create.hbs +0 -125
  181. package/templates/prompts/push-execute.hbs +0 -83
  182. package/templates/prompts/push.hbs +0 -24
  183. package/templates/prompts/release-notes.hbs +0 -38
  184. package/templates/prompts/requirements-to-business-flow.hbs +0 -29
  185. package/templates/prompts/requirements-to-tickets.hbs +0 -26
  186. package/templates/prompts/review.hbs +0 -126
  187. package/templates/prompts/setup.hbs +0 -247
  188. package/templates/prompts/spec.hbs +0 -35
  189. package/templates/prompts/specification-to-tickets.hbs +0 -24
  190. package/templates/prompts/submit.hbs +0 -143
  191. package/templates/prompts/sync.hbs +0 -63
  192. package/templates/prompts/test-plan.hbs +0 -56
  193. package/templates/scripts/aws/terraform-backend-setup.sh.hbs +0 -149
  194. package/templates/terraform/aws/alb.tf.hbs +0 -58
  195. package/templates/terraform/aws/backend.tf.hbs +0 -10
  196. package/templates/terraform/aws/cloudfront.tf.hbs +0 -96
  197. package/templates/terraform/aws/ecr.tf.hbs +0 -30
  198. package/templates/terraform/aws/ecs.tf.hbs +0 -142
  199. package/templates/terraform/aws/iam.tf.hbs +0 -88
  200. package/templates/terraform/aws/local.tf.hbs +0 -34
  201. package/templates/terraform/aws/output.tf.hbs +0 -49
  202. package/templates/terraform/aws/provider.tf.hbs +0 -26
  203. package/templates/terraform/aws/rds.tf.hbs +0 -38
  204. package/templates/terraform/aws/s3.tf.hbs +0 -34
  205. package/templates/terraform/aws/secrets.tf.hbs +0 -53
  206. package/templates/terraform/aws/security_groups.tf.hbs +0 -81
  207. package/templates/terraform/aws/vpc.tf.hbs +0 -63
  208. package/templates/terraform/azure/backend.tf.hbs +0 -8
  209. package/templates/terraform/azure/iam.tf.hbs +0 -36
  210. package/templates/terraform/azure/main.tf.hbs +0 -203
  211. package/templates/terraform/azure/output.tf.hbs +0 -19
  212. package/templates/terraform/azure/provider.tf.hbs +0 -19
  213. package/templates/terraform/gcp/backend.tf.hbs +0 -6
  214. package/templates/terraform/gcp/iam.tf.hbs +0 -47
  215. package/templates/terraform/gcp/main.tf.hbs +0 -175
  216. package/templates/terraform/gcp/output.tf.hbs +0 -15
  217. package/templates/terraform/gcp/provider.tf.hbs +0 -19
  218. package/templates/terraform/vercel-railway/main.tf.hbs +0 -64
  219. package/templates/terraform/vercel-railway/output.tf.hbs +0 -11
  220. /package/{notes-api → notes/api}/.dockerignore +0 -0
  221. /package/{notes-api → notes/api}/alembic/README +0 -0
  222. /package/{notes-api → notes/api}/alembic/env.py +0 -0
  223. /package/{notes-api → notes/api}/alembic/script.py.mako +0 -0
  224. /package/{notes-api → notes/api}/alembic/versions/001_initial_notes_tables.py +0 -0
  225. /package/{notes-api → notes/api}/alembic/versions/002_add_performance_indexes.py +0 -0
  226. /package/{notes-api → notes/api}/alembic/versions/003_add_yjs_documents.py +0 -0
  227. /package/{notes-api → notes/api}/alembic/versions/004_add_comments.py +0 -0
  228. /package/{notes-api → notes/api}/alembic/versions/005_add_github_username.py +0 -0
  229. /package/{notes-api → notes/api}/alembic/versions/006_add_check_constraints.py +0 -0
  230. /package/{notes-api → notes/api}/alembic.ini +0 -0
  231. /package/{notes-api → notes/api}/app/__init__.py +0 -0
  232. /package/{notes-api → notes/api}/app/config.py +0 -0
  233. /package/{notes-api → notes/api}/app/database.py +0 -0
  234. /package/{notes-api → notes/api}/app/http_client.py +0 -0
  235. /package/{notes-api → notes/api}/app/models/__init__.py +0 -0
  236. /package/{notes-api → notes/api}/app/models/audit.py +0 -0
  237. /package/{notes-api → notes/api}/app/models/base.py +0 -0
  238. /package/{notes-api → notes/api}/app/models/collab.py +0 -0
  239. /package/{notes-api → notes/api}/app/models/comment.py +0 -0
  240. /package/{notes-api → notes/api}/app/models/session.py +0 -0
  241. /package/{notes-api → notes/api}/app/models/setting.py +0 -0
  242. /package/{notes-api → notes/api}/app/models/user.py +0 -0
  243. /package/{notes-api → notes/api}/app/path_validation.py +0 -0
  244. /package/{notes-api → notes/api}/app/routers/__init__.py +0 -0
  245. /package/{notes-api → notes/api}/app/routers/collab.py +0 -0
  246. /package/{notes-api → notes/api}/app/routers/comments.py +0 -0
  247. /package/{notes-api → notes/api}/app/routers/files.py +0 -0
  248. /package/{notes-api → notes/api}/app/routers/settings.py +0 -0
  249. /package/{notes-api → notes/api}/app/routers/tree.py +0 -0
  250. /package/{notes-api → notes/api}/app/routers/upload.py +0 -0
  251. /package/{notes-api → notes/api}/app/routers/users.py +0 -0
  252. /package/{notes-api → notes/api}/app/schemas/__init__.py +0 -0
  253. /package/{notes-api → notes/api}/app/schemas/auth.py +0 -0
  254. /package/{notes-api → notes/api}/app/schemas/user.py +0 -0
  255. /package/{notes-api → notes/api}/app/security.py +0 -0
  256. /package/{notes-api → notes/api}/app/services/__init__.py +0 -0
  257. /package/{notes-api → notes/api}/app/services/audit.py +0 -0
  258. /package/{notes-api → notes/api}/app/services/business_date.py +0 -0
  259. /package/{notes-api → notes/api}/app/services/collab.py +0 -0
  260. /package/{notes-api → notes/api}/app/services/github.py +0 -0
  261. /package/{notes-api → notes/api}/app/services/pr_chain.py +0 -0
  262. /package/{notes-api → notes/api}/app/startup.py +0 -0
  263. /package/{notes-api → notes/api}/docker/Dockerfile +0 -0
  264. /package/{notes-api → notes/api}/docker/Dockerfile.test +0 -0
  265. /package/{notes-api → notes/api}/pyproject.toml +0 -0
  266. /package/{notes-api → notes/api}/tests/conftest.py +0 -0
  267. /package/{notes-api → notes/api}/tests/test_audit.py +0 -0
  268. /package/{notes-api → notes/api}/tests/test_auth.py +0 -0
  269. /package/{notes-api → notes/api}/tests/test_business_date.py +0 -0
  270. /package/{notes-api → notes/api}/tests/test_collab.py +0 -0
  271. /package/{notes-api → notes/api}/tests/test_comments.py +0 -0
  272. /package/{notes-api → notes/api}/tests/test_config_ssl.py +0 -0
  273. /package/{notes-api → notes/api}/tests/test_config_warnings.py +0 -0
  274. /package/{notes-api → notes/api}/tests/test_files.py +0 -0
  275. /package/{notes-api → notes/api}/tests/test_path_validation.py +0 -0
  276. /package/{notes-api → notes/api}/tests/test_security.py +0 -0
  277. /package/{notes-api → notes/api}/tests/test_settings.py +0 -0
  278. /package/{notes-api → notes/api}/tests/test_tree.py +0 -0
  279. /package/{notes-api → notes/api}/tests/test_upload.py +0 -0
  280. /package/{notes-api → notes/api}/tests/test_users.py +0 -0
  281. /package/{notes-app → notes/app}/.dockerignore +0 -0
  282. /package/{notes-app → notes/app}/index.html +0 -0
  283. /package/{notes-app → notes/app}/nginx.conf +0 -0
  284. /package/{notes-app → notes/app}/package-lock.json +0 -0
  285. /package/{notes-app → notes/app}/playwright.config.ts +0 -0
  286. /package/{notes-app → notes/app}/pnpm-lock.yaml +0 -0
  287. /package/{notes-app → notes/app}/src/App.tsx +0 -0
  288. /package/{notes-app → notes/app}/src/components/BranchSelectorModal.tsx +0 -0
  289. /package/{notes-app → notes/app}/src/components/CodeBlockView.test.tsx +0 -0
  290. /package/{notes-app → notes/app}/src/components/CodeBlockView.tsx +0 -0
  291. /package/{notes-app → notes/app}/src/components/CollabStatus.tsx +0 -0
  292. /package/{notes-app → notes/app}/src/components/DiffPreview.tsx +0 -0
  293. /package/{notes-app → notes/app}/src/components/DrawioEditor.tsx +0 -0
  294. /package/{notes-app → notes/app}/src/components/DrawioViewer.tsx +0 -0
  295. /package/{notes-app → notes/app}/src/components/ErrorBoundary.test.tsx +0 -0
  296. /package/{notes-app → notes/app}/src/components/ErrorBoundary.tsx +0 -0
  297. /package/{notes-app → notes/app}/src/components/FileContentView.tsx +0 -0
  298. /package/{notes-app → notes/app}/src/components/FileContextMenu.test.tsx +0 -0
  299. /package/{notes-app → notes/app}/src/components/FileContextMenu.tsx +0 -0
  300. /package/{notes-app → notes/app}/src/components/FileDialogs.test.tsx +0 -0
  301. /package/{notes-app → notes/app}/src/components/FileDialogs.tsx +0 -0
  302. /package/{notes-app → notes/app}/src/components/SaveStatusIndicator.test.tsx +0 -0
  303. /package/{notes-app → notes/app}/src/components/SaveStatusIndicator.tsx +0 -0
  304. /package/{notes-app → notes/app}/src/components/Skeleton.tsx +0 -0
  305. /package/{notes-app → notes/app}/src/components/SpreadsheetEditor.test.tsx +0 -0
  306. /package/{notes-app → notes/app}/src/components/SpreadsheetEditor.tsx +0 -0
  307. /package/{notes-app → notes/app}/src/components/TextEditor.tsx +0 -0
  308. /package/{notes-app → notes/app}/src/components/ToastContainer.tsx +0 -0
  309. /package/{notes-app → notes/app}/src/components/TreeNode.tsx +0 -0
  310. /package/{notes-app → notes/app}/src/contexts/AuthContext.test.tsx +0 -0
  311. /package/{notes-app → notes/app}/src/contexts/AuthContext.tsx +0 -0
  312. /package/{notes-app → notes/app}/src/contexts/ToastContext.test.ts +0 -0
  313. /package/{notes-app → notes/app}/src/contexts/ToastContext.tsx +0 -0
  314. /package/{notes-app → notes/app}/src/hooks/useAutoSave.test.ts +0 -0
  315. /package/{notes-app → notes/app}/src/hooks/useAutoSave.ts +0 -0
  316. /package/{notes-app → notes/app}/src/hooks/useCollaboration.ts +0 -0
  317. /package/{notes-app → notes/app}/src/hooks/useComments.ts +0 -0
  318. /package/{notes-app → notes/app}/src/hooks/useYText.ts +0 -0
  319. /package/{notes-app → notes/app}/src/lib/branch-diff.test.ts +0 -0
  320. /package/{notes-app → notes/app}/src/lib/branch-diff.ts +0 -0
  321. /package/{notes-app → notes/app}/src/lib/created-file.test.ts +0 -0
  322. /package/{notes-app → notes/app}/src/lib/created-file.ts +0 -0
  323. /package/{notes-app → notes/app}/src/lib/csv-utils.test.ts +0 -0
  324. /package/{notes-app → notes/app}/src/lib/csv-utils.ts +0 -0
  325. /package/{notes-app → notes/app}/src/lib/deepLinkPathToSearch.test.ts +0 -0
  326. /package/{notes-app → notes/app}/src/lib/deepLinkPathToSearch.ts +0 -0
  327. /package/{notes-app → notes/app}/src/lib/draft-storage.test.ts +0 -0
  328. /package/{notes-app → notes/app}/src/lib/draft-storage.ts +0 -0
  329. /package/{notes-app → notes/app}/src/lib/mermaid-render.ts +0 -0
  330. /package/{notes-app → notes/app}/src/lib/postLoginRedirect.test.ts +0 -0
  331. /package/{notes-app → notes/app}/src/lib/postLoginRedirect.ts +0 -0
  332. /package/{notes-app → notes/app}/src/lib/tree-utils.ts +0 -0
  333. /package/{notes-app → notes/app}/src/lib/user-colors.ts +0 -0
  334. /package/{notes-app → notes/app}/src/lib/xlsx-utils.test.ts +0 -0
  335. /package/{notes-app → notes/app}/src/lib/xlsx-utils.ts +0 -0
  336. /package/{notes-app → notes/app}/src/main.tsx +0 -0
  337. /package/{notes-app → notes/app}/src/pages/LoginPage.tsx +0 -0
  338. /package/{notes-app → notes/app}/src/pages/MainPage.insertChildEntry.test.ts +0 -0
  339. /package/{notes-app → notes/app}/src/pages/SettingsPage.tsx +0 -0
  340. /package/{notes-app → notes/app}/src/pages/UserManagementPage.tsx +0 -0
  341. /package/{notes-app → notes/app}/src/styles/globals.css +0 -0
  342. /package/{notes-app → notes/app}/src/types.ts +0 -0
  343. /package/{notes-app → notes/app}/src/vite-env.d.ts +0 -0
  344. /package/{notes-app → notes/app}/tsconfig.json +0 -0
  345. /package/{notes-app → notes/app}/tsconfig.node.json +0 -0
  346. /package/{notes-app → notes/app}/vite.config.js +0 -0
  347. /package/{notes-app → notes/app}/vite.config.ts +0 -0
  348. /package/{notes-app → notes/app}/vitest.config.ts +0 -0
@@ -0,0 +1,250 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { render, screen, fireEvent, waitFor, act } from "@testing-library/react";
3
+ import type { FileContent } from "@/types";
4
+
5
+ const triggerPeriodicSync = vi.hoisted(() => vi.fn());
6
+
7
+ vi.mock("@/hooks/usePeriodicSync", () => {
8
+ // eslint-disable-next-line @typescript-eslint/no-require-imports -- mock factory 制約
9
+ const { useEffect, useRef } = require("react") as typeof import("react");
10
+ return {
11
+ // 実フック(usePeriodicSync.ts)の即時 sync 挙動を忠実に再現する:
12
+ // onSync は ref 捕捉し、effect 依存は実フックと同じ [enabled, intervalMs, skipInitialSync]。
13
+ // enabled 時の effect setup(初回マウント / enabled false→true 遷移)で onSync を発火し、
14
+ // 初回マウントは skipInitialSync で抑制する。これにより「mount 直後の foreground load 中に
15
+ // 即時 background poll が走る」競合(#934)を再現する。
16
+ usePeriodicSync: ({
17
+ onSync,
18
+ enabled,
19
+ intervalMs,
20
+ skipInitialSync,
21
+ }: {
22
+ onSync: () => void;
23
+ enabled: boolean;
24
+ intervalMs: number;
25
+ skipInitialSync?: boolean;
26
+ }) => {
27
+ const onSyncRef = useRef(onSync);
28
+ const isInitialMountRef = useRef(true);
29
+ useEffect(() => {
30
+ onSyncRef.current = onSync;
31
+ }, [onSync]);
32
+ useEffect(() => {
33
+ triggerPeriodicSync.mockImplementation(() => {
34
+ if (enabled) onSyncRef.current();
35
+ });
36
+ const isInitialMount = isInitialMountRef.current;
37
+ isInitialMountRef.current = false;
38
+ if (!enabled || intervalMs <= 0) return;
39
+ if (skipInitialSync && isInitialMount) return;
40
+ onSyncRef.current();
41
+ }, [enabled, intervalMs, skipInitialSync]);
42
+ },
43
+ };
44
+ });
45
+
46
+ vi.mock("@/lib/api", () => ({
47
+ fetchHistoryApi: vi.fn().mockResolvedValue([]),
48
+ fetchBranchStatusApi: vi.fn(),
49
+ fetchSessionsApi: vi.fn(),
50
+ getErrorMessage: vi.fn((e: unknown, fallback?: string) => {
51
+ if (e instanceof Error) return e.message;
52
+ return fallback ?? String(e);
53
+ }),
54
+ isAbortError: vi.fn(() => false),
55
+ }));
56
+
57
+ import { fetchBranchStatusApi, fetchSessionsApi, isAbortError } from "@/lib/api";
58
+ import FileInfoPanel from "./FileInfoPanel";
59
+
60
+ const mockFetchBranchStatus = vi.mocked(fetchBranchStatusApi);
61
+ const mockFetchSessions = vi.mocked(fetchSessionsApi);
62
+ const mockIsAbortError = vi.mocked(isAbortError);
63
+
64
+ const mockFile: FileContent = {
65
+ path: "docs/readme.md",
66
+ content: "# Hello",
67
+ encoding: "utf-8",
68
+ size: 7,
69
+ };
70
+
71
+ const MOCK_BRANCH_STATUS = {
72
+ branch: "main",
73
+ ahead: 0,
74
+ behind: 0,
75
+ prStatus: null,
76
+ };
77
+
78
+ const panelProps = (syncEnabled: boolean) => ({
79
+ fileContent: mockFile,
80
+ collabUsers: [],
81
+ onClose: vi.fn(),
82
+ syncEnabled,
83
+ });
84
+
85
+ function openBranchTab() {
86
+ fireEvent.click(screen.getByText("ブランチ"));
87
+ }
88
+
89
+ describe("FileInfoPanel — BranchTab", () => {
90
+ beforeEach(() => {
91
+ vi.clearAllMocks();
92
+ mockFetchSessions.mockResolvedValue([]);
93
+ mockFetchBranchStatus.mockResolvedValue(MOCK_BRANCH_STATUS);
94
+ mockIsAbortError.mockImplementation(
95
+ (error: unknown) => error instanceof Error && error.name === "AbortError",
96
+ );
97
+ });
98
+
99
+ it("mount 直後 foreground 取得中に即時 background sync が失敗しても foreground SUCCESS が破棄されない(#934)", async () => {
100
+ let resolveForeground: ((value: typeof MOCK_BRANCH_STATUS) => void) | undefined;
101
+ let branchCalls = 0;
102
+ mockFetchBranchStatus.mockImplementation(() => {
103
+ branchCalls += 1;
104
+ // call1 = foreground 初回 load(保留), call2 = 即時 background poll(失敗)
105
+ if (branchCalls === 1) {
106
+ return new Promise((resolve) => {
107
+ resolveForeground = resolve;
108
+ });
109
+ }
110
+ return Promise.reject(new Error("502 Bad Gateway"));
111
+ });
112
+
113
+ const { rerender } = render(<FileInfoPanel {...panelProps(false)} />);
114
+ openBranchTab();
115
+
116
+ expect(screen.getByText("読み込み中…")).toBeTruthy();
117
+
118
+ // enabled false→true 遷移で即時 background poll が発火し、foreground と競合する
119
+ await act(async () => {
120
+ rerender(<FileInfoPanel {...panelProps(true)} />);
121
+ await Promise.resolve();
122
+ });
123
+
124
+ // 競合が実際に再現されたこと(foreground load + 即時 background poll)を固定する
125
+ await waitFor(() => {
126
+ expect(mockFetchBranchStatus).toHaveBeenCalledTimes(2);
127
+ });
128
+ // background poll 失敗は loading を解除しない(loading は foreground load のみが管理)
129
+ expect(screen.getByText("読み込み中…")).toBeTruthy();
130
+
131
+ await act(async () => {
132
+ resolveForeground?.(MOCK_BRANCH_STATUS);
133
+ await Promise.resolve();
134
+ });
135
+
136
+ await waitFor(() => {
137
+ expect(screen.getByText("現在のブランチ")).toBeTruthy();
138
+ });
139
+ expect(screen.queryByText("データなし")).toBeNull();
140
+ expect(screen.queryByText(/502 Bad Gateway/)).toBeNull();
141
+ });
142
+
143
+ it("より新しい background poll が先に成功したら、後着の古い foreground load では上書きしない(#949 / REQ-016-AC-13)", async () => {
144
+ const POLL_STATUS = { ...MOCK_BRANCH_STATUS, branch: "poll-newer" };
145
+ const STALE_FOREGROUND_STATUS = { ...MOCK_BRANCH_STATUS, branch: "stale-foreground" };
146
+ let resolveForeground: ((value: typeof MOCK_BRANCH_STATUS) => void) | undefined;
147
+ let branchCalls = 0;
148
+ mockFetchBranchStatus.mockImplementation(() => {
149
+ branchCalls += 1;
150
+ // call1 = foreground 初回 load(後着・保留・古い), call2 = より新しい background poll(先着・成功)
151
+ if (branchCalls === 1) {
152
+ return new Promise((resolve) => {
153
+ resolveForeground = resolve;
154
+ });
155
+ }
156
+ return Promise.resolve(POLL_STATUS);
157
+ });
158
+
159
+ const { rerender } = render(<FileInfoPanel {...panelProps(false)} />);
160
+ openBranchTab();
161
+
162
+ // 後から始まった background poll を先に成功させる(より新しいデータ)
163
+ await act(async () => {
164
+ rerender(<FileInfoPanel {...panelProps(true)} />);
165
+ await Promise.resolve();
166
+ });
167
+
168
+ // foreground load + 即時 background poll が実際に走ったことを固定する
169
+ await waitFor(() => {
170
+ expect(mockFetchBranchStatus).toHaveBeenCalledTimes(2);
171
+ });
172
+ // 後着の古い foreground SUCCESS が解決しても、より新しい poll の結果を上書きしない(freshness 後勝ち)
173
+ await act(async () => {
174
+ resolveForeground?.(STALE_FOREGROUND_STATUS);
175
+ await Promise.resolve();
176
+ });
177
+
178
+ await waitFor(() => {
179
+ expect(screen.getByText("poll-newer")).toBeTruthy();
180
+ });
181
+ expect(screen.queryByText("stale-foreground")).toBeNull();
182
+ expect(screen.queryByText("データなし")).toBeNull();
183
+ });
184
+
185
+ it("background の AbortError でも foreground SUCCESS が破棄されない", async () => {
186
+ const abortError = new DOMException("The operation was aborted", "AbortError");
187
+ let resolveForeground: ((value: typeof MOCK_BRANCH_STATUS) => void) | undefined;
188
+ let branchCalls = 0;
189
+ mockFetchBranchStatus.mockImplementation(() => {
190
+ branchCalls += 1;
191
+ if (branchCalls === 1) {
192
+ return new Promise((resolve) => {
193
+ resolveForeground = resolve;
194
+ });
195
+ }
196
+ return Promise.reject(abortError);
197
+ });
198
+
199
+ const { rerender } = render(<FileInfoPanel {...panelProps(false)} />);
200
+ openBranchTab();
201
+
202
+ expect(screen.getByText("読み込み中…")).toBeTruthy();
203
+
204
+ await act(async () => {
205
+ rerender(<FileInfoPanel {...panelProps(true)} />);
206
+ await Promise.resolve();
207
+ });
208
+
209
+ // foreground load + 即時 background poll(AbortError)が実際に走ったことを固定する
210
+ await waitFor(() => {
211
+ expect(mockFetchBranchStatus).toHaveBeenCalledTimes(2);
212
+ });
213
+
214
+ await act(async () => {
215
+ resolveForeground?.(MOCK_BRANCH_STATUS);
216
+ await Promise.resolve();
217
+ });
218
+
219
+ await waitFor(() => {
220
+ expect(screen.getByText("現在のブランチ")).toBeTruthy();
221
+ });
222
+ expect(screen.queryByText("データなし")).toBeNull();
223
+ });
224
+
225
+ it("背景 sync 失敗時は error を表示せず直前状態を維持する(REQ-016-AC-06)", async () => {
226
+ const { rerender } = render(<FileInfoPanel {...panelProps(false)} />);
227
+ openBranchTab();
228
+
229
+ await waitFor(() => {
230
+ expect(screen.getByText("現在のブランチ")).toBeTruthy();
231
+ });
232
+
233
+ mockFetchBranchStatus.mockRejectedValue(new Error("502 Bad Gateway"));
234
+
235
+ // enabled 有効化で即時 poll(失敗)、さらに interval 相当の poll(失敗)を発火
236
+ await act(async () => {
237
+ rerender(<FileInfoPanel {...panelProps(true)} />);
238
+ await Promise.resolve();
239
+ });
240
+ await act(async () => {
241
+ triggerPeriodicSync();
242
+ await Promise.resolve();
243
+ });
244
+
245
+ await waitFor(() => {
246
+ expect(screen.getByText("現在のブランチ")).toBeTruthy();
247
+ });
248
+ expect(screen.queryByText(/502 Bad Gateway/)).toBeNull();
249
+ });
250
+ });
@@ -0,0 +1,146 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { render, screen, fireEvent, waitFor, act } from "@testing-library/react";
3
+ import type { FileContent } from "@/types";
4
+ import type { CommitEntry } from "@/lib/api";
5
+
6
+ vi.mock("@/lib/api", () => ({
7
+ fetchHistoryApi: vi.fn(),
8
+ fetchBranchStatusApi: vi.fn().mockResolvedValue(null),
9
+ fetchSessionsApi: vi.fn().mockResolvedValue([]),
10
+ getErrorMessage: vi.fn((e: unknown, fallback?: string) => {
11
+ if (e instanceof Error) return e.message;
12
+ return fallback ?? String(e);
13
+ }),
14
+ isAbortError: vi.fn(
15
+ (error: unknown) => error instanceof Error && error.name === "AbortError",
16
+ ),
17
+ }));
18
+
19
+ import { fetchHistoryApi } from "@/lib/api";
20
+ import FileInfoPanel from "./FileInfoPanel";
21
+
22
+ const mockFetchHistory = vi.mocked(fetchHistoryApi);
23
+
24
+ const fileA: FileContent = {
25
+ path: "docs/a.md",
26
+ content: "# A",
27
+ encoding: "utf-8",
28
+ size: 3,
29
+ };
30
+
31
+ const fileB: FileContent = {
32
+ path: "docs/b.md",
33
+ content: "# B",
34
+ encoding: "utf-8",
35
+ size: 3,
36
+ };
37
+
38
+ const historyA: CommitEntry[] = [
39
+ { sha: "aaaaaaa1234567", message: "commit-A", author: "alice", date: "2026-06-01T00:00:00Z" },
40
+ ];
41
+ const historyB: CommitEntry[] = [
42
+ { sha: "bbbbbbb1234567", message: "commit-B", author: "bob", date: "2026-06-02T00:00:00Z" },
43
+ ];
44
+
45
+ const panelProps = (fileContent: FileContent) => ({
46
+ fileContent,
47
+ collabUsers: [],
48
+ onClose: vi.fn(),
49
+ });
50
+
51
+ function openHistoryTab() {
52
+ fireEvent.click(screen.getByText("履歴"));
53
+ }
54
+
55
+ describe("FileInfoPanel — HistoryTab in-flight 競合防止", () => {
56
+ beforeEach(() => {
57
+ vi.clearAllMocks();
58
+ });
59
+
60
+ it("ファイル切替後に後着した旧ファイルの応答で上書きされない", async () => {
61
+ let resolveA: ((value: CommitEntry[]) => void) | undefined;
62
+ mockFetchHistory.mockImplementation((path: string) => {
63
+ if (path === fileA.path) {
64
+ return new Promise<CommitEntry[]>((resolve) => {
65
+ resolveA = resolve;
66
+ });
67
+ }
68
+ return Promise.resolve(historyB);
69
+ });
70
+
71
+ const { rerender } = render(<FileInfoPanel {...panelProps(fileA)} />);
72
+ openHistoryTab();
73
+
74
+ // A 向け取得は pending(読み込み中)
75
+ expect(screen.getByText("読み込み中…")).toBeTruthy();
76
+
77
+ // ファイル B へ切替 → B の履歴が表示される
78
+ rerender(<FileInfoPanel {...panelProps(fileB)} />);
79
+ await waitFor(() => {
80
+ expect(screen.getByText("commit-B")).toBeTruthy();
81
+ });
82
+
83
+ // A 向けの in-flight 応答が後着しても無視される
84
+ await act(async () => {
85
+ resolveA?.(historyA);
86
+ await Promise.resolve();
87
+ });
88
+
89
+ expect(screen.getByText("commit-B")).toBeTruthy();
90
+ expect(screen.queryByText("commit-A")).toBeNull();
91
+ });
92
+
93
+ // unmount 後の後着応答(解決・棄却の両系)でクリーンに teardown されることを確認する。
94
+ // React 18+ は unmount 後の dispatch を黙って no-op にするため、mountedRef ガードの
95
+ // 有無は console 出力には現れない。本テストは「teardown 時にエラー/未処理 rejection が
96
+ // 表面化しない」ことの smoke test として機能する。
97
+ it.each(["解決", "棄却"] as const)(
98
+ "in-flight 中に unmount → 後着応答が%sしてもエラーが表面化しない",
99
+ async (mode) => {
100
+ let resolveA: ((value: CommitEntry[]) => void) | undefined;
101
+ let rejectA: ((reason: unknown) => void) | undefined;
102
+ mockFetchHistory.mockImplementation(
103
+ () =>
104
+ new Promise<CommitEntry[]>((resolve, reject) => {
105
+ resolveA = resolve;
106
+ rejectA = reject;
107
+ }),
108
+ );
109
+ const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
110
+
111
+ const { unmount } = render(<FileInfoPanel {...panelProps(fileA)} />);
112
+ openHistoryTab();
113
+ expect(screen.getByText("読み込み中…")).toBeTruthy();
114
+
115
+ unmount();
116
+
117
+ await act(async () => {
118
+ if (mode === "解決") resolveA?.(historyA);
119
+ else rejectA?.(new Error("late failure"));
120
+ await Promise.resolve();
121
+ });
122
+
123
+ expect(errorSpy).not.toHaveBeenCalled();
124
+ errorSpy.mockRestore();
125
+ },
126
+ );
127
+
128
+ it("再試行ボタンで履歴を再取得する", async () => {
129
+ mockFetchHistory
130
+ .mockRejectedValueOnce(new Error("履歴の取得に失敗しました"))
131
+ .mockResolvedValueOnce(historyA);
132
+
133
+ render(<FileInfoPanel {...panelProps(fileA)} />);
134
+ openHistoryTab();
135
+
136
+ await waitFor(() => {
137
+ expect(screen.getByText("履歴の取得に失敗しました")).toBeTruthy();
138
+ });
139
+
140
+ fireEvent.click(screen.getByText("再試行"));
141
+
142
+ await waitFor(() => {
143
+ expect(screen.getByText("commit-A")).toBeTruthy();
144
+ });
145
+ });
146
+ });
@@ -0,0 +1,101 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { render, screen } from "@testing-library/react";
3
+ import FileInfoPanel from "./FileInfoPanel";
4
+ import type { FileContent } from "@/types";
5
+
6
+ const mockFile: FileContent = {
7
+ path: "docs/readme.md",
8
+ content: "# Hello",
9
+ encoding: "utf-8",
10
+ size: 7,
11
+ };
12
+
13
+ describe("FileInfoPanel", () => {
14
+ it("panelResize.width を aside の inline width に適用する", () => {
15
+ const { container } = render(
16
+ <FileInfoPanel
17
+ fileContent={mockFile}
18
+ collabUsers={[]}
19
+ onClose={vi.fn()}
20
+ panelResize={{
21
+ width: 400,
22
+ minWidth: 240,
23
+ maxWidth: 560,
24
+ onPointerDown: vi.fn(),
25
+ onWidthChange: vi.fn(),
26
+ }}
27
+ />,
28
+ );
29
+
30
+ const aside = container.querySelector("aside");
31
+ expect(aside?.getAttribute("style")).toContain("width: 400px");
32
+ });
33
+
34
+ it("panelResize 指定時にリサイズハンドルを表示する", () => {
35
+ render(
36
+ <FileInfoPanel
37
+ fileContent={mockFile}
38
+ collabUsers={[]}
39
+ onClose={vi.fn()}
40
+ panelResize={{
41
+ width: 360,
42
+ minWidth: 240,
43
+ maxWidth: 560,
44
+ onPointerDown: vi.fn(),
45
+ onWidthChange: vi.fn(),
46
+ }}
47
+ />,
48
+ );
49
+
50
+ expect(
51
+ screen.getByRole("slider", { name: "ファイル情報パネルの幅を変更" }),
52
+ ).toBeTruthy();
53
+ });
54
+
55
+ it("showResizeHandle: false のとき幅は適用するがハンドルは非表示", () => {
56
+ const { container } = render(
57
+ <FileInfoPanel
58
+ fileContent={mockFile}
59
+ collabUsers={[]}
60
+ onClose={vi.fn()}
61
+ panelResize={{
62
+ width: 380,
63
+ minWidth: 240,
64
+ maxWidth: 560,
65
+ onPointerDown: vi.fn(),
66
+ onWidthChange: vi.fn(),
67
+ showResizeHandle: false,
68
+ }}
69
+ />,
70
+ );
71
+
72
+ expect(container.querySelector("aside")?.getAttribute("style")).toContain("width: 380px");
73
+ expect(screen.queryByRole("slider")).toBeNull();
74
+ });
75
+
76
+ it("panelResize 未指定時はリサイズハンドルを表示しない", () => {
77
+ render(
78
+ <FileInfoPanel
79
+ fileContent={mockFile}
80
+ collabUsers={[]}
81
+ onClose={vi.fn()}
82
+ />,
83
+ );
84
+
85
+ expect(screen.queryByRole("slider")).toBeNull();
86
+ });
87
+
88
+ it("md+ 用に aside を relative 配置する", () => {
89
+ const { container } = render(
90
+ <FileInfoPanel
91
+ fileContent={mockFile}
92
+ collabUsers={[]}
93
+ onClose={vi.fn()}
94
+ />,
95
+ );
96
+
97
+ const aside = container.querySelector("aside");
98
+ expect(aside?.className).toContain("md:relative");
99
+ expect(aside?.className).not.toContain("md:static");
100
+ });
101
+ });