@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
@@ -6,6 +6,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
6
6
  import pytest
7
7
 
8
8
  from app.services.github import _is_binary, fetch_file_content
9
+ from app.services.github_issues import create_issue
9
10
  from app.services.github_pr import _paginate_pulls, compare_branches
10
11
 
11
12
 
@@ -214,3 +215,44 @@ class TestPaginatePullsDedup:
214
215
 
215
216
  assert len(result) == 2
216
217
  assert [pr["id"] for pr in result] == [10, 20]
218
+
219
+
220
+ class TestCreateIssuePatWarning:
221
+ @pytest.fixture
222
+ def github_config(self):
223
+ return {
224
+ "owner": "testorg",
225
+ "repo": "testrepo",
226
+ "branch": "main",
227
+ "token": "ghp_test",
228
+ }
229
+
230
+ async def test_create_issue_warns_when_pat_fallback(self, github_config):
231
+ mock_resp = MagicMock()
232
+ mock_resp.raise_for_status = MagicMock()
233
+ mock_resp.json.return_value = {
234
+ "number": 1,
235
+ "title": "Test",
236
+ "state": "open",
237
+ "body": "",
238
+ "labels": [],
239
+ "user": {"login": "test-user"},
240
+ "created_at": "2026-01-01T00:00:00Z",
241
+ "updated_at": "2026-01-01T00:00:00Z",
242
+ "html_url": "https://github.com/testorg/testrepo/issues/1",
243
+ }
244
+ mock_client = AsyncMock()
245
+ mock_client.post.return_value = mock_resp
246
+
247
+ with (
248
+ patch("app.services.github_issues.get_github_client", return_value=mock_client),
249
+ patch(
250
+ "app.services.github_issues.resolve_token",
251
+ new_callable=AsyncMock,
252
+ return_value="ghp_test",
253
+ ),
254
+ patch("app.services.github_issues.warn_if_pat_used_for_write") as mock_warn,
255
+ ):
256
+ await create_issue(github_config, title="Test")
257
+
258
+ mock_warn.assert_called_once_with("Issue")
@@ -0,0 +1,52 @@
1
+ """Test health endpoint."""
2
+
3
+ from unittest.mock import AsyncMock, patch
4
+
5
+ import pytest
6
+
7
+
8
+ @pytest.mark.asyncio
9
+ async def test_health(client):
10
+ """Health check returns ok with GitHub author diagnostics."""
11
+ resp = await client.get("/api/health")
12
+ assert resp.status_code == 200
13
+ body = resp.json()
14
+ assert body["status"] == "ok"
15
+ assert body["github_app_configured"] is False
16
+ assert body["github_write_author"] == "mock"
17
+
18
+
19
+ @pytest.mark.asyncio
20
+ @patch("app.main.github_write_author_mode", return_value="bot")
21
+ @patch("app.main.is_app_configured", return_value=True)
22
+ async def test_health_when_github_app_configured(
23
+ _mock_configured,
24
+ _mock_mode,
25
+ client,
26
+ ):
27
+ resp = await client.get("/api/health")
28
+ assert resp.status_code == 200
29
+ body = resp.json()
30
+ assert body["github_app_configured"] is True
31
+ assert body["github_write_author"] == "bot"
32
+
33
+
34
+ @pytest.mark.asyncio
35
+ @patch("app.main.get_installation_token", new_callable=AsyncMock, return_value="ghs_test")
36
+ @patch("app.main.is_app_configured", return_value=True)
37
+ async def test_github_app_health_refresh_success(
38
+ _mock_configured,
39
+ _mock_token,
40
+ client,
41
+ ):
42
+ resp = await client.get("/api/health/github-app")
43
+ assert resp.status_code == 200
44
+ assert resp.json()["token_refresh"] == "success"
45
+ assert resp.json()["github_write_author"] == "bot"
46
+
47
+
48
+ @pytest.mark.asyncio
49
+ @patch("app.main.is_app_configured", return_value=False)
50
+ async def test_github_app_health_not_configured(_mock_configured, client):
51
+ resp = await client.get("/api/health/github-app")
52
+ assert resp.status_code == 503
@@ -36,6 +36,49 @@ class TestListIssues:
36
36
  assert resp.status_code == 200
37
37
  assert resp.json()["issues"] == mock_issues
38
38
 
39
+ async def test_list_issues_with_assignee_filter(self, client: AsyncClient, admin_token):
40
+ mock_issues = [
41
+ {"number": 1, "title": "Assigned Issue", "state": "open", "labels": []},
42
+ ]
43
+ with (
44
+ patch("app.routers.issues.settings") as mock_settings,
45
+ patch("app.routers.issues.get_github_config") as mock_config,
46
+ patch("app.routers.issues.list_issues", new_callable=AsyncMock) as mock_list,
47
+ ):
48
+ mock_settings.is_mock_mode.return_value = False
49
+ mock_config.return_value = {"token": "t", "owner": "o", "repo": "r", "branch": "main"}
50
+ mock_list.return_value = mock_issues
51
+ resp = await client.get(
52
+ "/api/issues?assignee=octocat",
53
+ headers=auth_headers(admin_token),
54
+ )
55
+ assert resp.status_code == 200
56
+ mock_list.assert_awaited_once()
57
+ assert mock_list.await_args.kwargs["assignee"] == "octocat"
58
+
59
+ async def test_list_issues_with_assignee_none_filter(self, client: AsyncClient, admin_token):
60
+ with (
61
+ patch("app.routers.issues.settings") as mock_settings,
62
+ patch("app.routers.issues.get_github_config") as mock_config,
63
+ patch("app.routers.issues.list_issues", new_callable=AsyncMock) as mock_list,
64
+ ):
65
+ mock_settings.is_mock_mode.return_value = False
66
+ mock_config.return_value = {"token": "t", "owner": "o", "repo": "r", "branch": "main"}
67
+ mock_list.return_value = []
68
+ resp = await client.get(
69
+ "/api/issues?assignee=none",
70
+ headers=auth_headers(admin_token),
71
+ )
72
+ assert resp.status_code == 200
73
+ assert mock_list.await_args.kwargs["assignee"] == "none"
74
+
75
+ async def test_list_issues_invalid_assignee(self, client: AsyncClient, admin_token):
76
+ resp = await client.get(
77
+ "/api/issues?assignee=invalid-",
78
+ headers=auth_headers(admin_token),
79
+ )
80
+ assert resp.status_code == 422
81
+
39
82
  async def test_list_issues_github_auth_error(self, client: AsyncClient, admin_token):
40
83
  mock_resp = httpx.Response(401, request=httpx.Request("GET", "https://api.github.com"))
41
84
  with (
@@ -235,3 +278,176 @@ class TestListLabels:
235
278
  resp = await client.get("/api/issues/labels", headers=auth_headers(admin_token))
236
279
  assert resp.status_code == 200
237
280
  assert resp.json()["labels"][0]["name"] == "bug"
281
+
282
+
283
+ class TestLabelMutations:
284
+ async def test_update_label_success(self, client: AsyncClient, admin_token):
285
+ mock_updated = {"name": "bug-fixed", "color": "ff0000", "description": "fixed"}
286
+ with (
287
+ patch("app.routers.issues.settings") as mock_settings,
288
+ patch("app.routers.issues.get_github_config") as mock_config,
289
+ patch("app.routers.issues.update_label", new_callable=AsyncMock) as mock_update,
290
+ ):
291
+ mock_settings.is_mock_mode.return_value = False
292
+ mock_config.return_value = {"token": "t", "owner": "o", "repo": "r", "branch": "main"}
293
+ mock_update.return_value = mock_updated
294
+ resp = await client.patch(
295
+ "/api/issues/labels/bug",
296
+ json={"new_name": "bug-fixed", "color": "ff0000"},
297
+ headers=auth_headers(admin_token),
298
+ )
299
+ assert resp.status_code == 200
300
+ assert resp.json()["name"] == "bug-fixed"
301
+ mock_update.assert_awaited_once()
302
+
303
+ async def test_update_label_empty_body(self, client: AsyncClient, admin_token):
304
+ with patch("app.routers.issues.settings") as mock_settings:
305
+ mock_settings.is_mock_mode.return_value = False
306
+ resp = await client.patch(
307
+ "/api/issues/labels/bug",
308
+ json={},
309
+ headers=auth_headers(admin_token),
310
+ )
311
+ assert resp.status_code == 422
312
+
313
+ async def test_update_label_viewer_forbidden(
314
+ self, client: AsyncClient, viewer_token,
315
+ ):
316
+ resp = await client.patch(
317
+ "/api/issues/labels/bug",
318
+ json={"color": "ff0000"},
319
+ headers=auth_headers(viewer_token),
320
+ )
321
+ assert resp.status_code == 403
322
+
323
+ async def test_update_label_mock_mode(self, client: AsyncClient, admin_token):
324
+ with patch("app.routers.issues.settings") as mock_settings:
325
+ mock_settings.is_mock_mode.return_value = True
326
+ resp = await client.patch(
327
+ "/api/issues/labels/bug",
328
+ json={"color": "ff0000"},
329
+ headers=auth_headers(admin_token),
330
+ )
331
+ assert resp.status_code == 400
332
+
333
+ async def test_delete_label_success(self, client: AsyncClient, admin_token):
334
+ with (
335
+ patch("app.routers.issues.settings") as mock_settings,
336
+ patch("app.routers.issues.get_github_config") as mock_config,
337
+ patch("app.routers.issues.delete_label", new_callable=AsyncMock) as mock_delete,
338
+ ):
339
+ mock_settings.is_mock_mode.return_value = False
340
+ mock_config.return_value = {"token": "t", "owner": "o", "repo": "r", "branch": "main"}
341
+ resp = await client.delete(
342
+ "/api/issues/labels/bug",
343
+ headers=auth_headers(admin_token),
344
+ )
345
+ assert resp.status_code == 204
346
+ mock_delete.assert_awaited_once()
347
+
348
+ async def test_delete_label_viewer_forbidden(
349
+ self, client: AsyncClient, viewer_token,
350
+ ):
351
+ resp = await client.delete(
352
+ "/api/issues/labels/bug",
353
+ headers=auth_headers(viewer_token),
354
+ )
355
+ assert resp.status_code == 403
356
+
357
+ async def test_delete_label_mock_mode(self, client: AsyncClient, admin_token):
358
+ with patch("app.routers.issues.settings") as mock_settings:
359
+ mock_settings.is_mock_mode.return_value = True
360
+ resp = await client.delete(
361
+ "/api/issues/labels/bug",
362
+ headers=auth_headers(admin_token),
363
+ )
364
+ assert resp.status_code == 400
365
+
366
+
367
+ class TestIssueComments:
368
+ async def test_list_comments_mock_mode(self, client: AsyncClient, admin_token):
369
+ with patch("app.routers.issues.settings") as mock_settings:
370
+ mock_settings.is_mock_mode.return_value = True
371
+ resp = await client.get(
372
+ "/api/issues/42/comments",
373
+ headers=auth_headers(admin_token),
374
+ )
375
+ assert resp.status_code == 200
376
+ assert resp.json() == {"comments": []}
377
+
378
+ async def test_list_comments_success(self, client: AsyncClient, admin_token):
379
+ mock_comments = [
380
+ {
381
+ "id": 1,
382
+ "body": "First comment",
383
+ "author": "alice",
384
+ "createdAt": "2026-05-19T00:00:00Z",
385
+ "updatedAt": "2026-05-19T00:00:00Z",
386
+ "url": "https://github.com/o/r/issues/42#issuecomment-1",
387
+ },
388
+ ]
389
+ with (
390
+ patch("app.routers.issues.settings") as mock_settings,
391
+ patch("app.routers.issues.get_github_config") as mock_config,
392
+ patch(
393
+ "app.routers.issues.list_issue_comments",
394
+ new_callable=AsyncMock,
395
+ ) as mock_list,
396
+ ):
397
+ mock_settings.is_mock_mode.return_value = False
398
+ mock_config.return_value = {"token": "t", "owner": "o", "repo": "r", "branch": "main"}
399
+ mock_list.return_value = mock_comments
400
+ resp = await client.get(
401
+ "/api/issues/42/comments",
402
+ headers=auth_headers(admin_token),
403
+ )
404
+ assert resp.status_code == 200
405
+ assert resp.json()["comments"] == mock_comments
406
+
407
+ async def test_create_comment_success(self, client: AsyncClient, admin_token):
408
+ mock_created = {
409
+ "id": 2,
410
+ "body": "New comment",
411
+ "author": "bot",
412
+ "createdAt": "2026-05-20T00:00:00Z",
413
+ "updatedAt": "2026-05-20T00:00:00Z",
414
+ "url": "https://github.com/o/r/issues/42#issuecomment-2",
415
+ }
416
+ with (
417
+ patch("app.routers.issues.settings") as mock_settings,
418
+ patch("app.routers.issues.get_github_config") as mock_config,
419
+ patch(
420
+ "app.routers.issues.create_issue_comment",
421
+ new_callable=AsyncMock,
422
+ ) as mock_create,
423
+ ):
424
+ mock_settings.is_mock_mode.return_value = False
425
+ mock_config.return_value = {"token": "t", "owner": "o", "repo": "r", "branch": "main"}
426
+ mock_create.return_value = mock_created
427
+ resp = await client.post(
428
+ "/api/issues/42/comments",
429
+ json={"body": "New comment"},
430
+ headers=auth_headers(admin_token),
431
+ )
432
+ assert resp.status_code == 201
433
+ assert resp.json()["body"] == "New comment"
434
+
435
+ async def test_create_comment_viewer_forbidden(
436
+ self, client: AsyncClient, viewer_token,
437
+ ):
438
+ resp = await client.post(
439
+ "/api/issues/42/comments",
440
+ json={"body": "Forbidden"},
441
+ headers=auth_headers(viewer_token),
442
+ )
443
+ assert resp.status_code == 403
444
+
445
+ async def test_create_comment_mock_mode(self, client: AsyncClient, admin_token):
446
+ with patch("app.routers.issues.settings") as mock_settings:
447
+ mock_settings.is_mock_mode.return_value = True
448
+ resp = await client.post(
449
+ "/api/issues/42/comments",
450
+ json={"body": "test"},
451
+ headers=auth_headers(admin_token),
452
+ )
453
+ assert resp.status_code == 400
@@ -24,6 +24,30 @@ class TestListSessions:
24
24
  resp = await client.get("/api/pr/sessions")
25
25
  assert resp.status_code == 401
26
26
 
27
+ async def test_list_sessions_editor_allowed(
28
+ self, client: AsyncClient, mock_db, editor_token,
29
+ ):
30
+ resp = await client.get(
31
+ "/api/pr/sessions",
32
+ headers=auth_headers(editor_token),
33
+ )
34
+ assert resp.status_code == 200
35
+ data = resp.json()
36
+ assert data["sessions"] == []
37
+ assert data["mock"] is True
38
+
39
+ async def test_list_sessions_viewer_allowed(
40
+ self, client: AsyncClient, mock_db, viewer_token,
41
+ ):
42
+ resp = await client.get(
43
+ "/api/pr/sessions",
44
+ headers=auth_headers(viewer_token),
45
+ )
46
+ assert resp.status_code == 200
47
+ data = resp.json()
48
+ assert data["sessions"] == []
49
+ assert data["mock"] is True
50
+
27
51
 
28
52
  class TestMySession:
29
53
  async def test_my_session_mock_mode(
@@ -529,6 +529,25 @@ class TestCreatePrDraftFlag:
529
529
  call_json = mock_client.post.call_args[1]["json"]
530
530
  assert call_json["draft"] is True
531
531
 
532
+ @pytest.mark.asyncio
533
+ async def test_create_pr_warns_when_pat_fallback(self):
534
+ mock_resp = MagicMock()
535
+ mock_resp.status_code = 201
536
+ mock_resp.json.return_value = {**FAKE_PR, "draft": True}
537
+ mock_resp.raise_for_status = MagicMock()
538
+
539
+ mock_client = AsyncMock()
540
+ mock_client.post = AsyncMock(return_value=mock_resp)
541
+
542
+ with (
543
+ patch("app.services.github_pr.get_github_client", return_value=mock_client),
544
+ patch("app.services.github_pr.is_app_configured", return_value=False),
545
+ patch("app.services.github_pr.warn_if_pat_used_for_write") as mock_warn,
546
+ ):
547
+ await create_pr("title", "head", "main", "body", [], FAKE_CONFIG)
548
+
549
+ mock_warn.assert_called_once_with("Pull request")
550
+
532
551
 
533
552
  class TestMarkPrReady:
534
553
  @pytest.mark.asyncio