@assistkick/create 1.10.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/dist/src/scaffolder.d.ts +12 -1
  2. package/dist/src/scaffolder.js +40 -3
  3. package/dist/src/scaffolder.js.map +1 -1
  4. package/package.json +1 -1
  5. package/templates/assistkick-product-system/package.json +1 -1
  6. package/templates/assistkick-product-system/packages/backend/package.json +1 -0
  7. package/templates/assistkick-product-system/packages/backend/src/mcp/permission_mcp_server.ts +196 -0
  8. package/templates/assistkick-product-system/packages/backend/src/routes/agents.ts +31 -7
  9. package/templates/assistkick-product-system/packages/backend/src/routes/auth.ts +15 -12
  10. package/templates/assistkick-product-system/packages/backend/src/routes/chat_files.test.ts +95 -0
  11. package/templates/assistkick-product-system/packages/backend/src/routes/chat_files.ts +97 -0
  12. package/templates/assistkick-product-system/packages/backend/src/routes/chat_permission.ts +94 -0
  13. package/templates/assistkick-product-system/packages/backend/src/routes/chat_sessions.ts +189 -0
  14. package/templates/assistkick-product-system/packages/backend/src/routes/chat_upload.test.ts +131 -0
  15. package/templates/assistkick-product-system/packages/backend/src/routes/chat_upload.ts +94 -0
  16. package/templates/assistkick-product-system/packages/backend/src/routes/files.test.ts +12 -3
  17. package/templates/assistkick-product-system/packages/backend/src/routes/files.ts +2 -2
  18. package/templates/assistkick-product-system/packages/backend/src/routes/git.ts +390 -22
  19. package/templates/assistkick-product-system/packages/backend/src/routes/git_branches.test.ts +306 -0
  20. package/templates/assistkick-product-system/packages/backend/src/routes/git_connect.test.ts +133 -0
  21. package/templates/assistkick-product-system/packages/backend/src/routes/pipeline.ts +66 -9
  22. package/templates/assistkick-product-system/packages/backend/src/routes/preview.ts +204 -0
  23. package/templates/assistkick-product-system/packages/backend/src/routes/projects.test.ts +205 -0
  24. package/templates/assistkick-product-system/packages/backend/src/routes/projects.ts +37 -9
  25. package/templates/assistkick-product-system/packages/backend/src/routes/skills.test.ts +139 -0
  26. package/templates/assistkick-product-system/packages/backend/src/routes/skills.ts +95 -0
  27. package/templates/assistkick-product-system/packages/backend/src/routes/terminal.ts +5 -4
  28. package/templates/assistkick-product-system/packages/backend/src/routes/users.ts +4 -4
  29. package/templates/assistkick-product-system/packages/backend/src/routes/video.ts +8 -8
  30. package/templates/assistkick-product-system/packages/backend/src/routes/workflow_groups.ts +5 -5
  31. package/templates/assistkick-product-system/packages/backend/src/routes/workflows.ts +6 -6
  32. package/templates/assistkick-product-system/packages/backend/src/server.ts +107 -27
  33. package/templates/assistkick-product-system/packages/backend/src/services/agent_service.test.ts +105 -203
  34. package/templates/assistkick-product-system/packages/backend/src/services/agent_service.ts +76 -266
  35. package/templates/assistkick-product-system/packages/backend/src/services/chat_cli_bridge.test.ts +427 -0
  36. package/templates/assistkick-product-system/packages/backend/src/services/chat_cli_bridge.ts +345 -0
  37. package/templates/assistkick-product-system/packages/backend/src/services/chat_message_repository.test.ts +170 -0
  38. package/templates/assistkick-product-system/packages/backend/src/services/chat_message_repository.ts +106 -0
  39. package/templates/assistkick-product-system/packages/backend/src/services/chat_session_service.test.ts +217 -0
  40. package/templates/assistkick-product-system/packages/backend/src/services/chat_session_service.ts +188 -0
  41. package/templates/assistkick-product-system/packages/backend/src/services/chat_ws_handler.test.ts +1243 -0
  42. package/templates/assistkick-product-system/packages/backend/src/services/chat_ws_handler.ts +894 -0
  43. package/templates/assistkick-product-system/packages/backend/src/services/coherence-review.ts +3 -3
  44. package/templates/assistkick-product-system/packages/backend/src/services/dev_command_detector.test.ts +85 -0
  45. package/templates/assistkick-product-system/packages/backend/src/services/dev_command_detector.ts +54 -0
  46. package/templates/assistkick-product-system/packages/backend/src/services/email_service.ts +13 -10
  47. package/templates/assistkick-product-system/packages/backend/src/services/init.ts +11 -3
  48. package/templates/assistkick-product-system/packages/backend/src/services/invitation_service.ts +1 -1
  49. package/templates/assistkick-product-system/packages/backend/src/services/password_reset_service.ts +1 -1
  50. package/templates/assistkick-product-system/packages/backend/src/services/permission_service.test.ts +243 -0
  51. package/templates/assistkick-product-system/packages/backend/src/services/permission_service.ts +259 -0
  52. package/templates/assistkick-product-system/packages/backend/src/services/preview_server_manager.test.ts +172 -0
  53. package/templates/assistkick-product-system/packages/backend/src/services/preview_server_manager.ts +225 -0
  54. package/templates/assistkick-product-system/packages/backend/src/services/project_service.test.ts +29 -0
  55. package/templates/assistkick-product-system/packages/backend/src/services/project_service.ts +17 -0
  56. package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.test.ts +255 -0
  57. package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.ts +300 -25
  58. package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.test.ts +44 -0
  59. package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.ts +62 -7
  60. package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.test.ts +77 -6
  61. package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.ts +129 -8
  62. package/templates/assistkick-product-system/packages/backend/src/services/terminal_ws_handler.ts +2 -1
  63. package/templates/assistkick-product-system/packages/backend/src/services/title_generator_service.test.ts +45 -0
  64. package/templates/assistkick-product-system/packages/backend/src/services/title_generator_service.ts +157 -0
  65. package/templates/assistkick-product-system/packages/backend/src/services/tts_service.ts +4 -3
  66. package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.ts +3 -3
  67. package/templates/assistkick-product-system/packages/frontend/package.json +5 -0
  68. package/templates/assistkick-product-system/packages/frontend/src/App.tsx +2 -0
  69. package/templates/assistkick-product-system/packages/frontend/src/api/client.ts +336 -5
  70. package/templates/assistkick-product-system/packages/frontend/src/components/AgentsView.tsx +192 -12
  71. package/templates/assistkick-product-system/packages/frontend/src/components/AttachmentPreviewList.tsx +98 -0
  72. package/templates/assistkick-product-system/packages/frontend/src/components/AutocompleteDropdown.tsx +65 -0
  73. package/templates/assistkick-product-system/packages/frontend/src/components/ChatAttachButton.tsx +56 -0
  74. package/templates/assistkick-product-system/packages/frontend/src/components/ChatDropZone.tsx +80 -0
  75. package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageBubble.tsx +155 -0
  76. package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageContent.tsx +182 -0
  77. package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageInput.tsx +233 -0
  78. package/templates/assistkick-product-system/packages/frontend/src/components/ChatSessionSidebar.tsx +218 -0
  79. package/templates/assistkick-product-system/packages/frontend/src/components/ChatStopButton.tsx +32 -0
  80. package/templates/assistkick-product-system/packages/frontend/src/components/ChatTodoSidebar.tsx +113 -0
  81. package/templates/assistkick-product-system/packages/frontend/src/components/ChatView.tsx +842 -0
  82. package/templates/assistkick-product-system/packages/frontend/src/components/CommitMessageModal.tsx +82 -0
  83. package/templates/assistkick-product-system/packages/frontend/src/components/DiagramOverlay.tsx +160 -0
  84. package/templates/assistkick-product-system/packages/frontend/src/components/EditorTabBar.tsx +5 -5
  85. package/templates/assistkick-product-system/packages/frontend/src/components/FileTree.tsx +9 -10
  86. package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeInlineInput.tsx +5 -5
  87. package/templates/assistkick-product-system/packages/frontend/src/components/FilesView.tsx +112 -41
  88. package/templates/assistkick-product-system/packages/frontend/src/components/GraphLegend.tsx +2 -2
  89. package/templates/assistkick-product-system/packages/frontend/src/components/HighlightedText.tsx +87 -0
  90. package/templates/assistkick-product-system/packages/frontend/src/components/ImageLightbox.tsx +192 -0
  91. package/templates/assistkick-product-system/packages/frontend/src/components/KanbanView.tsx +2 -2
  92. package/templates/assistkick-product-system/packages/frontend/src/components/MentionPill.tsx +33 -0
  93. package/templates/assistkick-product-system/packages/frontend/src/components/MermaidBlock.tsx +148 -0
  94. package/templates/assistkick-product-system/packages/frontend/src/components/PermissionDialog.tsx +91 -0
  95. package/templates/assistkick-product-system/packages/frontend/src/components/PermissionModeSelector.tsx +229 -0
  96. package/templates/assistkick-product-system/packages/frontend/src/components/ProjectSelector.tsx +249 -83
  97. package/templates/assistkick-product-system/packages/frontend/src/components/QueuedMessageBubble.tsx +38 -0
  98. package/templates/assistkick-product-system/packages/frontend/src/components/SidePanel.tsx +212 -117
  99. package/templates/assistkick-product-system/packages/frontend/src/components/SystemPromptAccordion.tsx +48 -0
  100. package/templates/assistkick-product-system/packages/frontend/src/components/TaskIcon.tsx +11 -0
  101. package/templates/assistkick-product-system/packages/frontend/src/components/TerminalView.tsx +25 -9
  102. package/templates/assistkick-product-system/packages/frontend/src/components/ToolDiffView.tsx +114 -0
  103. package/templates/assistkick-product-system/packages/frontend/src/components/ToolResultCard.tsx +87 -0
  104. package/templates/assistkick-product-system/packages/frontend/src/components/ToolUseCard.tsx +149 -0
  105. package/templates/assistkick-product-system/packages/frontend/src/components/Toolbar.tsx +25 -8
  106. package/templates/assistkick-product-system/packages/frontend/src/components/UnifiedGitWidget.tsx +722 -0
  107. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/GroupNode.tsx +2 -0
  108. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/NodePalette.tsx +2 -1
  109. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/ProgrammableNode.tsx +178 -0
  110. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowCanvas.tsx +3 -0
  111. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowMonitorModal.tsx +103 -9
  112. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/monitor_nodes.tsx +26 -2
  113. package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.ts +42 -1
  114. package/templates/assistkick-product-system/packages/frontend/src/hooks/useDocumentTitle.ts +11 -0
  115. package/templates/assistkick-product-system/packages/frontend/src/hooks/useProjects.ts +1 -0
  116. package/templates/assistkick-product-system/packages/frontend/src/hooks/use_chat_stream.ts +826 -0
  117. package/templates/assistkick-product-system/packages/frontend/src/hooks/use_file_tree_cache.ts +69 -0
  118. package/templates/assistkick-product-system/packages/frontend/src/hooks/use_mention_autocomplete.ts +284 -0
  119. package/templates/assistkick-product-system/packages/frontend/src/lib/attachment_manager.test.ts +183 -0
  120. package/templates/assistkick-product-system/packages/frontend/src/lib/attachment_manager.ts +150 -0
  121. package/templates/assistkick-product-system/packages/frontend/src/lib/chat_message_helpers.test.ts +305 -0
  122. package/templates/assistkick-product-system/packages/frontend/src/lib/chat_message_helpers.ts +113 -0
  123. package/templates/assistkick-product-system/packages/frontend/src/lib/context_usage_helpers.test.ts +157 -0
  124. package/templates/assistkick-product-system/packages/frontend/src/lib/context_usage_helpers.ts +95 -0
  125. package/templates/assistkick-product-system/packages/frontend/src/lib/mermaid_helpers.test.ts +65 -0
  126. package/templates/assistkick-product-system/packages/frontend/src/lib/mermaid_helpers.ts +110 -0
  127. package/templates/assistkick-product-system/packages/frontend/src/lib/message_queue.ts +66 -0
  128. package/templates/assistkick-product-system/packages/frontend/src/lib/tool_use_summary.test.ts +124 -0
  129. package/templates/assistkick-product-system/packages/frontend/src/lib/tool_use_summary.ts +112 -0
  130. package/templates/assistkick-product-system/packages/frontend/src/routes/AgentsRoute.tsx +2 -0
  131. package/templates/assistkick-product-system/packages/frontend/src/routes/ChatRoute.tsx +8 -0
  132. package/templates/assistkick-product-system/packages/frontend/src/routes/CoherenceRoute.tsx +2 -0
  133. package/templates/assistkick-product-system/packages/frontend/src/routes/DashboardLayout.tsx +0 -4
  134. package/templates/assistkick-product-system/packages/frontend/src/routes/DesignSystemRoute.tsx +2 -0
  135. package/templates/assistkick-product-system/packages/frontend/src/routes/FilesRoute.tsx +2 -0
  136. package/templates/assistkick-product-system/packages/frontend/src/routes/GraphRoute.tsx +2 -0
  137. package/templates/assistkick-product-system/packages/frontend/src/routes/KanbanRoute.tsx +2 -0
  138. package/templates/assistkick-product-system/packages/frontend/src/routes/TerminalRoute.tsx +2 -0
  139. package/templates/assistkick-product-system/packages/frontend/src/routes/UsersRoute.tsx +2 -0
  140. package/templates/assistkick-product-system/packages/frontend/src/routes/VideographyRoute.tsx +2 -0
  141. package/templates/assistkick-product-system/packages/frontend/src/routes/WorkflowsRoute.tsx +2 -0
  142. package/templates/assistkick-product-system/packages/frontend/src/routes/accept_invitation.tsx +2 -0
  143. package/templates/assistkick-product-system/packages/frontend/src/routes/forgot_password.tsx +2 -0
  144. package/templates/assistkick-product-system/packages/frontend/src/routes/login.tsx +2 -0
  145. package/templates/assistkick-product-system/packages/frontend/src/routes/register.tsx +2 -0
  146. package/templates/assistkick-product-system/packages/frontend/src/routes/reset_password.tsx +2 -0
  147. package/templates/assistkick-product-system/packages/frontend/src/stores/useAttachmentStore.ts +66 -0
  148. package/templates/assistkick-product-system/packages/frontend/src/stores/useChatSessionStore.ts +107 -0
  149. package/templates/assistkick-product-system/packages/frontend/src/stores/useMessageQueueStore.ts +110 -0
  150. package/templates/assistkick-product-system/packages/frontend/src/stores/usePreviewStore.ts +78 -0
  151. package/templates/assistkick-product-system/packages/frontend/src/stores/useProjectStore.ts +7 -0
  152. package/templates/assistkick-product-system/packages/frontend/src/stores/useSidePanelStore.ts +6 -1
  153. package/templates/assistkick-product-system/packages/frontend/src/styles/index.css +30 -357
  154. package/templates/assistkick-product-system/packages/frontend/src/utils/parse_node_markdown.test.ts +115 -0
  155. package/templates/assistkick-product-system/packages/frontend/src/utils/parse_node_markdown.ts +91 -0
  156. package/templates/assistkick-product-system/packages/frontend/src/utils/preview_utils.test.ts +30 -0
  157. package/templates/assistkick-product-system/packages/frontend/src/utils/preview_utils.ts +3 -0
  158. package/templates/assistkick-product-system/packages/shared/db/migrate.ts +82 -0
  159. package/templates/assistkick-product-system/packages/shared/db/migrations/0000_outgoing_ultron.sql +277 -0
  160. package/templates/assistkick-product-system/packages/shared/db/migrations/0015_magenta_jazinda.sql +1 -0
  161. package/templates/assistkick-product-system/packages/shared/db/migrations/0016_giant_xorn.sql +1 -0
  162. package/templates/assistkick-product-system/packages/shared/db/migrations/0017_sloppy_mentor.sql +6 -0
  163. package/templates/assistkick-product-system/packages/shared/db/migrations/0018_vengeful_kabuki.sql +9 -0
  164. package/templates/assistkick-product-system/packages/shared/db/migrations/0019_careful_sentinels.sql +8 -0
  165. package/templates/assistkick-product-system/packages/shared/db/migrations/0020_clever_spot.sql +27 -0
  166. package/templates/assistkick-product-system/packages/shared/db/migrations/0021_graceful_hex.sql +1 -0
  167. package/templates/assistkick-product-system/packages/shared/db/migrations/0022_short_kingpin.sql +1 -0
  168. package/templates/assistkick-product-system/packages/shared/db/migrations/0023_ambiguous_sharon_carter.sql +1 -0
  169. package/templates/assistkick-product-system/packages/shared/db/migrations/0024_fat_unus.sql +1 -0
  170. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0000_snapshot.json +972 -22
  171. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0015_snapshot.json +1552 -0
  172. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0016_snapshot.json +1560 -0
  173. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0017_snapshot.json +1598 -0
  174. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0018_snapshot.json +1657 -0
  175. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0019_snapshot.json +1709 -0
  176. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0020_snapshot.json +1733 -0
  177. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0021_snapshot.json +1740 -0
  178. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0022_snapshot.json +1755 -0
  179. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0023_snapshot.json +1762 -0
  180. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0024_snapshot.json +1769 -0
  181. package/templates/assistkick-product-system/packages/shared/db/migrations/meta/_journal.json +2 -100
  182. package/templates/assistkick-product-system/packages/shared/db/schema.ts +40 -1
  183. package/templates/assistkick-product-system/packages/shared/lib/claude-service.test.ts +236 -0
  184. package/templates/assistkick-product-system/packages/shared/lib/claude-service.ts +46 -5
  185. package/templates/assistkick-product-system/packages/shared/lib/git_workflow.ts +65 -39
  186. package/templates/assistkick-product-system/packages/shared/lib/programmable_node_executor.test.ts +173 -0
  187. package/templates/assistkick-product-system/packages/shared/lib/programmable_node_executor.ts +213 -0
  188. package/templates/assistkick-product-system/packages/shared/lib/validator.test.ts +70 -0
  189. package/templates/assistkick-product-system/packages/shared/lib/validator.ts +17 -1
  190. package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.test.ts +803 -27
  191. package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.ts +502 -68
  192. package/templates/assistkick-product-system/packages/shared/lib/workflow_orchestrator.ts +4 -4
  193. package/templates/assistkick-product-system/packages/shared/package.json +2 -1
  194. package/templates/assistkick-product-system/packages/shared/test_fixtures/hanging_stream.mjs +46 -0
  195. package/templates/assistkick-product-system/packages/shared/tools/add_node.test.ts +44 -0
  196. package/templates/assistkick-product-system/packages/shared/tools/add_node.ts +7 -0
  197. package/templates/assistkick-product-system/packages/shared/tools/remove_node.ts +2 -1
  198. package/templates/assistkick-product-system/packages/shared/tools/resolve_question.ts +2 -1
  199. package/templates/assistkick-product-system/packages/shared/tools/update_node.ts +2 -1
  200. package/templates/assistkick-product-system/tests/message_queue.test.ts +178 -0
  201. package/templates/assistkick-product-system/tests/message_queue_per_session.test.ts +143 -0
  202. package/templates/skills/assistkick-bootstrap/SKILL.md +26 -26
  203. package/templates/skills/assistkick-code-reviewer/SKILL.md +45 -46
  204. package/templates/skills/assistkick-db-explorer/SKILL.md +13 -13
  205. package/templates/skills/assistkick-debugger/SKILL.md +23 -23
  206. package/templates/skills/assistkick-developer/SKILL.md +59 -63
  207. package/templates/skills/assistkick-interview/SKILL.md +26 -26
  208. package/templates/skills/assistkick-video-composition-agent/SKILL.md +231 -0
  209. package/templates/skills/assistkick-video-script-writer/SKILL.md +136 -0
@@ -25,6 +25,8 @@
25
25
  --font-system: "Inter", system-ui, -apple-system, sans-serif;
26
26
  }
27
27
 
28
+ /* Theme variables — dark / light */
29
+
28
30
  :root {
29
31
  --font-mono: ui-monospace, "SF Mono", "Cascadia Code", "Fira Code", monospace;
30
32
  --font-system: "Inter", system-ui, -apple-system, sans-serif;
@@ -68,14 +70,9 @@
68
70
  --error-color: #d93025;
69
71
  }
70
72
 
73
+ /* Minimal base layer — only rules that cannot be expressed as Tailwind utilities */
71
74
  @layer base {
72
75
 
73
- * {
74
- margin: 0;
75
- padding: 0;
76
- box-sizing: border-box;
77
- }
78
-
79
76
  html, body, #root {
80
77
  width: 100%;
81
78
  height: 100%;
@@ -86,7 +83,7 @@ html, body, #root {
86
83
  color: var(--text-primary);
87
84
  }
88
85
 
89
- /* Settings toggle knob (pseudo-element cannot be expressed in Tailwind) */
86
+ /* Settings toggle needs ::after pseudo-element and :checked state */
90
87
  .settings-toggle::after {
91
88
  content: '';
92
89
  position: absolute;
@@ -104,76 +101,22 @@ html, body, #root {
104
101
  background: var(--accent);
105
102
  }
106
103
 
107
- /* Side panel dangerouslySetInnerHTML child selectors (cannot use Tailwind) */
108
- .panel-body {
109
- font-size: 14px;
110
- line-height: 1.6;
111
- }
112
-
113
- .panel-body h1 { font-size: 18px; margin: 12px 0 8px; color: var(--text-primary); }
114
- .panel-body h2 { font-size: 16px; margin: 12px 0 6px; color: var(--text-primary); }
115
- .panel-body h3 { font-size: 15px; margin: 10px 0 4px; color: var(--text-primary); }
116
- .panel-body p { margin: 4px 0; color: var(--text-primary); }
117
- .panel-body ul { padding-left: 20px; margin: 4px 0; }
118
- .panel-body li { color: var(--text-primary); margin: 2px 0; }
119
- .panel-body code {
120
- background: var(--bg-tertiary);
121
- padding: 1px 4px;
122
- border-radius: 3px;
123
- font-size: 11px;
124
- }
125
- .panel-body blockquote {
126
- border-left: 3px solid var(--border-color);
127
- padding-left: 12px;
128
- color: var(--text-muted);
129
- margin: 8px 0;
130
- }
131
- .panel-body strong { color: var(--text-primary); }
132
- .panel-body pre {
133
- background: var(--bg-tertiary);
134
- padding: 10px 12px;
135
- border-radius: 4px;
136
- overflow-x: auto;
137
- margin: 8px 0;
138
- font-size: 11px;
139
- }
140
- .panel-body pre code {
141
- background: transparent;
142
- padding: 0;
143
- }
144
-
145
- /* Side panel — dynamic status color variants */
146
- .panel-status-draft {
147
- background: rgba(173, 181, 189, 0.15);
148
- color: #adb5bd;
149
- }
150
-
151
- .panel-status-partially_defined {
152
- background: rgba(255, 212, 59, 0.15);
153
- color: #ffd43b;
154
- }
155
-
156
- .panel-status-defined {
157
- background: rgba(105, 219, 124, 0.15);
158
- color: #69db7c;
104
+ /* Terminalxterm library override */
105
+ .terminal-container .xterm {
106
+ height: 100%;
159
107
  }
160
108
 
161
- /* Gap indicatorspulsing ring for nodes with open questions (D3/SVG) */
109
+ /* Graph SVG animations applied via D3 .attr('class', ...) */
162
110
  .gap-pulse-ring {
163
111
  animation: gap-pulse 2s ease-in-out infinite;
164
112
  }
165
113
 
166
- @keyframes gap-pulse {
167
- 0%, 100% { stroke-opacity: 0.8; stroke-width: 2; }
168
- 50% { stroke-opacity: 0.2; stroke-width: 4; }
169
- }
170
-
171
114
  .gap-warning-icon {
172
115
  fill: #ff6b6b;
173
116
  filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.5));
174
117
  }
175
118
 
176
- /* Legend gap indicator swatch (@keyframes animation) */
119
+ /* Legend gap indicator keyframe animation */
177
120
  .legend-gap-pulse {
178
121
  background: var(--bg-tertiary) !important;
179
122
  border: 2px solid #ff6b6b;
@@ -181,16 +124,6 @@ html, body, #root {
181
124
  box-shadow: 0 0 0 0 rgba(255, 107, 107, 0.4);
182
125
  }
183
126
 
184
- @keyframes legend-gap-pulse {
185
- 0%, 100% { box-shadow: 0 0 0 0 rgba(255, 107, 107, 0.4); }
186
- 50% { box-shadow: 0 0 0 3px rgba(255, 107, 107, 0.1); }
187
- }
188
-
189
- /* Terminal — xterm.js child targeting */
190
- .terminal-container .xterm {
191
- height: 100%;
192
- }
193
-
194
127
  /* React Flow workflow canvas overrides */
195
128
  .workflow-canvas .react-flow__pane {
196
129
  cursor: grab;
@@ -215,296 +148,36 @@ html, body, #root {
215
148
  display: none;
216
149
  }
217
150
 
218
- /* ===== Files View ===== */
219
-
220
- .files-view {
221
- display: flex;
222
- flex-direction: row;
223
- height: 100%;
224
- width: 100%;
225
- overflow: hidden;
226
- }
227
-
228
- .files-view__empty {
229
- flex: 1;
230
- display: flex;
231
- align-items: center;
232
- justify-content: center;
233
- height: 100%;
234
- font-family: var(--font-mono);
235
- font-size: 13px;
236
- }
237
-
238
- .files-view__tree {
239
- display: flex;
240
- flex-direction: column;
241
- border-right: 1px solid var(--border-color);
242
- flex-shrink: 0;
243
- overflow: hidden;
244
- background: var(--bg-primary);
245
- }
246
-
247
- .files-view__tree-header {
248
- padding: 10px 12px;
249
- border-bottom: 1px solid var(--border-color);
250
- flex-shrink: 0;
251
- }
252
-
253
- .files-view__tree-content {
254
- flex: 1;
255
- overflow-y: auto;
256
- overflow-x: hidden;
257
- }
258
-
259
- .files-view__resize-handle {
260
- width: 4px;
261
- cursor: col-resize;
262
- background: transparent;
263
- flex-shrink: 0;
264
- transition: background 0.15s;
265
- position: relative;
266
- z-index: 2;
267
- margin-left: -2px;
268
- margin-right: -2px;
269
- }
270
-
271
- .files-view__resize-handle:hover,
272
- .files-view__resize-handle:active {
273
- background: var(--accent);
274
- }
275
-
276
- .files-view__editor {
277
- flex: 1;
278
- display: flex;
279
- flex-direction: column;
280
- min-width: 0;
281
- overflow: hidden;
282
- }
283
-
284
- .files-view__editor-container {
285
- flex: 1;
286
- min-height: 0;
287
- position: relative;
288
- }
289
-
290
- .files-view__loading {
291
- position: absolute;
292
- top: 0;
293
- left: 0;
294
- right: 0;
295
- z-index: 5;
296
- display: flex;
297
- justify-content: center;
298
- padding: 8px;
299
- background: var(--bg-secondary);
300
- border-bottom: 1px solid var(--border-color);
301
- font-family: var(--font-mono);
302
- }
303
-
304
- .files-view__empty-editor {
305
- flex: 1;
306
- display: flex;
307
- align-items: center;
308
- justify-content: center;
309
- font-family: var(--font-mono);
310
- font-size: 13px;
311
- background: var(--bg-primary);
312
- }
313
-
314
- /* File tree */
315
- .file-tree {
316
- display: flex;
317
- flex-direction: column;
318
- padding: 4px 0;
319
- }
320
-
321
- .file-tree-node {
322
- display: flex;
323
- align-items: center;
324
- gap: 4px;
325
- width: 100%;
326
- padding: 3px 8px;
327
- border: none;
328
- background: transparent;
329
- color: var(--text-secondary);
330
- font-family: var(--font-mono);
331
- font-size: 12px;
332
- cursor: pointer;
333
- text-align: left;
334
- white-space: nowrap;
335
- overflow: hidden;
336
- text-overflow: ellipsis;
337
- outline: none;
338
- transition: background 0.1s;
339
- }
340
-
341
- .file-tree-node:hover {
342
- background: var(--tab-hover-bg);
343
- color: var(--text-primary);
344
- }
345
-
346
- .file-tree-node--selected {
347
- background: var(--bg-tertiary);
348
- color: var(--accent);
349
- }
350
-
351
- .file-tree-node__chevron {
352
- flex-shrink: 0;
353
- width: 12px;
354
- display: flex;
355
- align-items: center;
356
- justify-content: center;
357
- color: var(--text-muted);
358
- }
359
-
360
- .file-tree-node__chevron--hidden {
361
- visibility: hidden;
362
- }
363
-
364
- .file-tree-node__icon {
365
- flex-shrink: 0;
366
- color: var(--text-muted);
367
- }
368
-
369
- .file-tree-node__icon--folder {
370
- color: var(--accent);
371
- }
372
-
373
- .file-tree-node__name {
374
- overflow: hidden;
375
- text-overflow: ellipsis;
376
- }
377
-
378
- /* File tree context menu */
379
- .file-tree-context-menu {
380
- background: var(--bg-secondary);
381
- border: 1px solid var(--border-color);
382
- border-radius: 4px;
383
- padding: 4px 0;
384
- min-width: 140px;
385
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
386
- font-family: var(--font-mono);
387
- }
388
-
389
- .file-tree-context-menu__item {
390
- display: block;
391
- width: 100%;
392
- padding: 5px 12px;
393
- border: none;
394
- background: transparent;
395
- color: var(--text-secondary);
396
- font-family: var(--font-mono);
397
- font-size: 12px;
398
- text-align: left;
399
- cursor: pointer;
400
- outline: none;
401
- transition: background 0.1s, color 0.1s;
402
- }
403
-
404
- .file-tree-context-menu__item:hover {
405
- background: var(--tab-hover-bg);
406
- color: var(--text-primary);
407
- }
408
-
409
- /* File tree inline input */
410
- .file-tree-inline-input {
411
- display: flex;
412
- align-items: center;
413
- gap: 4px;
414
- width: 100%;
415
- padding: 2px 8px;
416
- }
417
-
418
- .file-tree-inline-input__field {
419
- flex: 1;
420
- min-width: 0;
421
- padding: 2px 4px;
422
- border: 1px solid var(--accent);
423
- border-radius: 2px;
424
- background: var(--bg-primary);
425
- color: var(--text-primary);
426
- font-family: var(--font-mono);
427
- font-size: 12px;
428
- outline: none;
429
- }
430
-
431
- /* Editor tab bar */
432
- .editor-tab-bar {
433
- display: flex;
434
- flex-shrink: 0;
435
- overflow-x: auto;
436
- overflow-y: hidden;
437
- border-bottom: 1px solid var(--border-color);
438
- background: var(--bg-secondary);
439
- scrollbar-width: thin;
440
- }
441
-
442
- .editor-tab-bar::-webkit-scrollbar {
443
- height: 2px;
444
- }
445
-
446
- .editor-tab-bar::-webkit-scrollbar-thumb {
447
- background: var(--border-color);
448
- }
449
-
450
- .editor-tab {
451
- display: flex;
452
- align-items: center;
453
- gap: 6px;
454
- padding: 6px 12px;
455
- border: none;
456
- border-right: 1px solid var(--border-color);
457
- background: var(--bg-primary);
458
- color: var(--text-secondary);
459
- font-family: var(--font-mono);
460
- font-size: 12px;
461
- cursor: pointer;
462
- white-space: nowrap;
463
- outline: none;
464
- transition: background 0.1s, color 0.1s;
465
- flex-shrink: 0;
151
+ /* Mermaid diagram edge label padding & design-system alignment */
152
+ .mermaid-diagram .edgeLabel {
153
+ padding: 6px 10px;
466
154
  }
467
155
 
468
- .editor-tab:hover {
469
- background: var(--tab-hover-bg);
470
- color: var(--text-primary);
156
+ .mermaid-diagram .edgeLabel p {
157
+ margin: 0;
471
158
  }
472
159
 
473
- .editor-tab--active {
474
- background: var(--bg-secondary);
475
- color: var(--text-primary);
476
- border-bottom: 2px solid var(--accent);
477
- margin-bottom: -1px;
160
+ .mermaid-diagram .node rect,
161
+ .mermaid-diagram .node polygon,
162
+ .mermaid-diagram .node circle {
163
+ rx: 8;
164
+ ry: 8;
478
165
  }
479
166
 
480
- .editor-tab__name {
481
- overflow: hidden;
482
- text-overflow: ellipsis;
483
- max-width: 160px;
484
- }
167
+ } /* end @layer base */
485
168
 
486
- .editor-tab__close {
487
- display: flex;
488
- align-items: center;
489
- justify-content: center;
490
- width: 16px;
491
- height: 16px;
492
- border-radius: 3px;
493
- color: var(--text-muted);
494
- transition: background 0.1s, color 0.1s;
169
+ /* Keyframes — referenced by Tailwind arbitrary animations and CSS classes */
170
+ @keyframes toast-slide-in {
171
+ from { transform: translateY(20px); opacity: 0; }
172
+ to { transform: translateY(0); opacity: 1; }
495
173
  }
496
174
 
497
- .editor-tab__close:hover {
498
- background: var(--border-color);
499
- color: var(--text-primary);
175
+ @keyframes gap-pulse {
176
+ 0%, 100% { stroke-opacity: 0.8; stroke-width: 2; }
177
+ 50% { stroke-opacity: 0.2; stroke-width: 4; }
500
178
  }
501
179
 
502
- .editor-tab__dirty {
503
- font-size: 8px;
504
- line-height: 1;
505
- color: var(--text-secondary);
506
- margin-right: 4px;
507
- flex-shrink: 0;
180
+ @keyframes legend-gap-pulse {
181
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(255, 107, 107, 0.4); }
182
+ 50% { box-shadow: 0 0 0 3px rgba(255, 107, 107, 0.1); }
508
183
  }
509
-
510
- } /* end @layer base */
@@ -0,0 +1,115 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { parseNodeMarkdown } from './parse_node_markdown.ts';
4
+
5
+ describe('parseNodeMarkdown', () => {
6
+ it('strips frontmatter and extracts description', () => {
7
+ const md = `---
8
+ id: feat_001
9
+ type: feature
10
+ ---
11
+ Some description text.
12
+
13
+ ## Acceptance Criteria
14
+ - First criterion
15
+ - Second criterion
16
+ `;
17
+ const result = parseNodeMarkdown(md);
18
+ assert.equal(result.description, 'Some description text.');
19
+ assert.deepEqual(result.acceptanceCriteria, ['First criterion', 'Second criterion']);
20
+ });
21
+
22
+ it('parses numbered acceptance criteria', () => {
23
+ const md = `## Description
24
+ A feature.
25
+
26
+ ## Acceptance Criteria
27
+ 1. First item
28
+ 2. Second item
29
+ 3. Third item
30
+ `;
31
+ const result = parseNodeMarkdown(md);
32
+ assert.deepEqual(result.acceptanceCriteria, ['First item', 'Second item', 'Third item']);
33
+ });
34
+
35
+ it('parses open questions', () => {
36
+ const md = `## Description
37
+ Desc.
38
+
39
+ ## Open Questions
40
+ - What about X?
41
+ - How does Y work?
42
+ `;
43
+ const result = parseNodeMarkdown(md);
44
+ assert.deepEqual(result.openQuestions, ['What about X?', 'How does Y work?']);
45
+ });
46
+
47
+ it('parses resolved questions with arrow separator', () => {
48
+ const md = `## Resolved Questions
49
+ - [x] Should we use X? → Yes, use X because it is faster.
50
+ - [x] How to handle Y? → Use the Z approach.
51
+ `;
52
+ const result = parseNodeMarkdown(md);
53
+ assert.equal(result.resolvedQuestions.length, 2);
54
+ assert.equal(result.resolvedQuestions[0].question, 'Should we use X?');
55
+ assert.equal(result.resolvedQuestions[0].resolution, 'Yes, use X because it is faster.');
56
+ assert.equal(result.resolvedQuestions[1].question, 'How to handle Y?');
57
+ assert.equal(result.resolvedQuestions[1].resolution, 'Use the Z approach.');
58
+ });
59
+
60
+ it('parses resolved questions without resolution', () => {
61
+ const md = `## Resolved Questions
62
+ - [x] A question with no answer
63
+ `;
64
+ const result = parseNodeMarkdown(md);
65
+ assert.equal(result.resolvedQuestions.length, 1);
66
+ assert.equal(result.resolvedQuestions[0].question, 'A question with no answer');
67
+ assert.equal(result.resolvedQuestions[0].resolution, '');
68
+ });
69
+
70
+ it('extracts notes section', () => {
71
+ const md = `## Description
72
+ Desc.
73
+
74
+ ## Notes
75
+ > Session 1: Did something important.
76
+ > Session 2: Did more things.
77
+ `;
78
+ const result = parseNodeMarkdown(md);
79
+ assert.ok(result.notes.includes('Session 1: Did something important.'));
80
+ assert.ok(result.notes.includes('Session 2: Did more things.'));
81
+ });
82
+
83
+ it('returns empty values for missing sections', () => {
84
+ const md = `## Description
85
+ Just a description.
86
+ `;
87
+ const result = parseNodeMarkdown(md);
88
+ assert.equal(result.description, 'Just a description.');
89
+ assert.deepEqual(result.acceptanceCriteria, []);
90
+ assert.deepEqual(result.openQuestions, []);
91
+ assert.deepEqual(result.resolvedQuestions, []);
92
+ assert.equal(result.notes, '');
93
+ });
94
+
95
+ it('handles content with no frontmatter', () => {
96
+ const md = `## Description
97
+ No frontmatter here.
98
+
99
+ ## Acceptance Criteria
100
+ - One criterion
101
+ `;
102
+ const result = parseNodeMarkdown(md);
103
+ assert.equal(result.description, 'No frontmatter here.');
104
+ assert.deepEqual(result.acceptanceCriteria, ['One criterion']);
105
+ });
106
+
107
+ it('handles empty content', () => {
108
+ const result = parseNodeMarkdown('');
109
+ assert.equal(result.description, '');
110
+ assert.deepEqual(result.acceptanceCriteria, []);
111
+ assert.deepEqual(result.openQuestions, []);
112
+ assert.deepEqual(result.resolvedQuestions, []);
113
+ assert.equal(result.notes, '');
114
+ });
115
+ });
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Parses node markdown content (after frontmatter stripping) into typed sections.
3
+ * Splitting is done by ## heading boundaries.
4
+ */
5
+
6
+ export interface ParsedNodeContent {
7
+ description: string;
8
+ acceptanceCriteria: string[];
9
+ openQuestions: string[];
10
+ resolvedQuestions: ResolvedQuestion[];
11
+ notes: string;
12
+ }
13
+
14
+ export interface ResolvedQuestion {
15
+ question: string;
16
+ resolution: string;
17
+ }
18
+
19
+ const HEADING_RE = /^## (.+)$/m;
20
+
21
+ const stripFrontmatter = (md: string): string =>
22
+ md.replace(/^---[\s\S]*?---\n*/m, '');
23
+
24
+ const splitBullets = (text: string): string[] =>
25
+ text
26
+ .split(/\n/)
27
+ .map((line) => line.replace(/^\s*(?:-|\d+\.)\s+/, '').trim())
28
+ .filter(Boolean);
29
+
30
+ const parseResolvedQuestion = (line: string): ResolvedQuestion => {
31
+ // Format: "- [x] question text → resolution text" or "- [x] question text"
32
+ const cleaned = line.replace(/^\s*-?\s*\[x\]\s*/i, '').trim();
33
+ const arrowIdx = cleaned.indexOf('→');
34
+ if (arrowIdx !== -1) {
35
+ return {
36
+ question: cleaned.slice(0, arrowIdx).trim(),
37
+ resolution: cleaned.slice(arrowIdx + 1).trim(),
38
+ };
39
+ }
40
+ // Try "Resolution: " or "Answer: " split
41
+ const resMatch = cleaned.match(/^(.+?)(?:\s*(?:Resolution|Answer):\s*)(.+)$/s);
42
+ if (resMatch) {
43
+ return { question: resMatch[1].trim(), resolution: resMatch[2].trim() };
44
+ }
45
+ return { question: cleaned, resolution: '' };
46
+ };
47
+
48
+ const parseResolvedQuestions = (text: string): ResolvedQuestion[] =>
49
+ text
50
+ .split(/\n/)
51
+ .map((line) => line.trim())
52
+ .filter((line) => line.length > 0)
53
+ .map(parseResolvedQuestion);
54
+
55
+ /**
56
+ * Splits markdown content into named sections by ## headings.
57
+ * Returns a map of lowercase heading → section body text.
58
+ */
59
+ const splitSections = (md: string): Map<string, string> => {
60
+ const sections = new Map<string, string>();
61
+ const lines = md.split('\n');
62
+ let currentKey = 'description';
63
+ let currentLines: string[] = [];
64
+
65
+ for (const line of lines) {
66
+ const match = line.match(/^## (.+)$/);
67
+ if (match) {
68
+ sections.set(currentKey, currentLines.join('\n').trim());
69
+ currentKey = match[1].trim().toLowerCase();
70
+ currentLines = [];
71
+ } else {
72
+ currentLines.push(line);
73
+ }
74
+ }
75
+ sections.set(currentKey, currentLines.join('\n').trim());
76
+
77
+ return sections;
78
+ };
79
+
80
+ export const parseNodeMarkdown = (content: string): ParsedNodeContent => {
81
+ const stripped = stripFrontmatter(content);
82
+ const sections = splitSections(stripped);
83
+
84
+ return {
85
+ description: sections.get('description') ?? '',
86
+ acceptanceCriteria: splitBullets(sections.get('acceptance criteria') ?? ''),
87
+ openQuestions: splitBullets(sections.get('open questions') ?? ''),
88
+ resolvedQuestions: parseResolvedQuestions(sections.get('resolved questions') ?? ''),
89
+ notes: sections.get('notes') ?? '',
90
+ };
91
+ };
@@ -0,0 +1,30 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { toAppName } from './preview_utils.ts';
4
+
5
+ describe('toAppName', () => {
6
+ it('lowercases and replaces spaces with hyphens', () => {
7
+ assert.equal(toAppName('My Cool App'), 'my-cool-app');
8
+ });
9
+
10
+ it('strips non-alphanumeric characters', () => {
11
+ assert.equal(toAppName('App@#$Name!'), 'app-name');
12
+ });
13
+
14
+ it('collapses consecutive hyphens', () => {
15
+ assert.equal(toAppName('a--b---c'), 'a-b-c');
16
+ });
17
+
18
+ it('trims leading and trailing hyphens', () => {
19
+ assert.equal(toAppName('---hello---'), 'hello');
20
+ });
21
+
22
+ it('returns "app" for empty or all-special-character input', () => {
23
+ assert.equal(toAppName(''), 'app');
24
+ assert.equal(toAppName('!!!'), 'app');
25
+ });
26
+
27
+ it('handles already-valid names', () => {
28
+ assert.equal(toAppName('my-app-123'), 'my-app-123');
29
+ });
30
+ });
@@ -0,0 +1,3 @@
1
+ /** Sanitize a project name into a valid appName (alphanumeric + hyphens). */
2
+ export const toAppName = (name: string): string =>
3
+ name.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '') || 'app';