sillyspec 3.20.3 → 3.20.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 (224) hide show
  1. package/.claude/skills/sillyspec-archive/SKILL.md +21 -17
  2. package/.claude/skills/sillyspec-auto/SKILL.md +83 -77
  3. package/.claude/skills/sillyspec-brainstorm/SKILL.md +44 -17
  4. package/.claude/skills/sillyspec-commit/SKILL.md +106 -105
  5. package/.claude/skills/sillyspec-continue/SKILL.md +45 -44
  6. package/.claude/skills/sillyspec-doctor/SKILL.md +31 -22
  7. package/.claude/skills/sillyspec-execute/SKILL.md +30 -17
  8. package/.claude/skills/sillyspec-explore/SKILL.md +109 -96
  9. package/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  10. package/.claude/skills/sillyspec-plan/SKILL.md +21 -52
  11. package/.claude/skills/sillyspec-propose/SKILL.md +21 -17
  12. package/.claude/skills/sillyspec-quick/SKILL.md +21 -17
  13. package/.claude/skills/sillyspec-resume/SKILL.md +68 -111
  14. package/.claude/skills/sillyspec-scan/SKILL.md +21 -17
  15. package/.claude/skills/sillyspec-state/SKILL.md +54 -54
  16. package/.claude/skills/sillyspec-status/SKILL.md +21 -17
  17. package/.claude/skills/sillyspec-verify/SKILL.md +21 -17
  18. package/.claude/skills/sillyspec-workspace/SKILL.md +157 -149
  19. package/.husky/pre-push +13 -0
  20. package/CLAUDE.md +18 -0
  21. package/README.md +198 -186
  22. package/SKILL.md +90 -87
  23. package/bin/sillyspec.js +2 -2
  24. package/docs/brainstorm-plan-contract.md +64 -0
  25. package/docs/plan-execute-contract.md +123 -0
  26. package/docs/platform-scan-protocol.md +298 -0
  27. package/docs/revision-mode.md +115 -0
  28. package/docs/sillyspec/file-lifecycle/known-implementation-gaps.md +99 -0
  29. package/docs/sillyspec/file-lifecycle/platform-workflows-sync.md +218 -0
  30. package/docs/sillyspec/file-lifecycle/stage-artifacts.md +167 -0
  31. package/docs/sillyspec/file-lifecycle/storage-and-state.md +148 -0
  32. package/docs/sillyspec/file-lifecycle/worktree-and-guard.md +211 -0
  33. package/docs/sillyspec/file-lifecycle.md +125 -0
  34. package/docs/workflow-contract-regression.md +106 -0
  35. package/docs/worktree-isolation.md +252 -0
  36. package/package.json +40 -34
  37. package/packages/dashboard/dist/assets/{index-D1EVTLmc.js → index-Bq_Z2hne.js} +7446 -7446
  38. package/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  39. package/packages/dashboard/dist/index.html +16 -16
  40. package/packages/dashboard/dist/prototype-dashboard.html +836 -0
  41. package/packages/dashboard/dist/prototype-overview.html +256 -0
  42. package/packages/dashboard/index.html +15 -15
  43. package/packages/dashboard/package-lock.json +2384 -2384
  44. package/packages/dashboard/package.json +25 -25
  45. package/packages/dashboard/public/prototype-dashboard.html +836 -0
  46. package/packages/dashboard/public/prototype-overview.html +256 -0
  47. package/packages/dashboard/server/executor.js +86 -86
  48. package/packages/dashboard/server/index.js +588 -508
  49. package/packages/dashboard/server/parser.js +526 -458
  50. package/packages/dashboard/server/watcher.js +350 -342
  51. package/packages/dashboard/src/App.vue +558 -325
  52. package/packages/dashboard/src/components/ActionBar.vue +93 -84
  53. package/packages/dashboard/src/components/CommandPalette.vue +96 -92
  54. package/packages/dashboard/src/components/DetailPanel.vue +137 -137
  55. package/packages/dashboard/src/components/DocPreview.vue +105 -8
  56. package/packages/dashboard/src/components/DocTree.vue +75 -19
  57. package/packages/dashboard/src/components/HResizeHandle.vue +48 -0
  58. package/packages/dashboard/src/components/LogStream.vue +65 -65
  59. package/packages/dashboard/src/components/PipelineStage.vue +95 -75
  60. package/packages/dashboard/src/components/PipelineView.vue +156 -129
  61. package/packages/dashboard/src/components/ProjectCard.vue +187 -0
  62. package/packages/dashboard/src/components/ProjectList.vue +210 -210
  63. package/packages/dashboard/src/components/ProjectOverview.vue +113 -139
  64. package/packages/dashboard/src/components/StageBadge.vue +67 -53
  65. package/packages/dashboard/src/components/StepCard.vue +94 -89
  66. package/packages/dashboard/src/components/VResizeHandle.vue +61 -0
  67. package/packages/dashboard/src/components/detail/DocsDetail.vue +48 -48
  68. package/packages/dashboard/src/components/detail/GitDetail.vue +61 -61
  69. package/packages/dashboard/src/components/detail/TechDetail.vue +43 -43
  70. package/packages/dashboard/src/composables/useDashboard.js +192 -164
  71. package/packages/dashboard/src/composables/useKeyboard.js +119 -119
  72. package/packages/dashboard/src/composables/useLayout.js +131 -0
  73. package/packages/dashboard/src/composables/useWebSocket.js +129 -129
  74. package/packages/dashboard/src/main.js +8 -8
  75. package/packages/dashboard/src/style.css +132 -132
  76. package/packages/dashboard/vite.config.js +18 -18
  77. package/src/brainstorm-postcheck.js +158 -0
  78. package/src/change-list.js +52 -0
  79. package/src/change-risk-profile.js +352 -0
  80. package/src/classify-change.js +73 -0
  81. package/src/constants.js +70 -0
  82. package/src/contract-matrix.js +278 -0
  83. package/src/db.js +201 -0
  84. package/src/endpoint-extractor.js +315 -0
  85. package/src/hooks/claude-pre-tool-use.cjs +125 -0
  86. package/src/hooks/worktree-guard.js +761 -0
  87. package/src/index.js +922 -252
  88. package/src/init.js +431 -375
  89. package/src/knowledge-match.js +130 -0
  90. package/src/migrate.js +117 -117
  91. package/src/modules.js +482 -0
  92. package/src/progress.js +1734 -508
  93. package/src/run.js +3465 -652
  94. package/src/scan-postcheck.js +387 -0
  95. package/src/setup.js +398 -460
  96. package/src/stage-contract.js +700 -0
  97. package/src/stages/archive.js +160 -54
  98. package/src/stages/brainstorm-auto.js +229 -0
  99. package/src/stages/brainstorm.js +645 -239
  100. package/src/stages/doctor.js +365 -312
  101. package/src/stages/execute.js +625 -264
  102. package/src/stages/explore.js +34 -0
  103. package/src/stages/index.js +29 -35
  104. package/src/stages/knowledge.js +498 -0
  105. package/src/stages/plan-postcheck.js +511 -0
  106. package/src/stages/plan.js +582 -279
  107. package/src/stages/propose.js +174 -115
  108. package/src/stages/quick.js +102 -63
  109. package/src/stages/scan.js +558 -141
  110. package/src/stages/status.js +65 -65
  111. package/src/stages/verify.js +322 -135
  112. package/src/sync.js +497 -0
  113. package/src/task-review.js +346 -0
  114. package/src/workflow.js +785 -0
  115. package/src/worktree-apply.js +549 -0
  116. package/src/worktree-deps.js +185 -0
  117. package/src/worktree.js +982 -0
  118. package/templates/workflows/archive-impact.yaml +79 -0
  119. package/templates/workflows/scan-docs.yaml +132 -0
  120. package/test/brainstorm-plan-contract.test.mjs +273 -0
  121. package/test/check-syntax.mjs +26 -0
  122. package/test/cli-top-level-aliases.test.mjs +174 -0
  123. package/test/contract-artifacts.test.mjs +323 -0
  124. package/test/decision-supersede.test.mjs +277 -0
  125. package/test/knowledge-match.test.mjs +231 -0
  126. package/test/plan-execute-contract.test.mjs +330 -0
  127. package/test/plan-optimization.test.mjs +572 -0
  128. package/test/platform-artifacts.test.mjs +190 -0
  129. package/test/platform-failure-samples.test.mjs +199 -0
  130. package/test/platform-recovery-chain.test.mjs +179 -0
  131. package/test/platform-recovery.test.mjs +167 -0
  132. package/test/platform-scan-p0.test.mjs +175 -0
  133. package/test/revision-v1.test.mjs +1145 -0
  134. package/test/run-sanitize-project-name.test.mjs +51 -0
  135. package/test/run-scan-postcheck-fail.test.mjs +64 -0
  136. package/test/run-scan-project-parse.test.mjs +200 -0
  137. package/test/run-tests.mjs +48 -0
  138. package/test/scan-docs-yaml-placeholders.test.mjs +84 -0
  139. package/test/scan-knowledge.test.mjs +175 -0
  140. package/test/scan-paths.test.mjs +68 -0
  141. package/test/scan-postcheck-project-priority.test.mjs +85 -0
  142. package/test/scan-postcheck.test.mjs +197 -0
  143. package/test/scan-workflow-anyfailed-block.test.mjs +52 -0
  144. package/test/spec-dir.test.mjs +206 -0
  145. package/test/stage-contract-failed-post-check.test.mjs +102 -0
  146. package/test/stage-contract.test.mjs +299 -0
  147. package/test/stage-definitions.test.mjs +39 -0
  148. package/test/wait-gates.test.mjs +501 -0
  149. package/test/workflow-spec-base.test.mjs +142 -0
  150. package/test/worktree-deps-provision.test.mjs +148 -0
  151. package/test/worktree-guard.test.mjs +136 -0
  152. package/test/worktree-native-overlay.test.mjs +188 -0
  153. package/.sillyspec/changes/archive/2026-04-08-derive-state/design.md +0 -97
  154. package/.sillyspec/changes/archive/2026-04-08-derive-state/plan.md +0 -51
  155. package/.sillyspec/changes/archive/2026-04-08-derive-state/proposal.md +0 -29
  156. package/.sillyspec/changes/archive/2026-04-08-derive-state/requirements.md +0 -34
  157. package/.sillyspec/changes/archive/2026-04-08-derive-state/tasks.md +0 -13
  158. package/.sillyspec/changes/archive/2026-04-08-derive-state/verify-result.md +0 -43
  159. package/.sillyspec/changes/auto-mode/design.md +0 -50
  160. package/.sillyspec/changes/auto-mode/proposal.md +0 -19
  161. package/.sillyspec/changes/auto-mode/requirements.md +0 -21
  162. package/.sillyspec/changes/auto-mode/tasks.md +0 -7
  163. package/.sillyspec/changes/brainstorm-archive/2026-04-05-dashboard-design.md +0 -206
  164. package/.sillyspec/changes/brainstorm-archive/2026-04-05-unified-docs-design.md +0 -199
  165. package/.sillyspec/changes/dashboard/design.md +0 -219
  166. package/.sillyspec/changes/dashboard/design.md.braindraft +0 -206
  167. package/.sillyspec/changes/run-command-design/design.md +0 -1230
  168. package/.sillyspec/changes/unified-docs-design/design.md +0 -199
  169. package/.sillyspec/docs/sillyspec/scan/.gitkeep +0 -0
  170. package/.sillyspec/knowledge/INDEX.md +0 -8
  171. package/.sillyspec/knowledge/uncategorized.md +0 -3
  172. package/.sillyspec/plans/2026-04-05-dashboard.md +0 -737
  173. package/.sillyspec/projects/sillyspec.yaml +0 -3
  174. package/dist/steps/brainstorm/01-load-context.md +0 -30
  175. package/dist/steps/brainstorm/02-reuse-check.md +0 -6
  176. package/dist/steps/brainstorm/03-prototype-analysis.md +0 -11
  177. package/dist/steps/brainstorm/04-module-split.md +0 -23
  178. package/dist/steps/brainstorm/05-dialog-explore.md +0 -8
  179. package/dist/steps/brainstorm/06-propose-approaches.md +0 -3
  180. package/dist/steps/brainstorm/07-present-design.md +0 -3
  181. package/dist/steps/brainstorm/08-write-design.md +0 -21
  182. package/dist/steps/brainstorm/09-self-review.md +0 -15
  183. package/dist/steps/brainstorm/10-user-confirm.md +0 -3
  184. package/dist/steps/brainstorm/11-output-spec.md +0 -7
  185. package/dist/steps/brainstorm/manifest.yaml +0 -26
  186. package/dist/steps/execute/01-load-context.md +0 -41
  187. package/dist/steps/execute/02-scan-conventions.md +0 -47
  188. package/dist/steps/execute/03-skill-mcp.md +0 -19
  189. package/dist/steps/execute/04-assign-task.md +0 -22
  190. package/dist/steps/execute/04b-prompt-template.md +0 -54
  191. package/dist/steps/execute/05-write-test.md +0 -7
  192. package/dist/steps/execute/06-write-code.md +0 -8
  193. package/dist/steps/execute/07-run-test.md +0 -26
  194. package/dist/steps/execute/08-fix-issues.md +0 -28
  195. package/dist/steps/execute/09-next-task.md +0 -33
  196. package/dist/steps/execute/manifest.yaml +0 -28
  197. package/dist/steps/plan/01-load-context.md +0 -22
  198. package/dist/steps/plan/02-anchor-confirm.md +0 -1
  199. package/dist/steps/plan/03-expand-tasks.md +0 -33
  200. package/dist/steps/plan/04-mark-order.md +0 -15
  201. package/dist/steps/plan/05-e2e-planning.md +0 -17
  202. package/dist/steps/plan/06-self-check.md +0 -16
  203. package/dist/steps/plan/07-save.md +0 -1
  204. package/dist/steps/plan/manifest.yaml +0 -18
  205. package/dist/steps/scan/01-env-detect.md +0 -51
  206. package/dist/steps/scan/02-tech-stack.md +0 -16
  207. package/dist/steps/scan/03-conventions.md +0 -16
  208. package/dist/steps/scan/04-structure.md +0 -19
  209. package/dist/steps/scan/05-quality.md +0 -18
  210. package/dist/steps/scan/06-complete.md +0 -49
  211. package/dist/steps/scan/manifest.yaml +0 -16
  212. package/dist/steps/verify/01-load-specs.md +0 -28
  213. package/dist/steps/verify/02-check-tasks.md +0 -1
  214. package/dist/steps/verify/03-check-design.md +0 -6
  215. package/dist/steps/verify/04-run-tests.md +0 -7
  216. package/dist/steps/verify/05-e2e-tests.md +0 -27
  217. package/dist/steps/verify/05b-e2e-fix.md +0 -33
  218. package/dist/steps/verify/06-code-quality.md +0 -25
  219. package/dist/steps/verify/07-lint-check.md +0 -27
  220. package/dist/steps/verify/08-output-report.md +0 -14
  221. package/dist/steps/verify/manifest.yaml +0 -22
  222. package/packages/dashboard/dist/assets/index-DGe8CqeP.css +0 -1
  223. package/src/derive.js +0 -147
  224. package/src/step.js +0 -543
@@ -1,121 +1,121 @@
1
- import { reactive, computed } from 'vue'
2
-
3
- /**
4
- * Dashboard state management composable
5
- * @returns {object} Dashboard state and methods
6
- */
7
- export function useDashboard() {
8
- // Reactive state
9
- const state = reactive({
10
- projects: [],
11
- activeProject: null,
12
- activeStep: null,
13
- logs: [],
14
- isPanelOpen: true,
15
- executingProject: null,
16
- isLoading: true,
17
- activeTab: 'pipeline',
18
- docs: { groups: [] },
19
- selectedDocFile: null,
20
- docContent: '',
21
- docLoading: false
22
- })
23
-
24
- /**
25
- * Get project by name
26
- * @param {string} name - Project name
27
- * @returns {object|null} Project or null
28
- */
29
- function getProject(path) {
30
- return state.projects.find(p => p.path === path) || null
31
- }
32
-
33
- /**
34
- * Select a project as active
35
- * @param {object|string} project - Project object or path
36
- */
37
- function selectProject(project) {
38
- const proj = typeof project === 'string'
39
- ? getProject(project)
40
- : project
41
-
42
- if (proj) {
43
- state.activeProject = proj
44
- state.activeStep = null
45
- state.logs = []
46
- state.selectedDocFile = null
47
- state.docContent = ''
48
-
49
- // Load initial logs from project state if available
50
- if (proj.state?.progress?.currentLogs) {
51
- appendLog(proj.state.progress.currentLogs)
52
- }
53
- }
54
- }
55
-
56
- /**
57
- * Select a step within active project
58
- * @param {object} step - Step object
59
- */
60
- function selectStep(step) {
61
- state.activeStep = step
62
- }
63
-
64
- /**
65
- * Append log lines to logs buffer
66
- * @param {string|string[]} lines - Log line(s) to append
67
- */
68
- function appendLog(lines) {
69
- const newLines = Array.isArray(lines) ? lines : [lines]
70
-
71
- for (const line of newLines) {
72
- const timestamp = new Date().toISOString()
73
- state.logs.push({
74
- id: `${timestamp}-${Math.random().toString(36).substr(2, 9)}`,
75
- timestamp,
76
- content: line,
77
- type: 'info'
78
- })
79
- }
80
-
81
- // Keep only last 500 lines
82
- if (state.logs.length > 500) {
83
- state.logs = state.logs.slice(-500)
84
- }
85
- }
86
-
87
- /**
88
- * Clear logs buffer
89
- */
90
- function clearLogs() {
91
- state.logs = []
92
- }
93
-
94
- /**
95
- * Toggle detail panel open/closed
96
- */
97
- function togglePanel() {
98
- state.isPanelOpen = !state.isPanelOpen
99
- }
100
-
101
- /**
102
- * Open detail panel
103
- */
104
- function openPanel() {
105
- state.isPanelOpen = true
106
- }
107
-
108
- /**
109
- * Close detail panel
110
- */
111
- function closePanel() {
112
- state.isPanelOpen = false
113
- }
114
-
115
- /**
116
- * Update projects list
117
- * @param {array} projects - New projects array
118
- */
1
+ import { reactive, computed } from 'vue'
2
+
3
+ /**
4
+ * Dashboard state management composable
5
+ * @returns {object} Dashboard state and methods
6
+ */
7
+ export function useDashboard() {
8
+ // Reactive state
9
+ const state = reactive({
10
+ projects: [],
11
+ activeProject: null,
12
+ activeStep: null,
13
+ logs: [],
14
+ isPanelOpen: true,
15
+ executingProject: null,
16
+ isLoading: true,
17
+ activeTab: 'pipeline',
18
+ docs: { groups: [] },
19
+ selectedDocFile: null,
20
+ docContent: '',
21
+ docLoading: false
22
+ })
23
+
24
+ /**
25
+ * Get project by name
26
+ * @param {string} name - Project name
27
+ * @returns {object|null} Project or null
28
+ */
29
+ function getProject(path) {
30
+ return state.projects.find(p => p.path === path) || null
31
+ }
32
+
33
+ /**
34
+ * Select a project as active
35
+ * @param {object|string} project - Project object or path
36
+ */
37
+ function selectProject(project) {
38
+ const proj = typeof project === 'string'
39
+ ? getProject(project)
40
+ : project
41
+
42
+ if (proj) {
43
+ state.activeProject = proj
44
+ state.activeStep = null
45
+ state.logs = []
46
+ state.selectedDocFile = null
47
+ state.docContent = ''
48
+
49
+ // Load initial logs from project state if available
50
+ if (proj.state?.progress?.currentLogs) {
51
+ appendLog(proj.state.progress.currentLogs)
52
+ }
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Select a step within active project
58
+ * @param {object} step - Step object
59
+ */
60
+ function selectStep(step) {
61
+ state.activeStep = step
62
+ }
63
+
64
+ /**
65
+ * Append log lines to logs buffer
66
+ * @param {string|string[]} lines - Log line(s) to append
67
+ */
68
+ function appendLog(lines) {
69
+ const newLines = Array.isArray(lines) ? lines : [lines]
70
+
71
+ for (const line of newLines) {
72
+ const timestamp = new Date().toISOString()
73
+ state.logs.push({
74
+ id: `${timestamp}-${Math.random().toString(36).substr(2, 9)}`,
75
+ timestamp,
76
+ content: line,
77
+ type: 'info'
78
+ })
79
+ }
80
+
81
+ // Keep only last 500 lines
82
+ if (state.logs.length > 500) {
83
+ state.logs = state.logs.slice(-500)
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Clear logs buffer
89
+ */
90
+ function clearLogs() {
91
+ state.logs = []
92
+ }
93
+
94
+ /**
95
+ * Toggle detail panel open/closed
96
+ */
97
+ function togglePanel() {
98
+ state.isPanelOpen = !state.isPanelOpen
99
+ }
100
+
101
+ /**
102
+ * Open detail panel
103
+ */
104
+ function openPanel() {
105
+ state.isPanelOpen = true
106
+ }
107
+
108
+ /**
109
+ * Close detail panel
110
+ */
111
+ function closePanel() {
112
+ state.isPanelOpen = false
113
+ }
114
+
115
+ /**
116
+ * Update projects list
117
+ * @param {array} projects - New projects array
118
+ */
119
119
  function updateProjects(projects) {
120
120
  state.isLoading = false
121
121
  state.projects = projects
@@ -125,61 +125,89 @@ export function useDashboard() {
125
125
  const updated = getProject(state.activeProject.path)
126
126
  if (updated) {
127
127
  state.activeProject = updated
128
+ return
128
129
  }
129
130
  }
130
- }
131
131
 
132
- /**
133
- * Set executing project state
134
- * @param {string|null} projectName - Project name or null
135
- */
136
- function setExecuting(projectName) {
137
- state.executingProject = projectName
132
+ state.activeProject = state.projects[0] || null
138
133
  }
139
134
 
140
135
  /**
141
- * Check if a project is currently executing
142
- * @param {string} projectName - Project name
143
- * @returns {boolean}
136
+ * Merge a single project update into the current project list.
137
+ * @param {object} project - Partial project payload containing at least path
144
138
  */
145
- function isExecuting(projectName) {
146
- return state.executingProject === projectName
147
- }
139
+ function updateProject(project) {
140
+ if (!project?.path) return
148
141
 
149
- // Computed properties
150
- const activeProjectName = computed(() => state.activeProject?.name || null)
151
- const activeProjectPath = computed(() => state.activeProject?.path || null)
152
- const activeProjectStage = computed(() => state.activeProject?.state?.currentStage || null)
153
- const hasProjects = computed(() => state.projects.length > 0)
154
- const activeProjectSteps = computed(() => {
155
- if (!state.activeProject?.state?.progress?.stages) return []
156
- const currentStage = state.activeProject.state.currentStage
157
- const stageData = state.activeProject.state.progress.stages[currentStage]
158
- return stageData?.steps || []
159
- })
142
+ const index = state.projects.findIndex(p => p.path === project.path)
143
+ if (index === -1) return
160
144
 
161
- return {
162
- state,
163
- getProject,
164
- selectProject,
165
- selectStep,
166
- appendLog,
167
- clearLogs,
168
- togglePanel,
169
- openPanel,
145
+ const updated = {
146
+ ...state.projects[index],
147
+ ...project,
148
+ state: project.state ?? state.projects[index].state,
149
+ overview: project.overview ?? state.projects[index].overview
150
+ }
151
+
152
+ state.projects.splice(index, 1, updated)
153
+
154
+ if (state.activeProject?.path === project.path) {
155
+ state.activeProject = updated
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Set executing project state
161
+ * @param {string|null} projectName - Project name or null
162
+ */
163
+ function setExecuting(projectName) {
164
+ state.executingProject = projectName
165
+ }
166
+
167
+ /**
168
+ * Check if a project is currently executing
169
+ * @param {string} projectName - Project name
170
+ * @returns {boolean}
171
+ */
172
+ function isExecuting(projectName) {
173
+ return state.executingProject === projectName
174
+ }
175
+
176
+ // Computed properties
177
+ const activeProjectName = computed(() => state.activeProject?.name || null)
178
+ const activeProjectPath = computed(() => state.activeProject?.path || null)
179
+ const activeProjectStage = computed(() => state.activeProject?.state?.currentStage || null)
180
+ const hasProjects = computed(() => state.projects.length > 0)
181
+ const activeProjectSteps = computed(() => {
182
+ if (!state.activeProject?.state?.progress?.stages) return []
183
+ const currentStage = state.activeProject.state.currentStage
184
+ const stageData = state.activeProject.state.progress.stages[currentStage]
185
+ return stageData?.steps || []
186
+ })
187
+
188
+ return {
189
+ state,
190
+ getProject,
191
+ selectProject,
192
+ selectStep,
193
+ appendLog,
194
+ clearLogs,
195
+ togglePanel,
196
+ openPanel,
170
197
  closePanel,
171
198
  updateProjects,
199
+ updateProject,
172
200
  setExecuting,
173
- isExecuting,
174
- activeProjectName,
175
- activeProjectPath,
176
- activeProjectStage,
177
- hasProjects,
178
- activeProjectSteps,
179
- setActiveTab(tab) { state.activeTab = tab },
180
- updateDocs(docs) { state.docs = docs },
181
- selectDocFile(file) { state.selectedDocFile = file },
182
- setDocContent(content) { state.docContent = content },
183
- setDocLoading(loading) { state.docLoading = loading }
184
- }
185
- }
201
+ isExecuting,
202
+ activeProjectName,
203
+ activeProjectPath,
204
+ activeProjectStage,
205
+ hasProjects,
206
+ activeProjectSteps,
207
+ setActiveTab(tab) { state.activeTab = tab },
208
+ updateDocs(docs) { state.docs = docs },
209
+ selectDocFile(file) { state.selectedDocFile = file },
210
+ setDocContent(content) { state.docContent = content },
211
+ setDocLoading(loading) { state.docLoading = loading }
212
+ }
213
+ }
@@ -1,119 +1,119 @@
1
- import { onMounted, onUnmounted } from 'vue'
2
-
3
- /**
4
- * Keyboard shortcuts composable
5
- * @param {object} options - Configuration options
6
- * @returns {object} Keyboard API
7
- */
8
- export function useKeyboard(options = {}) {
9
- const {
10
- onCmdK = null,
11
- onJ = null,
12
- onK = null,
13
- onEscape = null,
14
- onEnter = null,
15
- onArrowUp = null,
16
- onArrowDown = null,
17
- disabled: initialDisabled = false
18
- } = options
19
-
20
- let isDisabled = initialDisabled
21
-
22
- /**
23
- * Handle keyboard events
24
- * @param {KeyboardEvent} event
25
- */
26
- function handleKeyDown(event) {
27
- if (isDisabled) return
28
-
29
- // Ignore if in input field
30
- const target = event.target
31
- if (target.tagName === 'INPUT' ||
32
- target.tagName === 'TEXTAREA' ||
33
- target.contentEditable === 'true') {
34
- return
35
- }
36
-
37
- const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0
38
- const cmdOrCtrl = isMac ? event.metaKey : event.ctrlKey
39
-
40
- // Cmd/Ctrl + K
41
- if (cmdOrCtrl && event.key === 'k') {
42
- event.preventDefault()
43
- if (onCmdK) onCmdK()
44
- }
45
-
46
- // J - navigate down
47
- if (event.key === 'j' && !cmdOrCtrl) {
48
- event.preventDefault()
49
- if (onJ) onJ()
50
- }
51
-
52
- // K - navigate up
53
- if (event.key === 'k' && !cmdOrCtrl) {
54
- event.preventDefault()
55
- if (onK) onK()
56
- }
57
-
58
- // Escape
59
- if (event.key === 'Escape') {
60
- event.preventDefault()
61
- if (onEscape) onEscape()
62
- }
63
-
64
- // Enter
65
- if (event.key === 'Enter' && !cmdOrCtrl) {
66
- event.preventDefault()
67
- if (onEnter) onEnter()
68
- }
69
-
70
- // Arrow Up
71
- if (event.key === 'ArrowUp' && !cmdOrCtrl) {
72
- event.preventDefault()
73
- if (onArrowUp) onArrowUp()
74
- }
75
-
76
- // Arrow Down
77
- if (event.key === 'ArrowDown' && !cmdOrCtrl) {
78
- event.preventDefault()
79
- if (onArrowDown) onArrowDown()
80
- }
81
- }
82
-
83
- onMounted(() => {
84
- window.addEventListener('keydown', handleKeyDown)
85
- })
86
-
87
- onUnmounted(() => {
88
- window.removeEventListener('keydown', handleKeyDown)
89
- })
90
-
91
- return {
92
- disable: () => { isDisabled = true },
93
- enable: () => { isDisabled = false }
94
- }
95
- }
96
-
97
- /**
98
- * Global keyboard shortcuts for dashboard
99
- * @param {object} callbacks - Callback functions for each shortcut
100
- * @returns {object} Keyboard API
101
- */
102
- export function useDashboardKeyboard(callbacks = {}) {
103
- const {
104
- onOpenCommandPalette,
105
- onNavigateDown,
106
- onNavigateUp,
107
- onClose,
108
- onSelect,
109
- onPanelToggle
110
- } = callbacks
111
-
112
- return useKeyboard({
113
- onCmdK: onOpenCommandPalette,
114
- onJ: onNavigateDown,
115
- onK: onNavigateUp,
116
- onEscape: onClose,
117
- onEnter: onSelect
118
- })
119
- }
1
+ import { onMounted, onUnmounted } from 'vue'
2
+
3
+ /**
4
+ * Keyboard shortcuts composable
5
+ * @param {object} options - Configuration options
6
+ * @returns {object} Keyboard API
7
+ */
8
+ export function useKeyboard(options = {}) {
9
+ const {
10
+ onCmdK = null,
11
+ onJ = null,
12
+ onK = null,
13
+ onEscape = null,
14
+ onEnter = null,
15
+ onArrowUp = null,
16
+ onArrowDown = null,
17
+ disabled: initialDisabled = false
18
+ } = options
19
+
20
+ let isDisabled = initialDisabled
21
+
22
+ /**
23
+ * Handle keyboard events
24
+ * @param {KeyboardEvent} event
25
+ */
26
+ function handleKeyDown(event) {
27
+ if (isDisabled) return
28
+
29
+ // Ignore if in input field
30
+ const target = event.target
31
+ if (target.tagName === 'INPUT' ||
32
+ target.tagName === 'TEXTAREA' ||
33
+ target.contentEditable === 'true') {
34
+ return
35
+ }
36
+
37
+ const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0
38
+ const cmdOrCtrl = isMac ? event.metaKey : event.ctrlKey
39
+
40
+ // Cmd/Ctrl + K
41
+ if (cmdOrCtrl && event.key === 'k') {
42
+ event.preventDefault()
43
+ if (onCmdK) onCmdK()
44
+ }
45
+
46
+ // J - navigate down
47
+ if (event.key === 'j' && !cmdOrCtrl) {
48
+ event.preventDefault()
49
+ if (onJ) onJ()
50
+ }
51
+
52
+ // K - navigate up
53
+ if (event.key === 'k' && !cmdOrCtrl) {
54
+ event.preventDefault()
55
+ if (onK) onK()
56
+ }
57
+
58
+ // Escape
59
+ if (event.key === 'Escape') {
60
+ event.preventDefault()
61
+ if (onEscape) onEscape()
62
+ }
63
+
64
+ // Enter
65
+ if (event.key === 'Enter' && !cmdOrCtrl) {
66
+ event.preventDefault()
67
+ if (onEnter) onEnter()
68
+ }
69
+
70
+ // Arrow Up
71
+ if (event.key === 'ArrowUp' && !cmdOrCtrl) {
72
+ event.preventDefault()
73
+ if (onArrowUp) onArrowUp()
74
+ }
75
+
76
+ // Arrow Down
77
+ if (event.key === 'ArrowDown' && !cmdOrCtrl) {
78
+ event.preventDefault()
79
+ if (onArrowDown) onArrowDown()
80
+ }
81
+ }
82
+
83
+ onMounted(() => {
84
+ window.addEventListener('keydown', handleKeyDown)
85
+ })
86
+
87
+ onUnmounted(() => {
88
+ window.removeEventListener('keydown', handleKeyDown)
89
+ })
90
+
91
+ return {
92
+ disable: () => { isDisabled = true },
93
+ enable: () => { isDisabled = false }
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Global keyboard shortcuts for dashboard
99
+ * @param {object} callbacks - Callback functions for each shortcut
100
+ * @returns {object} Keyboard API
101
+ */
102
+ export function useDashboardKeyboard(callbacks = {}) {
103
+ const {
104
+ onOpenCommandPalette,
105
+ onNavigateDown,
106
+ onNavigateUp,
107
+ onClose,
108
+ onSelect,
109
+ onPanelToggle
110
+ } = callbacks
111
+
112
+ return useKeyboard({
113
+ onCmdK: onOpenCommandPalette,
114
+ onJ: onNavigateDown,
115
+ onK: onNavigateUp,
116
+ onEscape: onClose,
117
+ onEnter: onSelect
118
+ })
119
+ }