@compilr-dev/cli 0.4.0 → 0.5.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 (315) hide show
  1. package/README.md +30 -12
  2. package/dist/agent.d.ts +74 -1
  3. package/dist/agent.js +259 -76
  4. package/dist/anchors/index.d.ts +9 -0
  5. package/dist/anchors/index.js +9 -0
  6. package/dist/anchors/project-anchors.d.ts +79 -0
  7. package/dist/anchors/project-anchors.js +202 -0
  8. package/dist/commands/handler-types.d.ts +68 -0
  9. package/dist/commands/handler-types.js +8 -0
  10. package/dist/commands/handlers/agent-commands.d.ts +13 -0
  11. package/dist/commands/handlers/agent-commands.js +305 -0
  12. package/dist/commands/handlers/design-commands.d.ts +15 -0
  13. package/dist/commands/handlers/design-commands.js +334 -0
  14. package/dist/commands/handlers/index.d.ts +20 -0
  15. package/dist/commands/handlers/index.js +43 -0
  16. package/dist/commands/handlers/overlay-commands.d.ts +21 -0
  17. package/dist/commands/handlers/overlay-commands.js +287 -0
  18. package/dist/commands/handlers/project-commands.d.ts +11 -0
  19. package/dist/commands/handlers/project-commands.js +167 -0
  20. package/dist/commands/handlers/simple-commands.d.ts +19 -0
  21. package/dist/commands/handlers/simple-commands.js +144 -0
  22. package/dist/commands/index.d.ts +2 -1
  23. package/dist/commands/registry.d.ts +50 -0
  24. package/dist/commands/registry.js +75 -0
  25. package/dist/commands-v2/handlers/context.d.ts +13 -0
  26. package/dist/commands-v2/handlers/context.js +348 -0
  27. package/dist/commands-v2/handlers/core.d.ts +13 -0
  28. package/dist/commands-v2/handlers/core.js +165 -0
  29. package/dist/commands-v2/handlers/debug.d.ts +11 -0
  30. package/dist/commands-v2/handlers/debug.js +159 -0
  31. package/dist/commands-v2/handlers/index.d.ts +12 -0
  32. package/dist/commands-v2/handlers/index.js +24 -0
  33. package/dist/commands-v2/handlers/project.d.ts +22 -0
  34. package/dist/commands-v2/handlers/project.js +814 -0
  35. package/dist/commands-v2/handlers/settings.d.ts +15 -0
  36. package/dist/commands-v2/handlers/settings.js +235 -0
  37. package/dist/commands-v2/index.d.ts +13 -0
  38. package/dist/commands-v2/index.js +15 -0
  39. package/dist/commands-v2/registry.d.ts +37 -0
  40. package/dist/commands-v2/registry.js +80 -0
  41. package/dist/commands-v2/types.d.ts +75 -0
  42. package/dist/commands-v2/types.js +7 -0
  43. package/dist/commands.js +110 -7
  44. package/dist/index.js +288 -29
  45. package/dist/input-handlers/index.d.ts +7 -0
  46. package/dist/input-handlers/index.js +7 -0
  47. package/dist/input-handlers/memory-handler.d.ts +26 -0
  48. package/dist/input-handlers/memory-handler.js +68 -0
  49. package/dist/repl-helpers.d.ts +63 -0
  50. package/dist/repl-helpers.js +318 -0
  51. package/dist/repl-v2.d.ts +155 -0
  52. package/dist/repl-v2.js +774 -0
  53. package/dist/repl.d.ts +32 -4
  54. package/dist/repl.js +250 -977
  55. package/dist/settings/index.d.ts +23 -0
  56. package/dist/settings/index.js +48 -0
  57. package/dist/settings/paths.d.ts +110 -0
  58. package/dist/settings/paths.js +264 -0
  59. package/dist/templates/compilr-md.js +7 -4
  60. package/dist/templates/index.js +3 -4
  61. package/dist/themes/colors.js +3 -1
  62. package/dist/themes/registry.d.ts +5 -36
  63. package/dist/themes/registry.js +11 -95
  64. package/dist/themes/types.d.ts +3 -38
  65. package/dist/themes/types.js +2 -2
  66. package/dist/tools/anchor-tools.d.ts +31 -0
  67. package/dist/tools/anchor-tools.js +255 -0
  68. package/dist/tools/backlog-wrappers.d.ts +54 -0
  69. package/dist/tools/backlog-wrappers.js +338 -0
  70. package/dist/tools/backlog.js +1 -1
  71. package/dist/tools/db-tools.d.ts +65 -0
  72. package/dist/tools/db-tools.js +19 -0
  73. package/dist/tools/document-db.d.ts +43 -0
  74. package/dist/tools/document-db.js +220 -0
  75. package/dist/tools/project-db.d.ts +102 -0
  76. package/dist/tools/project-db.js +370 -0
  77. package/dist/tools/workitem-db.d.ts +103 -0
  78. package/dist/tools/workitem-db.js +549 -0
  79. package/dist/tools.js +13 -3
  80. package/dist/ui/agents-overlay-v2.d.ts +43 -0
  81. package/dist/ui/agents-overlay-v2.js +809 -0
  82. package/dist/ui/agents-overlay.d.ts +5 -5
  83. package/dist/ui/agents-overlay.js +782 -420
  84. package/dist/ui/anchors-overlay.d.ts +12 -0
  85. package/dist/ui/anchors-overlay.js +775 -0
  86. package/dist/ui/arch-type-overlay.d.ts +1 -6
  87. package/dist/ui/arch-type-overlay.js +175 -203
  88. package/dist/ui/ask-user-overlay-v2.d.ts +26 -0
  89. package/dist/ui/ask-user-overlay-v2.js +555 -0
  90. package/dist/ui/ask-user-overlay.d.ts +2 -2
  91. package/dist/ui/ask-user-overlay.js +443 -535
  92. package/dist/ui/ask-user-simple-overlay-v2.d.ts +25 -0
  93. package/dist/ui/ask-user-simple-overlay-v2.js +215 -0
  94. package/dist/ui/ask-user-simple-overlay.d.ts +2 -2
  95. package/dist/ui/ask-user-simple-overlay.js +182 -209
  96. package/dist/ui/backlog-overlay.d.ts +16 -1
  97. package/dist/ui/backlog-overlay.js +525 -659
  98. package/dist/ui/base/index.d.ts +26 -0
  99. package/dist/ui/base/index.js +33 -0
  100. package/dist/ui/base/inline-overlay-utils.d.ts +217 -0
  101. package/dist/ui/base/inline-overlay-utils.js +320 -0
  102. package/dist/ui/base/inline-overlay.d.ts +159 -0
  103. package/dist/ui/base/inline-overlay.js +257 -0
  104. package/dist/ui/base/key-utils.d.ts +15 -0
  105. package/dist/ui/base/key-utils.js +30 -0
  106. package/dist/ui/base/overlay-base-v2.d.ts +193 -0
  107. package/dist/ui/base/overlay-base-v2.js +246 -0
  108. package/dist/ui/base/overlay-base.d.ts +156 -0
  109. package/dist/ui/base/overlay-base.js +238 -0
  110. package/dist/ui/base/overlay-lifecycle.d.ts +65 -0
  111. package/dist/ui/base/overlay-lifecycle.js +159 -0
  112. package/dist/ui/base/overlay-types.d.ts +185 -0
  113. package/dist/ui/base/overlay-types.js +7 -0
  114. package/dist/ui/base/render-utils.d.ts +8 -0
  115. package/dist/ui/base/render-utils.js +11 -0
  116. package/dist/ui/base/screen-stack.d.ts +148 -0
  117. package/dist/ui/base/screen-stack.js +184 -0
  118. package/dist/ui/base/tabbed-list-overlay-v2.d.ts +103 -0
  119. package/dist/ui/base/tabbed-list-overlay-v2.js +317 -0
  120. package/dist/ui/base/tabbed-list-overlay.d.ts +153 -0
  121. package/dist/ui/base/tabbed-list-overlay.js +369 -0
  122. package/dist/ui/commands-overlay-v2.d.ts +33 -0
  123. package/dist/ui/commands-overlay-v2.js +441 -0
  124. package/dist/ui/commands-overlay.d.ts +7 -2
  125. package/dist/ui/commands-overlay.js +384 -355
  126. package/dist/ui/config-overlay.d.ts +5 -4
  127. package/dist/ui/config-overlay.js +243 -513
  128. package/dist/ui/conversation.d.ts +75 -4
  129. package/dist/ui/conversation.js +374 -161
  130. package/dist/ui/docs-overlay.d.ts +17 -0
  131. package/dist/ui/docs-overlay.js +303 -0
  132. package/dist/ui/ephemeral.d.ts +1 -1
  133. package/dist/ui/ephemeral.js +1 -1
  134. package/dist/ui/features/index.d.ts +34 -0
  135. package/dist/ui/features/index.js +34 -0
  136. package/dist/ui/features/input-feature.d.ts +85 -0
  137. package/dist/ui/features/input-feature.js +238 -0
  138. package/dist/ui/features/list-feature.d.ts +155 -0
  139. package/dist/ui/features/list-feature.js +244 -0
  140. package/dist/ui/features/pagination-feature.d.ts +154 -0
  141. package/dist/ui/features/pagination-feature.js +238 -0
  142. package/dist/ui/features/search-feature.d.ts +148 -0
  143. package/dist/ui/features/search-feature.js +185 -0
  144. package/dist/ui/features/tab-feature.d.ts +194 -0
  145. package/dist/ui/features/tab-feature.js +307 -0
  146. package/dist/ui/footer-v2.d.ts +222 -0
  147. package/dist/ui/footer-v2.js +1349 -0
  148. package/dist/ui/footer.d.ts +107 -0
  149. package/dist/ui/footer.js +359 -67
  150. package/dist/ui/guardrail-overlay.d.ts +29 -0
  151. package/dist/ui/guardrail-overlay.js +145 -0
  152. package/dist/ui/help-overlay-v2.d.ts +34 -0
  153. package/dist/ui/help-overlay-v2.js +309 -0
  154. package/dist/ui/help-overlay.d.ts +16 -0
  155. package/dist/ui/help-overlay.js +316 -0
  156. package/dist/ui/index.d.ts +1 -1
  157. package/dist/ui/index.js +1 -3
  158. package/dist/ui/init-overlay-v2.d.ts +34 -0
  159. package/dist/ui/init-overlay-v2.js +600 -0
  160. package/dist/ui/init-overlay.d.ts +12 -2
  161. package/dist/ui/init-overlay.js +349 -270
  162. package/dist/ui/input-prompt-v2.d.ts +1 -0
  163. package/dist/ui/input-prompt-v2.js +14 -6
  164. package/dist/ui/input-prompt.d.ts +116 -33
  165. package/dist/ui/input-prompt.js +536 -337
  166. package/dist/ui/iteration-limit-overlay-v2.d.ts +21 -0
  167. package/dist/ui/iteration-limit-overlay-v2.js +114 -0
  168. package/dist/ui/iteration-limit-overlay.d.ts +2 -2
  169. package/dist/ui/iteration-limit-overlay.js +92 -128
  170. package/dist/ui/keys-overlay-v2.d.ts +41 -0
  171. package/dist/ui/keys-overlay-v2.js +248 -0
  172. package/dist/ui/keys-overlay.d.ts +1 -0
  173. package/dist/ui/keys-overlay.js +203 -141
  174. package/dist/ui/line-utils.d.ts +88 -0
  175. package/dist/ui/line-utils.js +150 -0
  176. package/dist/ui/live-region.d.ts +161 -0
  177. package/dist/ui/live-region.js +387 -0
  178. package/dist/ui/mascot/expressions.d.ts +32 -0
  179. package/dist/ui/mascot/expressions.js +213 -0
  180. package/dist/ui/mascot/index.d.ts +8 -0
  181. package/dist/ui/mascot/index.js +8 -0
  182. package/dist/ui/mascot/renderer.d.ts +19 -0
  183. package/dist/ui/mascot/renderer.js +97 -0
  184. package/dist/ui/mascot-overlay-v2.d.ts +41 -0
  185. package/dist/ui/mascot-overlay-v2.js +138 -0
  186. package/dist/ui/mascot-overlay.d.ts +21 -0
  187. package/dist/ui/mascot-overlay.js +146 -0
  188. package/dist/ui/model-overlay-v2.d.ts +49 -0
  189. package/dist/ui/model-overlay-v2.js +118 -0
  190. package/dist/ui/model-overlay.d.ts +27 -0
  191. package/dist/ui/model-overlay.js +221 -0
  192. package/dist/ui/model-warning-overlay.js +3 -5
  193. package/dist/ui/new-overlay.d.ts +34 -0
  194. package/dist/ui/new-overlay.js +604 -0
  195. package/dist/ui/overlay/impl/agents-overlay-v2.d.ts +45 -0
  196. package/dist/ui/overlay/impl/agents-overlay-v2.js +825 -0
  197. package/dist/ui/overlay/impl/anchors-overlay-v2.d.ts +47 -0
  198. package/dist/ui/overlay/impl/anchors-overlay-v2.js +783 -0
  199. package/dist/ui/overlay/impl/arch-type-overlay-v2.d.ts +37 -0
  200. package/dist/ui/overlay/impl/arch-type-overlay-v2.js +240 -0
  201. package/dist/ui/overlay/impl/ask-user-overlay-v2.d.ts +72 -0
  202. package/dist/ui/overlay/impl/ask-user-overlay-v2.js +584 -0
  203. package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.d.ts +46 -0
  204. package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.js +204 -0
  205. package/dist/ui/overlay/impl/backlog-overlay-v2.d.ts +49 -0
  206. package/dist/ui/overlay/impl/backlog-overlay-v2.js +642 -0
  207. package/dist/ui/overlay/impl/commands-overlay-v2.d.ts +33 -0
  208. package/dist/ui/overlay/impl/commands-overlay-v2.js +441 -0
  209. package/dist/ui/overlay/impl/config-overlay-v2.d.ts +100 -0
  210. package/dist/ui/overlay/impl/config-overlay-v2.js +654 -0
  211. package/dist/ui/overlay/impl/dashboard-overlay-v2.d.ts +55 -0
  212. package/dist/ui/overlay/impl/dashboard-overlay-v2.js +359 -0
  213. package/dist/ui/overlay/impl/docs-overlay-v2.d.ts +45 -0
  214. package/dist/ui/overlay/impl/docs-overlay-v2.js +114 -0
  215. package/dist/ui/overlay/impl/document-detail-overlay-v2.d.ts +77 -0
  216. package/dist/ui/overlay/impl/document-detail-overlay-v2.js +1071 -0
  217. package/dist/ui/overlay/impl/guardrail-overlay-v2.d.ts +43 -0
  218. package/dist/ui/overlay/impl/guardrail-overlay-v2.js +114 -0
  219. package/dist/ui/overlay/impl/help-overlay-v2.d.ts +34 -0
  220. package/dist/ui/overlay/impl/help-overlay-v2.js +309 -0
  221. package/dist/ui/overlay/impl/init-overlay-v2.d.ts +77 -0
  222. package/dist/ui/overlay/impl/init-overlay-v2.js +593 -0
  223. package/dist/ui/overlay/impl/init-setup-overlay-v2.d.ts +25 -0
  224. package/dist/ui/overlay/impl/init-setup-overlay-v2.js +97 -0
  225. package/dist/ui/overlay/impl/iteration-limit-overlay-v2.d.ts +35 -0
  226. package/dist/ui/overlay/impl/iteration-limit-overlay-v2.js +105 -0
  227. package/dist/ui/overlay/impl/keys-overlay-v2.d.ts +41 -0
  228. package/dist/ui/overlay/impl/keys-overlay-v2.js +248 -0
  229. package/dist/ui/overlay/impl/mascot-overlay-v2.d.ts +41 -0
  230. package/dist/ui/overlay/impl/mascot-overlay-v2.js +138 -0
  231. package/dist/ui/overlay/impl/model-overlay-v2.d.ts +49 -0
  232. package/dist/ui/overlay/impl/model-overlay-v2.js +118 -0
  233. package/dist/ui/overlay/impl/model-warning-overlay-v2.d.ts +46 -0
  234. package/dist/ui/overlay/impl/model-warning-overlay-v2.js +132 -0
  235. package/dist/ui/overlay/impl/new-overlay-v2.d.ts +77 -0
  236. package/dist/ui/overlay/impl/new-overlay-v2.js +593 -0
  237. package/dist/ui/overlay/impl/permission-overlay-v2.d.ts +36 -0
  238. package/dist/ui/overlay/impl/permission-overlay-v2.js +380 -0
  239. package/dist/ui/overlay/impl/projects-overlay-v2.d.ts +36 -0
  240. package/dist/ui/overlay/impl/projects-overlay-v2.js +499 -0
  241. package/dist/ui/overlay/impl/theme-overlay-v2.d.ts +42 -0
  242. package/dist/ui/overlay/impl/theme-overlay-v2.js +135 -0
  243. package/dist/ui/overlay/impl/tools-overlay-v2.d.ts +47 -0
  244. package/dist/ui/overlay/impl/tools-overlay-v2.js +218 -0
  245. package/dist/ui/overlay/impl/tutorial-overlay-v2.d.ts +31 -0
  246. package/dist/ui/overlay/impl/tutorial-overlay-v2.js +1035 -0
  247. package/dist/ui/overlay/impl/workflow-overlay-v2.d.ts +80 -0
  248. package/dist/ui/overlay/impl/workflow-overlay-v2.js +637 -0
  249. package/dist/ui/overlay/index.d.ts +33 -0
  250. package/dist/ui/overlay/index.js +35 -0
  251. package/dist/ui/overlay/key-utils.d.ts +6 -0
  252. package/dist/ui/overlay/key-utils.js +6 -0
  253. package/dist/ui/overlay/overlay-types.d.ts +128 -0
  254. package/dist/ui/overlay/overlay-types.js +22 -0
  255. package/dist/ui/overlay/types.d.ts +135 -0
  256. package/dist/ui/overlay/types.js +22 -0
  257. package/dist/ui/overlays/help-overlay-v2.d.ts +28 -0
  258. package/dist/ui/overlays/help-overlay-v2.js +198 -0
  259. package/dist/ui/overlays/index.d.ts +11 -0
  260. package/dist/ui/overlays/index.js +11 -0
  261. package/dist/ui/overlays.d.ts +0 -4
  262. package/dist/ui/overlays.js +0 -444
  263. package/dist/ui/permission-overlay-v2.d.ts +36 -0
  264. package/dist/ui/permission-overlay-v2.js +380 -0
  265. package/dist/ui/permission-overlay.d.ts +1 -1
  266. package/dist/ui/permission-overlay.js +186 -298
  267. package/dist/ui/projects-overlay.d.ts +19 -0
  268. package/dist/ui/projects-overlay.js +484 -0
  269. package/dist/ui/providers/types.d.ts +178 -0
  270. package/dist/ui/providers/types.js +9 -0
  271. package/dist/ui/render-modes.d.ts +36 -0
  272. package/dist/ui/render-modes.js +44 -0
  273. package/dist/ui/startup-menu.d.ts +36 -0
  274. package/dist/ui/startup-menu.js +236 -0
  275. package/dist/ui/subagent-renderer.d.ts +117 -0
  276. package/dist/ui/subagent-renderer.js +334 -0
  277. package/dist/ui/terminal-codes.d.ts +94 -0
  278. package/dist/ui/terminal-codes.js +124 -0
  279. package/dist/ui/terminal-renderer.d.ts +221 -0
  280. package/dist/ui/terminal-renderer.js +751 -0
  281. package/dist/ui/terminal-ui.d.ts +463 -0
  282. package/dist/ui/terminal-ui.js +2296 -0
  283. package/dist/ui/terminal.d.ts +20 -0
  284. package/dist/ui/terminal.js +72 -0
  285. package/dist/ui/theme-overlay-v2.d.ts +42 -0
  286. package/dist/ui/theme-overlay-v2.js +135 -0
  287. package/dist/ui/theme-overlay.d.ts +24 -0
  288. package/dist/ui/theme-overlay.js +127 -0
  289. package/dist/ui/todo-zone.js +53 -25
  290. package/dist/ui/tool-formatters.d.ts +16 -0
  291. package/dist/ui/tool-formatters.js +516 -0
  292. package/dist/ui/tools-overlay-v2.d.ts +47 -0
  293. package/dist/ui/tools-overlay-v2.js +218 -0
  294. package/dist/ui/tools-overlay.d.ts +10 -2
  295. package/dist/ui/tools-overlay.js +172 -220
  296. package/dist/ui/tutorial-overlay-v2.d.ts +31 -0
  297. package/dist/ui/tutorial-overlay-v2.js +1035 -0
  298. package/dist/ui/tutorial-overlay.d.ts +1 -0
  299. package/dist/ui/tutorial-overlay.js +400 -302
  300. package/dist/ui/workflow-overlay.d.ts +22 -0
  301. package/dist/ui/workflow-overlay.js +636 -0
  302. package/dist/utils/debug-log.d.ts +28 -0
  303. package/dist/utils/debug-log.js +57 -0
  304. package/dist/utils/model-tiers.js +1 -1
  305. package/dist/utils/path-safety.d.ts +56 -0
  306. package/dist/utils/path-safety.js +239 -0
  307. package/dist/workflow/guided-mode-injector.d.ts +42 -0
  308. package/dist/workflow/guided-mode-injector.js +191 -0
  309. package/dist/workflow/index.d.ts +8 -0
  310. package/dist/workflow/index.js +8 -0
  311. package/dist/workflow/step-criteria.d.ts +62 -0
  312. package/dist/workflow/step-criteria.js +150 -0
  313. package/dist/workflow/step-tracker.d.ts +92 -0
  314. package/dist/workflow/step-tracker.js +141 -0
  315. package/package.json +12 -5
@@ -3,9 +3,10 @@
3
3
  *
4
4
  * Interactive tutorial that guides users through the compilr.dev workflow.
5
5
  * Supports guided sequential tour and topic-based navigation.
6
+ * Refactored to use BaseOverlay + ScreenStack.
6
7
  */
7
8
  import * as terminal from './terminal.js';
8
- import { getStyles } from '../themes/index.js';
9
+ import { BaseOverlay, BaseScreen, ScreenStack, stay, pushScreen, popScreen, closeOverlay, isEscape, isEnter, isCtrlC, isClose, isNavigateUp, isNavigateDown, isLeftArrow, isRightArrow, isVimLeft, isVimRight, isBackspace, } from './base/index.js';
9
10
  // =============================================================================
10
11
  // Helper
11
12
  // =============================================================================
@@ -16,16 +17,10 @@ function stripAnsi(str) {
16
17
  // eslint-disable-next-line no-control-regex
17
18
  return str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
18
19
  }
19
- function getBorder() {
20
- const s = getStyles();
21
- const cols = terminal.getTerminalWidth();
22
- return s.muted('─'.repeat(Math.max(1, cols - 1)));
23
- }
24
20
  // =============================================================================
25
21
  // Content
26
22
  // =============================================================================
27
- function buildTopics() {
28
- const s = getStyles();
23
+ function buildTopics(s) {
29
24
  return [
30
25
  // =========================================================================
31
26
  // Topic 1: Workflow Overview
@@ -80,20 +75,42 @@ function buildTopics() {
80
75
  '',
81
76
  ` The development workflow has five main stages:`,
82
77
  '',
83
- ` ${s.primary('/init')} Set up your project structure`,
84
- ` Creates COMPILR.md, backlog.md, and configuration`,
78
+ ` ${s.primary('/new')} Set up your project structure`,
79
+ ` Creates project in database with configuration`,
85
80
  '',
86
81
  ` ${s.primary('/design')} Gather requirements and create a PRD`,
87
- ` Comprehensive planning through conversation`,
82
+ ` Documents stored in database for persistence`,
88
83
  '',
89
84
  ` ${s.primary('/backlog')} Manage your work items`,
90
- ` Prioritize, track status, break down tasks`,
85
+ ` Track status, prioritize, break down tasks`,
91
86
  '',
92
87
  ` ${s.primary('/build')} Implement features from the backlog`,
93
88
  ` AI-assisted coding with your approval`,
94
89
  '',
95
- ` ${s.secondary('Iterate')} Refine and improve continuously`,
96
- ` Use /refine, /arch, /prd to evolve the project`,
90
+ ` ${s.primary('/workflow')} Check progress and next steps`,
91
+ ` See where you are and what's next`,
92
+ '',
93
+ ],
94
+ },
95
+ {
96
+ title: 'Project Management',
97
+ lines: [
98
+ '',
99
+ ` ${s.secondary('Track Your Progress')}`,
100
+ '',
101
+ ` ${s.primaryBold('/projects')}`,
102
+ ` View all your projects in one place.`,
103
+ ` Filter by status: Active, Paused, Completed, Archived.`,
104
+ ` Switch between projects or open project directories.`,
105
+ '',
106
+ ` ${s.primaryBold('/workflow')}`,
107
+ ` See your current project's workflow status.`,
108
+ ` Shows which phases are complete and what's next.`,
109
+ ` Quick actions to jump to the right command.`,
110
+ '',
111
+ ` ${s.primaryBold('/docs')}`,
112
+ ` Browse documents created during design.`,
113
+ ` View PRDs, architecture docs, and notes.`,
97
114
  '',
98
115
  ],
99
116
  },
@@ -108,16 +125,15 @@ function buildTopics() {
108
125
  description: 'Setting up a new project',
109
126
  pages: [
110
127
  {
111
- title: '/init Command',
128
+ title: '/new Command',
112
129
  lines: [
113
130
  '',
114
- ` ${s.primaryBold('/init')} creates your project foundation through an 8-step wizard.`,
131
+ ` ${s.primaryBold('/new')} creates your project foundation through an 8-step wizard.`,
115
132
  '',
116
133
  ` ${s.secondary('What it creates:')}`,
117
134
  '',
118
- ` ${s.success('+')} Project directory with proper structure`,
135
+ ` ${s.success('+')} ${s.primary('Project in database')} - Tracked for easy management`,
119
136
  ` ${s.success('+')} ${s.primary('COMPILR.md')} - Context file for the AI assistant`,
120
- ` ${s.success('+')} ${s.primary('backlog.md')} - Work item tracking`,
121
137
  ` ${s.success('+')} ${s.primary('.compilr/config.json')} - Project configuration`,
122
138
  ` ${s.success('+')} Tech stack setup based on your choices`,
123
139
  '',
@@ -125,26 +141,26 @@ function buildTopics() {
125
141
  ` - Project name and description`,
126
142
  ` - Project type (web, api, cli, fullstack)`,
127
143
  ` - Tech stack preferences`,
128
- ` - Documentation setup (single or two repos)`,
144
+ ` - Workflow mode (flexible or guided)`,
129
145
  '',
130
146
  ],
131
147
  },
132
148
  {
133
- title: '/init - Setup Options',
149
+ title: '/new - Database Tracking',
134
150
  lines: [
135
151
  '',
136
- ` ${s.secondary('Single Repository Setup')}`,
137
- ` Everything in one directory: code, docs, and backlog.`,
138
- ` Best for: small projects, personal projects, quick starts.`,
152
+ ` ${s.secondary('Project Database')}`,
153
+ ` All projects are tracked in a local SQLite database.`,
154
+ ` This enables: multi-project switching, progress tracking,`,
155
+ ` and persistent work item management.`,
139
156
  '',
140
- ` ${s.secondary('Two Repository Setup')}`,
141
- ` Separate repository for documentation and planning.`,
142
- ` Best for: team projects, complex projects, when you want`,
143
- ` to keep planning separate from code.`,
157
+ ` ${s.secondary('View Your Projects')}`,
158
+ ` Use ${s.primary('/projects')} to see all your projects.`,
159
+ ` Use ${s.primary('/workflow')} to see current project status.`,
144
160
  '',
145
- ` ${s.muted('Tip: Run /init in an empty directory to start fresh.')}`,
161
+ ` ${s.muted('Tip: Run /new in an empty directory to start fresh.')}`,
146
162
  '',
147
- ` After /init completes, the AI reads your COMPILR.md to understand`,
163
+ ` After /new completes, the AI reads your COMPILR.md to understand`,
148
164
  ` your project context. You're ready for the next step: ${s.primary('/design')}`,
149
165
  '',
150
166
  ],
@@ -191,19 +207,18 @@ function buildTopics() {
191
207
  ` ${s.secondary('What /design creates:')}`,
192
208
  '',
193
209
  ` ${s.success('+')} ${s.primary('Product Requirements Document (PRD)')}`,
194
- ` A comprehensive document capturing your vision,`,
195
- ` features, technical requirements, and constraints.`,
210
+ ` Stored in the database for persistence.`,
211
+ ` Use ${s.primary('/docs')} to view it anytime.`,
196
212
  '',
197
213
  ` ${s.success('+')} ${s.primary('5-15 Backlog Items')}`,
198
- ` Auto-generated from your requirements,`,
199
- ` ready to be built with /build.`,
214
+ ` Stored in database with status tracking.`,
215
+ ` Use ${s.primary('/backlog')} to manage them.`,
200
216
  '',
201
217
  ` ${s.success('+')} ${s.primary('Clear Acceptance Criteria')}`,
202
218
  ` Each backlog item has defined done criteria`,
203
219
  ` so you know when it's complete.`,
204
220
  '',
205
221
  ` ${s.muted('Best for: serious projects that need thorough planning upfront.')}`,
206
- ` ${s.muted('Expect: 30+ minute conversation to capture everything.')}`,
207
222
  '',
208
223
  ],
209
224
  },
@@ -336,11 +351,11 @@ function buildTopics() {
336
351
  '',
337
352
  ` Items move through three statuses:`,
338
353
  '',
339
- ` ${s.warning('pending')} Not started yet`,
354
+ ` ${s.warning('backlog')} Not started yet`,
340
355
  ` ${s.muted('↓')}`,
341
356
  ` ${s.primary('in-progress')} Currently being worked on`,
342
357
  ` ${s.muted('↓')}`,
343
- ` ${s.success('done')} Completed`,
358
+ ` ${s.success('completed')} Done!`,
344
359
  '',
345
360
  ` ${s.secondary('Item Types:')}`,
346
361
  ` ${s.muted('Feature')} New functionality to build`,
@@ -348,7 +363,7 @@ function buildTopics() {
348
363
  ` ${s.muted('Tech-Debt')} Code improvements needed`,
349
364
  ` ${s.muted('Chore')} Maintenance tasks`,
350
365
  '',
351
- ` Items are stored in ${s.primary('backlog.md')} and can also be edited manually.`,
366
+ ` Items are stored in the ${s.primary('database')} and persist across sessions.`,
352
367
  '',
353
368
  ],
354
369
  },
@@ -568,6 +583,29 @@ function buildTopics() {
568
583
  '',
569
584
  ],
570
585
  },
586
+ {
587
+ title: 'Anchors - Persistent Context',
588
+ lines: [
589
+ '',
590
+ ` ${s.secondary('Anchors')} are critical pieces of information that survive`,
591
+ ` context compaction. They're always included at the top of context.`,
592
+ '',
593
+ ` ${s.primaryBold('/anchors')}`,
594
+ ` View and manage your anchors.`,
595
+ ` Add, edit, or remove persistent context.`,
596
+ '',
597
+ ` ${s.secondary('When to use anchors:')}`,
598
+ ` ${s.muted('+')} Project context that must never be forgotten`,
599
+ ` ${s.muted('+')} Key architectural decisions`,
600
+ ` ${s.muted('+')} User preferences for code style`,
601
+ ` ${s.muted('+')} Important constraints or requirements`,
602
+ '',
603
+ ` ${s.secondary('Scope:')}`,
604
+ ` ${s.primary('Global')} - Persists across all projects`,
605
+ ` ${s.primary('Project')} - Specific to current project`,
606
+ '',
607
+ ],
608
+ },
571
609
  ],
572
610
  },
573
611
  // =========================================================================
@@ -624,7 +662,7 @@ function buildTopics() {
624
662
  title: 'Best Practices',
625
663
  lines: [
626
664
  '',
627
- ` ${s.primary('1.')} Start with ${s.primaryBold('/init')}, then ${s.primaryBold('/design')} or ${s.primaryBold('/sketch')}`,
665
+ ` ${s.primary('1.')} Start with ${s.primaryBold('/new')}, then ${s.primaryBold('/design')} or ${s.primaryBold('/sketch')}`,
628
666
  ` Don't skip planning - it pays off later.`,
629
667
  '',
630
668
  ` ${s.primary('2.')} Keep backlog items small and focused`,
@@ -646,291 +684,351 @@ function buildTopics() {
646
684
  ];
647
685
  }
648
686
  // =============================================================================
649
- // Rendering
687
+ // Screens
650
688
  // =============================================================================
651
- function renderWelcome(state, previousLineCount) {
652
- const s = getStyles();
653
- const lines = [];
654
- const border = getBorder();
655
- if (previousLineCount > 0) {
656
- terminal.clearLinesAbove(previousLineCount);
689
+ /**
690
+ * Welcome screen - shows entry options (guided tour or topic list)
691
+ */
692
+ class WelcomeScreen extends BaseScreen {
693
+ state;
694
+ styles;
695
+ topics;
696
+ selectedIndex = 0;
697
+ constructor(state, styles, topics) {
698
+ super();
699
+ this.state = state;
700
+ this.styles = styles;
701
+ this.topics = topics;
657
702
  }
658
- lines.push(border);
659
- lines.push(` ${s.primaryBold('compilr.dev Tutorial')}`);
660
- lines.push('');
661
- lines.push(` Learn the AI-powered development workflow that takes you`);
662
- lines.push(` from idea to implementation with structure and discipline.`);
663
- lines.push('');
664
- lines.push(` This tutorial covers: initialization, design, backlog`);
665
- lines.push(` management, building, configuration, and best practices.`);
666
- lines.push('');
667
- lines.push(` ${s.muted('How would you like to explore?')}`);
668
- lines.push('');
669
- const options = [
670
- { label: 'Start Guided Tour', desc: 'Step-by-step walkthrough (recommended)' },
671
- { label: 'Jump to Topic', desc: 'Go directly to a specific topic' },
672
- ];
673
- for (let i = 0; i < options.length; i++) {
674
- const opt = options[i];
675
- const selected = i === state.welcomeIndex;
676
- const prefix = selected ? s.primary(' ') : ' ';
677
- const label = selected ? s.primary(opt.label) : opt.label;
678
- const desc = s.muted(opt.desc);
679
- lines.push(`${prefix}${label.padEnd(22)} ${desc}`);
703
+ render() {
704
+ const s = this.styles;
705
+ const cols = terminal.getTerminalWidth();
706
+ const border = s.muted('─'.repeat(Math.max(1, cols - 1)));
707
+ const lines = [];
708
+ lines.push(border);
709
+ lines.push(` ${s.primaryBold('compilr.dev Tutorial')}`);
710
+ lines.push('');
711
+ lines.push(` Learn the AI-powered development workflow that takes you`);
712
+ lines.push(` from idea to implementation with structure and discipline.`);
713
+ lines.push('');
714
+ lines.push(` This tutorial covers: initialization, design, backlog`);
715
+ lines.push(` management, building, configuration, and best practices.`);
716
+ lines.push('');
717
+ lines.push(` ${s.muted('How would you like to explore?')}`);
718
+ lines.push('');
719
+ const options = [
720
+ { label: 'Start Guided Tour', desc: 'Step-by-step walkthrough (recommended)' },
721
+ { label: 'Jump to Topic', desc: 'Go directly to a specific topic' },
722
+ ];
723
+ for (let i = 0; i < options.length; i++) {
724
+ const opt = options[i];
725
+ const selected = i === this.selectedIndex;
726
+ const prefix = selected ? s.primary(' ❯ ') : ' ';
727
+ const label = selected ? s.primary(opt.label) : opt.label;
728
+ const desc = s.muted(opt.desc);
729
+ lines.push(`${prefix}${label.padEnd(22)} ${desc}`);
730
+ }
731
+ lines.push('');
732
+ lines.push(border);
733
+ lines.push(s.muted(' ↑↓/jk Navigate · Enter Select · q/Esc Exit'));
734
+ return lines;
735
+ }
736
+ handleKey(data) {
737
+ // Close keys
738
+ if (isCtrlC(data) || isClose(data)) {
739
+ return closeOverlay({ completed: false });
740
+ }
741
+ // Navigation
742
+ if (isNavigateUp(data) && this.selectedIndex > 0) {
743
+ this.selectedIndex--;
744
+ return stay();
745
+ }
746
+ if (isNavigateDown(data) && this.selectedIndex < 1) {
747
+ this.selectedIndex++;
748
+ return stay();
749
+ }
750
+ // Enter - select option
751
+ if (isEnter(data)) {
752
+ if (this.selectedIndex === 0) {
753
+ // Guided mode
754
+ this.state.isGuidedMode = true;
755
+ this.state.currentTopicIndex = 0;
756
+ this.state.currentPageIndex = 0;
757
+ return pushScreen(new ViewingScreen(this.state, this.styles, this.topics));
758
+ }
759
+ else {
760
+ // Topic list mode
761
+ return pushScreen(new TopicListScreen(this.state, this.styles, this.topics));
762
+ }
763
+ }
764
+ return stay(false);
680
765
  }
681
- lines.push('');
682
- lines.push(border);
683
- lines.push(s.muted(' ↑↓ Navigate · Enter Select · Esc Exit'));
684
- terminal.write(lines.join('\n'));
685
- return lines.length;
686
766
  }
687
- function renderTopicList(state, topics, previousLineCount) {
688
- const s = getStyles();
689
- const lines = [];
690
- const border = getBorder();
691
- if (previousLineCount > 0) {
692
- terminal.clearLinesAbove(previousLineCount);
767
+ /**
768
+ * Topic list screen - shows all topics to choose from
769
+ */
770
+ class TopicListScreen extends BaseScreen {
771
+ state;
772
+ styles;
773
+ topics;
774
+ constructor(state, styles, topics) {
775
+ super();
776
+ this.state = state;
777
+ this.styles = styles;
778
+ this.topics = topics;
779
+ }
780
+ render() {
781
+ const s = this.styles;
782
+ const cols = terminal.getTerminalWidth();
783
+ const border = s.muted('─'.repeat(Math.max(1, cols - 1)));
784
+ const lines = [];
785
+ lines.push(border);
786
+ lines.push(` ${s.primaryBold('Tutorial Topics')}`);
787
+ lines.push('');
788
+ for (let i = 0; i < this.topics.length; i++) {
789
+ const topic = this.topics[i];
790
+ const selected = i === this.state.topicListIndex;
791
+ const prefix = selected ? s.primary(' ❯ ') : ' ';
792
+ const name = selected ? s.primary(topic.name) : topic.name;
793
+ const desc = s.muted(topic.description);
794
+ const pages = s.muted(`(${String(topic.pages.length)} ${topic.pages.length === 1 ? 'page' : 'pages'})`);
795
+ lines.push(`${prefix}${name.padEnd(26)} ${desc.padEnd(30)} ${pages}`);
796
+ }
797
+ lines.push('');
798
+ lines.push(border);
799
+ lines.push(s.muted(' ↑↓/jk Navigate · Enter View · q/Esc Close'));
800
+ return lines;
693
801
  }
694
- lines.push(border);
695
- lines.push(` ${s.primaryBold('Tutorial Topics')}`);
696
- lines.push('');
697
- for (let i = 0; i < topics.length; i++) {
698
- const topic = topics[i];
699
- const selected = i === state.topicListIndex;
700
- const prefix = selected ? s.primary(' ❯ ') : ' ';
701
- const name = selected ? s.primary(topic.name) : topic.name;
702
- const desc = s.muted(topic.description);
703
- const pages = s.muted(`(${String(topic.pages.length)} ${topic.pages.length === 1 ? 'page' : 'pages'})`);
704
- lines.push(`${prefix}${name.padEnd(26)} ${desc.padEnd(30)} ${pages}`);
802
+ handleKey(data) {
803
+ // Ctrl+C or q closes overlay
804
+ if (isCtrlC(data)) {
805
+ return closeOverlay({ completed: false });
806
+ }
807
+ // Escape goes back to welcome
808
+ if (isEscape(data)) {
809
+ return popScreen();
810
+ }
811
+ // Navigation
812
+ if (isNavigateUp(data) && this.state.topicListIndex > 0) {
813
+ this.state.topicListIndex--;
814
+ return stay();
815
+ }
816
+ if (isNavigateDown(data) && this.state.topicListIndex < this.topics.length - 1) {
817
+ this.state.topicListIndex++;
818
+ return stay();
819
+ }
820
+ // Enter - view topic
821
+ if (isEnter(data)) {
822
+ this.state.isGuidedMode = false;
823
+ this.state.currentTopicIndex = this.state.topicListIndex;
824
+ this.state.currentPageIndex = 0;
825
+ return pushScreen(new ViewingScreen(this.state, this.styles, this.topics));
826
+ }
827
+ return stay(false);
705
828
  }
706
- lines.push('');
707
- lines.push(border);
708
- lines.push(s.muted(' ↑↓ Navigate · Enter View · Esc Back'));
709
- terminal.write(lines.join('\n'));
710
- return lines.length;
711
829
  }
712
- function renderPage(state, topics, previousLineCount) {
713
- const s = getStyles();
714
- const lines = [];
715
- const border = getBorder();
716
- if (previousLineCount > 0) {
717
- terminal.clearLinesAbove(previousLineCount);
830
+ /**
831
+ * Viewing screen - shows a page from a topic with navigation
832
+ */
833
+ class ViewingScreen extends BaseScreen {
834
+ state;
835
+ styles;
836
+ topics;
837
+ constructor(state, styles, topics) {
838
+ super();
839
+ this.state = state;
840
+ this.styles = styles;
841
+ this.topics = topics;
842
+ }
843
+ render() {
844
+ const s = this.styles;
845
+ const cols = terminal.getTerminalWidth();
846
+ const border = s.muted('─'.repeat(Math.max(1, cols - 1)));
847
+ const lines = [];
848
+ const topic = this.topics[this.state.currentTopicIndex];
849
+ const page = topic.pages[this.state.currentPageIndex];
850
+ const totalPages = topic.pages.length;
851
+ // Calculate overall progress for guided mode
852
+ let progressText = `[${String(this.state.currentPageIndex + 1)}/${String(totalPages)}]`;
853
+ if (this.state.isGuidedMode) {
854
+ let totalPagesAll = 0;
855
+ let currentPageAll = 0;
856
+ for (let i = 0; i < this.topics.length; i++) {
857
+ if (i < this.state.currentTopicIndex) {
858
+ currentPageAll += this.topics[i].pages.length;
859
+ }
860
+ else if (i === this.state.currentTopicIndex) {
861
+ currentPageAll += this.state.currentPageIndex + 1;
862
+ }
863
+ totalPagesAll += this.topics[i].pages.length;
864
+ }
865
+ progressText = `[${String(currentPageAll)}/${String(totalPagesAll)}]`;
866
+ }
867
+ // Header - calculate padding to right-align progress indicator
868
+ const titleStyled = s.primaryBold(page.title);
869
+ const progressStyled = s.muted(progressText);
870
+ const titleLen = stripAnsi(titleStyled).length + 1; // +1 for leading space
871
+ const progressLen = stripAnsi(progressStyled).length;
872
+ const padding = Math.max(1, cols - titleLen - progressLen - 2); // -2 for margins
873
+ lines.push(border);
874
+ lines.push(` ${titleStyled}${' '.repeat(padding)}${progressStyled}`);
875
+ lines.push('');
876
+ // Content
877
+ for (const line of page.lines) {
878
+ lines.push(line);
879
+ }
880
+ // Pad to consistent height
881
+ while (lines.length < 20) {
882
+ lines.push('');
883
+ }
884
+ // Navigation footer
885
+ lines.push(border);
886
+ if (this.state.isGuidedMode) {
887
+ lines.push(s.muted(' ←/→/hl Navigate · Esc Exit Tour'));
888
+ }
889
+ else {
890
+ lines.push(s.muted(' ←/→/hl Navigate · Esc Back to Topics'));
891
+ }
892
+ return lines;
718
893
  }
719
- const topic = topics[state.currentTopicIndex];
720
- const page = topic.pages[state.currentPageIndex];
721
- const totalPages = topic.pages.length;
722
- // Calculate overall progress for guided mode
723
- let progressText = `[${String(state.currentPageIndex + 1)}/${String(totalPages)}]`;
724
- if (state.isGuidedMode) {
725
- let totalPagesAll = 0;
726
- let currentPageAll = 0;
727
- for (let i = 0; i < topics.length; i++) {
728
- if (i < state.currentTopicIndex) {
729
- currentPageAll += topics[i].pages.length;
894
+ handleKey(data) {
895
+ // Ctrl+C closes overlay
896
+ if (isCtrlC(data)) {
897
+ return closeOverlay({ completed: false });
898
+ }
899
+ const topic = this.topics[this.state.currentTopicIndex];
900
+ const totalPages = topic.pages.length;
901
+ // Escape goes back
902
+ if (isEscape(data)) {
903
+ return popScreen();
904
+ }
905
+ // Previous page (left arrow, h, or backspace)
906
+ if (isLeftArrow(data) || isVimLeft(data) || isBackspace(data)) {
907
+ if (this.state.currentPageIndex > 0) {
908
+ this.state.currentPageIndex--;
909
+ return stay();
730
910
  }
731
- else if (i === state.currentTopicIndex) {
732
- currentPageAll += state.currentPageIndex + 1;
911
+ else if (this.state.isGuidedMode && this.state.currentTopicIndex > 0) {
912
+ this.state.currentTopicIndex--;
913
+ this.state.currentPageIndex = this.topics[this.state.currentTopicIndex].pages.length - 1;
914
+ return stay();
915
+ }
916
+ return stay(false);
917
+ }
918
+ // Next page (right arrow, l, or enter)
919
+ if (isRightArrow(data) || isVimRight(data) || isEnter(data)) {
920
+ if (this.state.currentPageIndex < totalPages - 1) {
921
+ this.state.currentPageIndex++;
922
+ return stay();
923
+ }
924
+ else if (this.state.isGuidedMode) {
925
+ if (this.state.currentTopicIndex < this.topics.length - 1) {
926
+ this.state.currentTopicIndex++;
927
+ this.state.currentPageIndex = 0;
928
+ return stay();
929
+ }
930
+ else {
931
+ // End of guided tour - show complete screen
932
+ return pushScreen(new CompleteScreen(this.styles));
933
+ }
733
934
  }
734
- totalPagesAll += topics[i].pages.length;
935
+ return stay(false);
735
936
  }
736
- progressText = `[${String(currentPageAll)}/${String(totalPagesAll)}]`;
937
+ return stay(false);
737
938
  }
738
- // Header - calculate padding to right-align progress indicator
739
- const titleStyled = s.primaryBold(page.title);
740
- const progressStyled = s.muted(progressText);
741
- const titleLen = stripAnsi(titleStyled).length + 1; // +1 for leading space
742
- const progressLen = stripAnsi(progressStyled).length;
743
- const cols = terminal.getTerminalWidth();
744
- const padding = Math.max(1, cols - titleLen - progressLen - 2); // -2 for margins
745
- lines.push(border);
746
- lines.push(` ${titleStyled}${' '.repeat(padding)}${progressStyled}`);
747
- lines.push('');
748
- // Content
749
- for (const line of page.lines) {
750
- lines.push(line);
939
+ }
940
+ /**
941
+ * Complete screen - shows completion message
942
+ */
943
+ class CompleteScreen extends BaseScreen {
944
+ styles;
945
+ constructor(styles) {
946
+ super();
947
+ this.styles = styles;
751
948
  }
752
- // Pad to consistent height
753
- while (lines.length < 20) {
949
+ render() {
950
+ const s = this.styles;
951
+ const cols = terminal.getTerminalWidth();
952
+ const border = s.muted('─'.repeat(Math.max(1, cols - 1)));
953
+ const lines = [];
954
+ lines.push(border);
955
+ lines.push(` ${s.success('Tutorial Complete!')}`);
754
956
  lines.push('');
957
+ lines.push(` You've learned the compilr.dev workflow!`);
958
+ lines.push('');
959
+ lines.push(` ${s.secondary('Key commands to remember:')}`);
960
+ lines.push('');
961
+ lines.push(` ${s.primary('/new')} Start a new project`);
962
+ lines.push(` ${s.primary('/design')} Plan your requirements`);
963
+ lines.push(` ${s.primary('/backlog')} Manage your work items`);
964
+ lines.push(` ${s.primary('/build')} Implement features`);
965
+ lines.push(` ${s.primary('/help')} See all commands`);
966
+ lines.push('');
967
+ lines.push(` ${s.secondary('Ready to start?')}`);
968
+ lines.push(` Try ${s.primary('/new')} in a new directory!`);
969
+ lines.push('');
970
+ lines.push(border);
971
+ lines.push(s.muted(' Press any key to exit...'));
972
+ return lines;
755
973
  }
756
- // Navigation footer
757
- lines.push(border);
758
- if (state.isGuidedMode) {
759
- lines.push(s.muted(' ←/→ Navigate · Esc Exit Tour'));
760
- }
761
- else {
762
- lines.push(s.muted(' ←/→ Navigate · Esc Back to Topics'));
974
+ handleKey(_data) {
975
+ // Any key closes the overlay with completed = true
976
+ return closeOverlay({ completed: true });
763
977
  }
764
- terminal.write(lines.join('\n'));
765
- return lines.length;
766
978
  }
767
- function renderComplete(previousLineCount) {
768
- const s = getStyles();
769
- const lines = [];
770
- const border = getBorder();
771
- if (previousLineCount > 0) {
772
- terminal.clearLinesAbove(previousLineCount);
979
+ // =============================================================================
980
+ // Overlay Class
981
+ // =============================================================================
982
+ class TutorialOverlay extends BaseOverlay {
983
+ screenStack;
984
+ topics;
985
+ constructor() {
986
+ super({
987
+ lineCount: 0,
988
+ maxLineCount: 0,
989
+ topicListIndex: 0,
990
+ currentTopicIndex: 0,
991
+ currentPageIndex: 0,
992
+ isGuidedMode: false,
993
+ });
994
+ this.topics = buildTopics(this.styles);
995
+ this.screenStack = new ScreenStack();
996
+ this.screenStack.push(new WelcomeScreen(this.state, this.styles, this.topics));
773
997
  }
774
- lines.push(border);
775
- lines.push(` ${s.success('Tutorial Complete!')}`);
776
- lines.push('');
777
- lines.push(` You've learned the compilr.dev workflow!`);
778
- lines.push('');
779
- lines.push(` ${s.secondary('Key commands to remember:')}`);
780
- lines.push('');
781
- lines.push(` ${s.primary('/init')} Start a new project`);
782
- lines.push(` ${s.primary('/design')} Plan your requirements`);
783
- lines.push(` ${s.primary('/backlog')} Manage your work items`);
784
- lines.push(` ${s.primary('/build')} Implement features`);
785
- lines.push(` ${s.primary('/help')} See all commands`);
786
- lines.push('');
787
- lines.push(` ${s.secondary('Ready to start?')}`);
788
- lines.push(` Try ${s.primary('/init')} in a new directory!`);
789
- lines.push('');
790
- lines.push(border);
791
- lines.push(s.muted(' Press any key to exit...'));
792
- terminal.write(lines.join('\n'));
793
- return lines.length;
794
- }
795
- function render(state, topics, previousLineCount) {
796
- switch (state.mode) {
797
- case 'welcome':
798
- return renderWelcome(state, previousLineCount);
799
- case 'topic-list':
800
- return renderTopicList(state, topics, previousLineCount);
801
- case 'viewing':
802
- return renderPage(state, topics, previousLineCount);
803
- case 'complete':
804
- return renderComplete(previousLineCount);
998
+ render() {
999
+ const screen = this.screenStack.current();
1000
+ return screen?.render() ?? [];
1001
+ }
1002
+ handleKey(data) {
1003
+ const screen = this.screenStack.current();
1004
+ if (!screen) {
1005
+ this.close({ completed: false });
1006
+ return;
1007
+ }
1008
+ const result = screen.handleKey(data);
1009
+ switch (result.action) {
1010
+ case 'stay':
1011
+ if (result.render) {
1012
+ this.update();
1013
+ }
1014
+ break;
1015
+ case 'push':
1016
+ this.screenStack.push(result.screen);
1017
+ this.update();
1018
+ break;
1019
+ case 'pop':
1020
+ this.screenStack.pop();
1021
+ this.update();
1022
+ break;
1023
+ case 'close':
1024
+ this.close(result.result);
1025
+ break;
1026
+ }
805
1027
  }
806
1028
  }
807
1029
  // =============================================================================
808
- // Main Export
1030
+ // Export Function (Backward Compatible)
809
1031
  // =============================================================================
810
1032
  export async function showTutorialOverlay() {
811
- const topics = buildTopics();
812
- const state = {
813
- mode: 'welcome',
814
- welcomeIndex: 0,
815
- topicListIndex: 0,
816
- currentTopicIndex: 0,
817
- currentPageIndex: 0,
818
- isGuidedMode: false,
819
- };
820
- let lineCount = 0;
821
- lineCount = render(state, topics, lineCount);
822
- return new Promise((resolve) => {
823
- const stdin = process.stdin;
824
- stdin.setRawMode(true);
825
- stdin.resume();
826
- const cleanup = () => {
827
- stdin.removeListener('data', handleKey);
828
- stdin.setRawMode(false);
829
- stdin.pause();
830
- terminal.clearLinesAbove(lineCount);
831
- };
832
- const handleKey = (data) => {
833
- const key = data.toString();
834
- const isEscape = key === '\x1B' && data.length === 1;
835
- const isEnter = key === '\r' || key === '\n';
836
- const isUpArrow = key === '\x1B[A';
837
- const isDownArrow = key === '\x1B[B';
838
- const isLeftArrow = key === '\x1B[D';
839
- const isRightArrow = key === '\x1B[C';
840
- const isCtrlC = key === '\x03';
841
- if (isCtrlC) {
842
- cleanup();
843
- resolve({ completed: false });
844
- return;
845
- }
846
- switch (state.mode) {
847
- case 'welcome': {
848
- if (isEscape) {
849
- cleanup();
850
- resolve({ completed: false });
851
- return;
852
- }
853
- if (isUpArrow && state.welcomeIndex > 0) {
854
- state.welcomeIndex--;
855
- }
856
- else if (isDownArrow && state.welcomeIndex < 1) {
857
- state.welcomeIndex++;
858
- }
859
- else if (isEnter) {
860
- if (state.welcomeIndex === 0) {
861
- state.isGuidedMode = true;
862
- state.currentTopicIndex = 0;
863
- state.currentPageIndex = 0;
864
- state.mode = 'viewing';
865
- }
866
- else {
867
- state.mode = 'topic-list';
868
- }
869
- }
870
- break;
871
- }
872
- case 'topic-list': {
873
- if (isEscape) {
874
- state.mode = 'welcome';
875
- }
876
- else if (isUpArrow && state.topicListIndex > 0) {
877
- state.topicListIndex--;
878
- }
879
- else if (isDownArrow && state.topicListIndex < topics.length - 1) {
880
- state.topicListIndex++;
881
- }
882
- else if (isEnter) {
883
- state.isGuidedMode = false;
884
- state.currentTopicIndex = state.topicListIndex;
885
- state.currentPageIndex = 0;
886
- state.mode = 'viewing';
887
- }
888
- break;
889
- }
890
- case 'viewing': {
891
- const topic = topics[state.currentTopicIndex];
892
- const totalPages = topic.pages.length;
893
- if (isEscape) {
894
- if (state.isGuidedMode) {
895
- state.mode = 'welcome';
896
- }
897
- else {
898
- state.mode = 'topic-list';
899
- }
900
- }
901
- else if (isLeftArrow || key === '\x7F') {
902
- if (state.currentPageIndex > 0) {
903
- state.currentPageIndex--;
904
- }
905
- else if (state.isGuidedMode && state.currentTopicIndex > 0) {
906
- state.currentTopicIndex--;
907
- state.currentPageIndex = topics[state.currentTopicIndex].pages.length - 1;
908
- }
909
- }
910
- else if (isRightArrow || isEnter) {
911
- if (state.currentPageIndex < totalPages - 1) {
912
- state.currentPageIndex++;
913
- }
914
- else if (state.isGuidedMode) {
915
- if (state.currentTopicIndex < topics.length - 1) {
916
- state.currentTopicIndex++;
917
- state.currentPageIndex = 0;
918
- }
919
- else {
920
- state.mode = 'complete';
921
- }
922
- }
923
- }
924
- break;
925
- }
926
- case 'complete': {
927
- cleanup();
928
- resolve({ completed: true });
929
- return;
930
- }
931
- }
932
- lineCount = render(state, topics, lineCount);
933
- };
934
- stdin.on('data', handleKey);
935
- });
1033
+ return new TutorialOverlay().show();
936
1034
  }