mstro-app 0.3.7 → 0.3.9

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 (131) hide show
  1. package/README.md +4 -8
  2. package/bin/mstro.js +54 -15
  3. package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -1
  4. package/dist/server/cli/headless/claude-invoker.js +18 -9
  5. package/dist/server/cli/headless/claude-invoker.js.map +1 -1
  6. package/dist/server/cli/headless/headless-logger.d.ts +10 -0
  7. package/dist/server/cli/headless/headless-logger.d.ts.map +1 -0
  8. package/dist/server/cli/headless/headless-logger.js +66 -0
  9. package/dist/server/cli/headless/headless-logger.js.map +1 -0
  10. package/dist/server/cli/headless/mcp-config.d.ts.map +1 -1
  11. package/dist/server/cli/headless/mcp-config.js +6 -5
  12. package/dist/server/cli/headless/mcp-config.js.map +1 -1
  13. package/dist/server/cli/headless/runner.d.ts.map +1 -1
  14. package/dist/server/cli/headless/runner.js +4 -0
  15. package/dist/server/cli/headless/runner.js.map +1 -1
  16. package/dist/server/cli/headless/stall-assessor.d.ts +21 -0
  17. package/dist/server/cli/headless/stall-assessor.d.ts.map +1 -1
  18. package/dist/server/cli/headless/stall-assessor.js +74 -20
  19. package/dist/server/cli/headless/stall-assessor.js.map +1 -1
  20. package/dist/server/cli/headless/tool-watchdog.d.ts +0 -12
  21. package/dist/server/cli/headless/tool-watchdog.d.ts.map +1 -1
  22. package/dist/server/cli/headless/tool-watchdog.js +30 -9
  23. package/dist/server/cli/headless/tool-watchdog.js.map +1 -1
  24. package/dist/server/cli/headless/types.d.ts +8 -1
  25. package/dist/server/cli/headless/types.d.ts.map +1 -1
  26. package/dist/server/cli/improvisation-session-manager.d.ts +16 -0
  27. package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -1
  28. package/dist/server/cli/improvisation-session-manager.js +94 -11
  29. package/dist/server/cli/improvisation-session-manager.js.map +1 -1
  30. package/dist/server/index.js +0 -4
  31. package/dist/server/index.js.map +1 -1
  32. package/dist/server/mcp/bouncer-cli.d.ts +3 -0
  33. package/dist/server/mcp/bouncer-cli.d.ts.map +1 -0
  34. package/dist/server/mcp/bouncer-cli.js +54 -0
  35. package/dist/server/mcp/bouncer-cli.js.map +1 -0
  36. package/dist/server/mcp/bouncer-integration.d.ts +2 -0
  37. package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
  38. package/dist/server/mcp/bouncer-integration.js +55 -39
  39. package/dist/server/mcp/bouncer-integration.js.map +1 -1
  40. package/dist/server/mcp/bouncer-sandbox.d.ts +60 -0
  41. package/dist/server/mcp/bouncer-sandbox.d.ts.map +1 -0
  42. package/dist/server/mcp/bouncer-sandbox.js +182 -0
  43. package/dist/server/mcp/bouncer-sandbox.js.map +1 -0
  44. package/dist/server/mcp/security-patterns.d.ts +6 -12
  45. package/dist/server/mcp/security-patterns.d.ts.map +1 -1
  46. package/dist/server/mcp/security-patterns.js +197 -10
  47. package/dist/server/mcp/security-patterns.js.map +1 -1
  48. package/dist/server/services/plan/composer.d.ts +4 -0
  49. package/dist/server/services/plan/composer.d.ts.map +1 -0
  50. package/dist/server/services/plan/composer.js +181 -0
  51. package/dist/server/services/plan/composer.js.map +1 -0
  52. package/dist/server/services/plan/dependency-resolver.d.ts +28 -0
  53. package/dist/server/services/plan/dependency-resolver.d.ts.map +1 -0
  54. package/dist/server/services/plan/dependency-resolver.js +152 -0
  55. package/dist/server/services/plan/dependency-resolver.js.map +1 -0
  56. package/dist/server/services/plan/executor.d.ts +91 -0
  57. package/dist/server/services/plan/executor.d.ts.map +1 -0
  58. package/dist/server/services/plan/executor.js +545 -0
  59. package/dist/server/services/plan/executor.js.map +1 -0
  60. package/dist/server/services/plan/parser.d.ts +11 -0
  61. package/dist/server/services/plan/parser.d.ts.map +1 -0
  62. package/dist/server/services/plan/parser.js +415 -0
  63. package/dist/server/services/plan/parser.js.map +1 -0
  64. package/dist/server/services/plan/state-reconciler.d.ts +2 -0
  65. package/dist/server/services/plan/state-reconciler.d.ts.map +1 -0
  66. package/dist/server/services/plan/state-reconciler.js +105 -0
  67. package/dist/server/services/plan/state-reconciler.js.map +1 -0
  68. package/dist/server/services/plan/types.d.ts +120 -0
  69. package/dist/server/services/plan/types.d.ts.map +1 -0
  70. package/dist/server/services/plan/types.js +4 -0
  71. package/dist/server/services/plan/types.js.map +1 -0
  72. package/dist/server/services/plan/watcher.d.ts +14 -0
  73. package/dist/server/services/plan/watcher.d.ts.map +1 -0
  74. package/dist/server/services/plan/watcher.js +69 -0
  75. package/dist/server/services/plan/watcher.js.map +1 -0
  76. package/dist/server/services/websocket/file-explorer-handlers.js +20 -0
  77. package/dist/server/services/websocket/file-explorer-handlers.js.map +1 -1
  78. package/dist/server/services/websocket/handler.d.ts +0 -1
  79. package/dist/server/services/websocket/handler.d.ts.map +1 -1
  80. package/dist/server/services/websocket/handler.js +28 -2
  81. package/dist/server/services/websocket/handler.js.map +1 -1
  82. package/dist/server/services/websocket/plan-handlers.d.ts +6 -0
  83. package/dist/server/services/websocket/plan-handlers.d.ts.map +1 -0
  84. package/dist/server/services/websocket/plan-handlers.js +494 -0
  85. package/dist/server/services/websocket/plan-handlers.js.map +1 -0
  86. package/dist/server/services/websocket/quality-handlers.d.ts +4 -0
  87. package/dist/server/services/websocket/quality-handlers.d.ts.map +1 -0
  88. package/dist/server/services/websocket/quality-handlers.js +470 -0
  89. package/dist/server/services/websocket/quality-handlers.js.map +1 -0
  90. package/dist/server/services/websocket/quality-persistence.d.ts +45 -0
  91. package/dist/server/services/websocket/quality-persistence.d.ts.map +1 -0
  92. package/dist/server/services/websocket/quality-persistence.js +187 -0
  93. package/dist/server/services/websocket/quality-persistence.js.map +1 -0
  94. package/dist/server/services/websocket/quality-service.d.ts +54 -0
  95. package/dist/server/services/websocket/quality-service.d.ts.map +1 -0
  96. package/dist/server/services/websocket/quality-service.js +816 -0
  97. package/dist/server/services/websocket/quality-service.js.map +1 -0
  98. package/dist/server/services/websocket/session-handlers.d.ts.map +1 -1
  99. package/dist/server/services/websocket/session-handlers.js +23 -0
  100. package/dist/server/services/websocket/session-handlers.js.map +1 -1
  101. package/dist/server/services/websocket/types.d.ts +2 -2
  102. package/dist/server/services/websocket/types.d.ts.map +1 -1
  103. package/package.json +3 -2
  104. package/server/cli/headless/claude-invoker.ts +21 -9
  105. package/server/cli/headless/headless-logger.ts +78 -0
  106. package/server/cli/headless/mcp-config.ts +6 -5
  107. package/server/cli/headless/runner.ts +4 -0
  108. package/server/cli/headless/stall-assessor.ts +101 -20
  109. package/server/cli/headless/tool-watchdog.ts +18 -9
  110. package/server/cli/headless/types.ts +10 -1
  111. package/server/cli/improvisation-session-manager.ts +118 -11
  112. package/server/index.ts +0 -4
  113. package/server/mcp/bouncer-cli.ts +73 -0
  114. package/server/mcp/bouncer-integration.ts +66 -44
  115. package/server/mcp/bouncer-sandbox.ts +214 -0
  116. package/server/mcp/security-patterns.ts +206 -10
  117. package/server/services/plan/composer.ts +199 -0
  118. package/server/services/plan/dependency-resolver.ts +179 -0
  119. package/server/services/plan/executor.ts +604 -0
  120. package/server/services/plan/parser.ts +459 -0
  121. package/server/services/plan/state-reconciler.ts +132 -0
  122. package/server/services/plan/types.ts +164 -0
  123. package/server/services/plan/watcher.ts +73 -0
  124. package/server/services/websocket/file-explorer-handlers.ts +20 -0
  125. package/server/services/websocket/handler.ts +28 -2
  126. package/server/services/websocket/plan-handlers.ts +592 -0
  127. package/server/services/websocket/quality-handlers.ts +570 -0
  128. package/server/services/websocket/quality-persistence.ts +250 -0
  129. package/server/services/websocket/quality-service.ts +975 -0
  130. package/server/services/websocket/session-handlers.ts +26 -0
  131. package/server/services/websocket/types.ts +62 -2
@@ -0,0 +1,164 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+
4
+ /**
5
+ * Plan Types — Project Plan Spec (PPS) data structures
6
+ *
7
+ * These types represent the parsed contents of .pm/ directory files.
8
+ */
9
+
10
+ // ============================================================================
11
+ // Project Config (project.md front matter)
12
+ // ============================================================================
13
+
14
+ export interface ProjectConfig {
15
+ name: string;
16
+ id: string;
17
+ created: string;
18
+ status: 'active' | 'paused' | 'completed' | 'archived';
19
+ estimation: 'fibonacci' | 'tshirt' | 'hours' | 'none';
20
+ idPrefixes: Record<string, string>;
21
+ workflows: WorkflowStatus[];
22
+ labels: string[];
23
+ teams: Team[];
24
+ }
25
+
26
+ export interface WorkflowStatus {
27
+ status: string;
28
+ category: 'unstarted' | 'started' | 'completed' | 'cancelled';
29
+ description: string;
30
+ }
31
+
32
+ export interface Team {
33
+ name: string;
34
+ description?: string;
35
+ }
36
+
37
+ // ============================================================================
38
+ // Project State (STATE.md front matter + body)
39
+ // ============================================================================
40
+
41
+ export interface ProjectState {
42
+ project: string;
43
+ currentSprint: string | null;
44
+ activeMilestone: string | null;
45
+ paused: boolean;
46
+ lastSession: string | null;
47
+ // Parsed from markdown body sections:
48
+ readyToWork: IssueSummary[];
49
+ inProgress: IssueSummary[];
50
+ blocked: IssueSummary[];
51
+ recentlyCompleted: IssueSummary[];
52
+ warnings: string[];
53
+ }
54
+
55
+ export interface IssueSummary {
56
+ id: string;
57
+ title: string;
58
+ path: string;
59
+ priority: string;
60
+ blockedBy?: string;
61
+ }
62
+
63
+ // ============================================================================
64
+ // Issue / Epic / Bug (backlog/*.md)
65
+ // ============================================================================
66
+
67
+ export interface Issue {
68
+ id: string;
69
+ title: string;
70
+ type: 'issue' | 'epic' | 'bug' | 'task';
71
+ status: string;
72
+ priority: string;
73
+ estimate: number | string | null;
74
+ labels: string[];
75
+ epic: string | null;
76
+ sprint: string | null;
77
+ milestone: string | null;
78
+ assigned: string | null;
79
+ created: string;
80
+ updated: string | null;
81
+ due: string | null;
82
+ blockedBy: string[];
83
+ blocks: string[];
84
+ relatesTo: string[];
85
+ // Body sections
86
+ description: string;
87
+ acceptanceCriteria: AcceptanceCriterion[];
88
+ technicalNotes: string | null;
89
+ filesToModify: string[];
90
+ activity: string[];
91
+ // Children (for epics)
92
+ children: string[];
93
+ // Progress (for epics)
94
+ progress: string | null;
95
+ // Full markdown body
96
+ body: string;
97
+ // File path relative to .pm/
98
+ path: string;
99
+ }
100
+
101
+ export interface AcceptanceCriterion {
102
+ text: string;
103
+ checked: boolean;
104
+ }
105
+
106
+ // ============================================================================
107
+ // Sprint (sprints/*.md)
108
+ // ============================================================================
109
+
110
+ export interface Sprint {
111
+ id: string;
112
+ title: string;
113
+ status: 'planned' | 'active' | 'completed';
114
+ start: string;
115
+ end: string;
116
+ goal: string;
117
+ capacity: number | null;
118
+ committed: number | null;
119
+ completed: number | null;
120
+ issues: SprintIssueSummary[];
121
+ path: string;
122
+ }
123
+
124
+ export interface SprintIssueSummary {
125
+ id: string;
126
+ title: string;
127
+ path: string;
128
+ points: number | string | null;
129
+ status: string;
130
+ }
131
+
132
+ // ============================================================================
133
+ // Milestone (milestones/*.md)
134
+ // ============================================================================
135
+
136
+ export interface Milestone {
137
+ id: string;
138
+ title: string;
139
+ status: 'planned' | 'in_progress' | 'completed' | 'missed';
140
+ targetDate: string | null;
141
+ progress: string | null;
142
+ definition: string;
143
+ epics: MilestoneEpicSummary[];
144
+ path: string;
145
+ }
146
+
147
+ export interface MilestoneEpicSummary {
148
+ id: string;
149
+ title: string;
150
+ path: string;
151
+ progress: string;
152
+ }
153
+
154
+ // ============================================================================
155
+ // Plan full state (sent on planInit)
156
+ // ============================================================================
157
+
158
+ export interface PlanFullState {
159
+ project: ProjectConfig;
160
+ state: ProjectState;
161
+ issues: Issue[];
162
+ sprints: Sprint[];
163
+ milestones: Milestone[];
164
+ }
@@ -0,0 +1,73 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+
4
+ /**
5
+ * Plan Watcher — Watches .pm/ (or legacy .plan/) directory for changes and broadcasts updates.
6
+ *
7
+ * Uses fs.watch with debouncing to batch rapid changes.
8
+ */
9
+
10
+ import { type FSWatcher, watch } from 'node:fs';
11
+ import type { HandlerContext } from '../websocket/handler-context.js';
12
+ import { parsePlanDirectory, resolvePmDir } from './parser.js';
13
+
14
+ export class PlanWatcher {
15
+ private watcher: FSWatcher | null = null;
16
+ private debounceTimer: ReturnType<typeof setTimeout> | null = null;
17
+ private readonly workingDir: string;
18
+ private readonly ctx: HandlerContext;
19
+ private started = false;
20
+
21
+ constructor(workingDir: string, ctx: HandlerContext) {
22
+ this.workingDir = workingDir;
23
+ this.ctx = ctx;
24
+ }
25
+
26
+ start(): void {
27
+ if (this.started) return;
28
+
29
+ const planDir = resolvePmDir(this.workingDir);
30
+ if (!planDir) return;
31
+
32
+ try {
33
+ this.watcher = watch(planDir, { recursive: true }, (_event, filename) => {
34
+ if (!filename || !filename.endsWith('.md')) return;
35
+ this.debounce();
36
+ });
37
+ this.started = true;
38
+ } catch {
39
+ // fs.watch recursive may not be supported on all platforms
40
+ }
41
+ }
42
+
43
+ stop(): void {
44
+ if (this.watcher) {
45
+ this.watcher.close();
46
+ this.watcher = null;
47
+ }
48
+ if (this.debounceTimer) {
49
+ clearTimeout(this.debounceTimer);
50
+ this.debounceTimer = null;
51
+ }
52
+ this.started = false;
53
+ }
54
+
55
+ private debounce(): void {
56
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
57
+ this.debounceTimer = setTimeout(() => {
58
+ this.handleChange();
59
+ }, 200);
60
+ }
61
+
62
+ private handleChange(): void {
63
+ try {
64
+ // Always do a full reparse — concurrent changes may affect multiple files
65
+ const fullState = parsePlanDirectory(this.workingDir);
66
+ if (fullState) {
67
+ this.ctx.broadcastToAll({ type: 'planStateUpdated', data: fullState });
68
+ }
69
+ } catch {
70
+ // Ignore parse errors from partial writes
71
+ }
72
+ }
73
+ }
@@ -542,6 +542,22 @@ function handleFindDefinition(ctx: HandlerContext, ws: WSContext, msg: WebSocket
542
542
  `(fn|struct|enum|trait|type|const|static|mod)\\s+${s}\\b`,
543
543
  `impl\\s+${s}\\b`,
544
544
  ],
545
+ swift: (s) => [
546
+ `(func|class|struct|enum|protocol|typealias|actor)\\s+${s}\\b`,
547
+ `(let|var)\\s+${s}\\b`,
548
+ `extension\\s+${s}\\b`,
549
+ ],
550
+ kotlin: (s) => [
551
+ `(fun|class|object|interface|typealias|enum\\s+class)\\s+${s}\\b`,
552
+ `(val|var)\\s+${s}\\b`,
553
+ ],
554
+ java: (s) => [
555
+ `(class|interface|enum)\\s+${s}\\b`,
556
+ `(public|private|protected|static)?\\s*(void|int|String|boolean|\\w+)\\s+${s}\\s*\\(`,
557
+ ],
558
+ ruby: (s) => [
559
+ `(def|class|module)\\s+${s}\\b`,
560
+ ],
545
561
  };
546
562
 
547
563
  const LANGUAGE_GLOBS: Record<string, string> = {
@@ -550,6 +566,10 @@ function handleFindDefinition(ctx: HandlerContext, ws: WSContext, msg: WebSocket
550
566
  python: '*.py',
551
567
  go: '*.go',
552
568
  rust: '*.rs',
569
+ swift: '*.swift',
570
+ kotlin: '*.{kt,kts}',
571
+ java: '*.java',
572
+ ruby: '*.rb',
553
573
  };
554
574
 
555
575
  const patterns = DEFINITION_PATTERNS[language] || DEFINITION_PATTERNS.typescript;
@@ -19,6 +19,8 @@ import { handleFileExplorerMessage, handleFileMessage } from './file-explorer-ha
19
19
  import { FileUploadHandler } from './file-upload-handler.js';
20
20
  import { handleGitMessage } from './git-handlers.js';
21
21
  import type { HandlerContext, UsageReporter } from './handler-context.js';
22
+ import { handlePlanMessage } from './plan-handlers.js';
23
+ import { handleQualityMessage } from './quality-handlers.js';
22
24
  import { handleHistoryMessage, handleSessionMessage, initializeTab, resumeHistoricalSession } from './session-handlers.js';
23
25
  import { SessionRegistry } from './session-registry.js';
24
26
  import { generateNotificationSummary, handleGetSettings, handleUpdateSettings } from './settings-handlers.js';
@@ -220,6 +222,32 @@ export class WebSocketImproviseHandler implements HandlerContext {
220
222
  return handleRemoveTab(this, ws, tabId, workingDir);
221
223
  case 'markTabViewed':
222
224
  return handleMarkTabViewed(this, ws, tabId, workingDir);
225
+ // Quality messages
226
+ case 'qualityDetectTools':
227
+ case 'qualityScan':
228
+ case 'qualityInstallTools':
229
+ case 'qualityCodeReview':
230
+ case 'qualityFixIssues':
231
+ case 'qualityLoadState':
232
+ case 'qualitySaveDirectories':
233
+ return handleQualityMessage(this, ws, msg, tabId, workingDir);
234
+ // Plan messages
235
+ case 'planInit':
236
+ case 'planGetState':
237
+ case 'planListIssues':
238
+ case 'planGetIssue':
239
+ case 'planGetSprint':
240
+ case 'planGetMilestone':
241
+ case 'planCreateIssue':
242
+ case 'planUpdateIssue':
243
+ case 'planDeleteIssue':
244
+ case 'planScaffold':
245
+ case 'planPrompt':
246
+ case 'planExecute':
247
+ case 'planPause':
248
+ case 'planStop':
249
+ case 'planResume':
250
+ return handlePlanMessage(this, ws, msg, tabId, workingDir, permission);
223
251
  // Settings messages
224
252
  case 'getSettings':
225
253
  return handleGetSettings(this, ws);
@@ -291,6 +319,4 @@ export class WebSocketImproviseHandler implements HandlerContext {
291
319
  this.sessions.delete(sessionId);
292
320
  }
293
321
 
294
- cleanupStaleSessions(): void {
295
- }
296
322
  }