@devo-bmad-custom/agent-orchestration 1.0.4 → 1.0.6

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 (86) hide show
  1. package/package.json +1 -1
  2. package/src/.agents/skills/tmux-commands/SKILL.md +353 -0
  3. package/src/bmm/data/project-context-template.md +26 -26
  4. package/src/bmm/teams/default-party.csv +20 -20
  5. package/src/bmm/workflows/2-plan-workflows/create-prd/data/domain-complexity.csv +14 -14
  6. package/src/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md +197 -197
  7. package/src/bmm/workflows/2-plan-workflows/create-prd/data/project-types.csv +10 -10
  8. package/src/bmm/workflows/2-plan-workflows/create-prd/templates/prd-template.md +10 -10
  9. package/src/bmm/workflows/3-solutioning/create-architecture/data/domain-complexity.csv +12 -12
  10. package/src/bmm/workflows/4-implementation/code-review/instructions.xml +226 -226
  11. package/src/bmm/workflows/4-implementation/correct-course/checklist.md +288 -288
  12. package/src/bmm/workflows/4-implementation/correct-course/instructions.md +207 -207
  13. package/src/bmm/workflows/4-implementation/retrospective/instructions.md +1444 -1444
  14. package/src/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +55 -55
  15. package/src/bmm/workflows/4-implementation/sprint-status/instructions.md +230 -230
  16. package/src/bmm/workflows/bmad-quick-flow/quick-spec/tech-spec-template.md +74 -74
  17. package/src/bmm/workflows/document-project/instructions.md +130 -130
  18. package/src/bmm/workflows/document-project/templates/project-scan-report-schema.json +160 -160
  19. package/src/bmm/workflows/document-project/workflows/deep-dive-instructions.md +298 -298
  20. package/src/bmm/workflows/document-project/workflows/deep-dive.yaml +31 -31
  21. package/src/bmm/workflows/document-project/workflows/full-scan-instructions.md +1106 -1106
  22. package/src/bmm/workflows/document-project/workflows/full-scan.yaml +31 -31
  23. package/src/bmm/workflows/qa-generate-e2e-tests/checklist.md +33 -33
  24. package/src/bmm/workflows/qa-generate-e2e-tests/instructions.md +110 -110
  25. package/src/core/agents/bmad-master.md +56 -56
  26. package/src/core/workflows/party-mode/steps/step-02-discussion-orchestration.md +187 -187
  27. package/src/core/workflows/party-mode/steps/step-03-graceful-exit.md +168 -168
  28. package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/SKILL.md +0 -475
  29. package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/references/vision-requests.md +0 -736
  30. package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/vision-framework/references/visionkit-scanner.md +0 -738
  31. package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/weatherkit/SKILL.md +0 -410
  32. package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/weatherkit/references/weatherkit-patterns.md +0 -567
  33. package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/widgetkit/SKILL.md +0 -497
  34. package/src/.agents/skills/ui-ux-pro-custom/data/swift-ios-skills/widgetkit/references/widgetkit-advanced.md +0 -871
  35. package/src/.agents/skills/ui-ux-pro-custom/data/typography.csv +0 -58
  36. package/src/.agents/skills/ui-ux-pro-custom/data/ui-reasoning.csv +0 -101
  37. package/src/.agents/skills/ui-ux-pro-custom/data/ux-guidelines.csv +0 -100
  38. package/src/.agents/skills/ui-ux-pro-custom/data/web-interface.csv +0 -31
  39. package/src/.agents/skills/ui-ux-pro-custom/scripts/core.py +0 -253
  40. package/src/.agents/skills/ui-ux-pro-custom/scripts/design_system.py +0 -1067
  41. package/src/.agents/skills/ui-ux-pro-custom/scripts/search.py +0 -114
  42. package/src/.agents/skills/ux-audit/SKILL.md +0 -151
  43. package/src/.agents/skills/websocket-engineer/SKILL.md +0 -168
  44. package/src/.agents/skills/websocket-engineer/references/alternatives.md +0 -391
  45. package/src/.agents/skills/websocket-engineer/references/patterns.md +0 -400
  46. package/src/.agents/skills/websocket-engineer/references/protocol.md +0 -195
  47. package/src/.agents/skills/websocket-engineer/references/scaling.md +0 -333
  48. package/src/.agents/skills/websocket-engineer/references/security.md +0 -474
  49. package/src/.agents/skills/writing-skills/SKILL.md +0 -655
  50. package/src/.agents/skills/writing-skills/anthropic-best-practices.md +0 -1150
  51. package/src/.agents/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +0 -189
  52. package/src/.agents/skills/writing-skills/graphviz-conventions.dot +0 -172
  53. package/src/.agents/skills/writing-skills/persuasion-principles.md +0 -187
  54. package/src/.agents/skills/writing-skills/render-graphs.js +0 -168
  55. package/src/.agents/skills/writing-skills/testing-skills-with-subagents.md +0 -384
  56. package/src/.claude/commands/bmad-track-compact.md +0 -19
  57. package/src/.claude/commands/bmad-track-extended.md +0 -19
  58. package/src/.claude/commands/bmad-track-large.md +0 -19
  59. package/src/.claude/commands/bmad-track-medium.md +0 -19
  60. package/src/.claude/commands/bmad-track-nano.md +0 -19
  61. package/src/.claude/commands/bmad-track-rv.md +0 -18
  62. package/src/.claude/commands/bmad-track-small.md +0 -19
  63. package/src/.claude/commands/master-orchestrator.md +0 -15
  64. package/src/_memory/master-orchestrator-sidecar/docs-index.md +0 -3
  65. package/src/_memory/master-orchestrator-sidecar/instructions.md +0 -2616
  66. package/src/_memory/master-orchestrator-sidecar/memories.md +0 -8
  67. package/src/_memory/master-orchestrator-sidecar/session-state.md +0 -15
  68. package/src/_memory/master-orchestrator-sidecar/triage-history.md +0 -3
  69. package/src/_memory/master-orchestrator-sidecar/workflows-overview.html +0 -1230
  70. package/src/core/agents/master-orchestrator.md +0 -54
  71. package/src/docs/dev/tmux/actions_popup.py +0 -291
  72. package/src/docs/dev/tmux/actions_popup.sh +0 -110
  73. package/src/docs/dev/tmux/claude_usage.sh +0 -15
  74. package/src/docs/dev/tmux/colors.conf +0 -26
  75. package/src/docs/dev/tmux/cpu_usage.sh +0 -7
  76. package/src/docs/dev/tmux/dispatch.sh +0 -10
  77. package/src/docs/dev/tmux/float_init.sh +0 -13
  78. package/src/docs/dev/tmux/float_term.sh +0 -23
  79. package/src/docs/dev/tmux/open_clip.sh +0 -14
  80. package/src/docs/dev/tmux/paste_clipboard.sh +0 -13
  81. package/src/docs/dev/tmux/paste_image_wrapper.sh +0 -94
  82. package/src/docs/dev/tmux/ram_usage.sh +0 -3
  83. package/src/docs/dev/tmux/title_sync.sh +0 -54
  84. package/src/docs/dev/tmux/tmux-setup.md +0 -867
  85. package/src/docs/dev/tmux/tmux.conf +0 -127
  86. package/src/docs/dev/tmux/xclip +0 -18
@@ -1,474 +0,0 @@
1
- # WebSocket Security Reference
2
-
3
- ## Authentication
4
-
5
- ### JWT Authentication
6
-
7
- ```javascript
8
- const io = require('socket.io')(3000);
9
- const jwt = require('jsonwebtoken');
10
-
11
- // Middleware for authentication
12
- io.use((socket, next) => {
13
- const token = socket.handshake.auth.token;
14
-
15
- if (!token) {
16
- return next(new Error('Authentication error: No token provided'));
17
- }
18
-
19
- try {
20
- const decoded = jwt.verify(token, process.env.JWT_SECRET);
21
- socket.userId = decoded.userId;
22
- socket.username = decoded.username;
23
- next();
24
- } catch (err) {
25
- next(new Error('Authentication error: Invalid token'));
26
- }
27
- });
28
-
29
- io.on('connection', (socket) => {
30
- console.log(`User ${socket.username} connected`);
31
-
32
- socket.on('message', (data) => {
33
- // socket.userId is already verified
34
- saveMessage(socket.userId, data);
35
- });
36
- });
37
- ```
38
-
39
- ### Query Parameter Authentication (Less Secure)
40
-
41
- ```javascript
42
- // Use only for initial handshake, then upgrade to token
43
- io.use((socket, next) => {
44
- const token = socket.handshake.query.token;
45
-
46
- if (!token) {
47
- return next(new Error('Authentication required'));
48
- }
49
-
50
- jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
51
- if (err) return next(new Error('Invalid token'));
52
- socket.userId = decoded.userId;
53
- next();
54
- });
55
- });
56
- ```
57
-
58
- ### Cookie Authentication
59
-
60
- ```javascript
61
- const cookieParser = require('cookie-parser');
62
-
63
- io.use((socket, next) => {
64
- const cookies = socket.handshake.headers.cookie;
65
-
66
- if (!cookies) {
67
- return next(new Error('No cookies'));
68
- }
69
-
70
- // Parse cookies
71
- cookieParser(process.env.COOKIE_SECRET)(
72
- socket.request,
73
- {},
74
- () => {
75
- const sessionId = socket.request.signedCookies.sessionId;
76
-
77
- if (!sessionId) {
78
- return next(new Error('No session'));
79
- }
80
-
81
- // Verify session in Redis/DB
82
- verifySession(sessionId).then(user => {
83
- socket.userId = user.id;
84
- next();
85
- }).catch(err => {
86
- next(new Error('Invalid session'));
87
- });
88
- }
89
- );
90
- });
91
- ```
92
-
93
- ## Authorization
94
-
95
- ### Room-Based Authorization
96
-
97
- ```javascript
98
- io.on('connection', (socket) => {
99
- socket.on('join-room', async (roomId) => {
100
- // Check if user has permission
101
- const hasAccess = await checkRoomAccess(socket.userId, roomId);
102
-
103
- if (!hasAccess) {
104
- socket.emit('error', { message: 'Access denied to room' });
105
- return;
106
- }
107
-
108
- socket.join(roomId);
109
- socket.emit('joined', { room: roomId });
110
- });
111
-
112
- socket.on('send-message', async ({ roomId, text }) => {
113
- // Verify user is in room
114
- if (!socket.rooms.has(roomId)) {
115
- socket.emit('error', { message: 'Not in room' });
116
- return;
117
- }
118
-
119
- // Check write permissions
120
- const canWrite = await checkWritePermission(socket.userId, roomId);
121
-
122
- if (!canWrite) {
123
- socket.emit('error', { message: 'No write permission' });
124
- return;
125
- }
126
-
127
- io.to(roomId).emit('message', {
128
- userId: socket.userId,
129
- text,
130
- timestamp: Date.now()
131
- });
132
- });
133
- });
134
- ```
135
-
136
- ### Admin-Only Events
137
-
138
- ```javascript
139
- const ADMIN_EVENTS = ['kick-user', 'ban-user', 'delete-message'];
140
-
141
- io.use((socket, next) => {
142
- // Attach role to socket after auth
143
- getUserRole(socket.userId).then(role => {
144
- socket.role = role;
145
- next();
146
- });
147
- });
148
-
149
- io.on('connection', (socket) => {
150
- ADMIN_EVENTS.forEach(event => {
151
- socket.on(event, async (data) => {
152
- if (socket.role !== 'admin') {
153
- socket.emit('error', { message: 'Admin access required' });
154
- return;
155
- }
156
-
157
- // Execute admin action
158
- await handleAdminAction(event, data);
159
- });
160
- });
161
- });
162
- ```
163
-
164
- ## Rate Limiting
165
-
166
- ### Per-Socket Rate Limiting
167
-
168
- ```javascript
169
- const rateLimit = require('express-rate-limit');
170
-
171
- class SocketRateLimiter {
172
- constructor(maxRequests = 100, windowMs = 60000) {
173
- this.maxRequests = maxRequests;
174
- this.windowMs = windowMs;
175
- this.requests = new Map();
176
- }
177
-
178
- check(socketId) {
179
- const now = Date.now();
180
- const userRequests = this.requests.get(socketId) || [];
181
-
182
- // Remove expired requests
183
- const validRequests = userRequests.filter(
184
- time => now - time < this.windowMs
185
- );
186
-
187
- if (validRequests.length >= this.maxRequests) {
188
- return false; // Rate limit exceeded
189
- }
190
-
191
- validRequests.push(now);
192
- this.requests.set(socketId, validRequests);
193
- return true;
194
- }
195
-
196
- reset(socketId) {
197
- this.requests.delete(socketId);
198
- }
199
- }
200
-
201
- const limiter = new SocketRateLimiter(100, 60000); // 100 req/min
202
-
203
- io.on('connection', (socket) => {
204
- socket.on('message', (data) => {
205
- if (!limiter.check(socket.id)) {
206
- socket.emit('error', { message: 'Rate limit exceeded' });
207
- return;
208
- }
209
-
210
- // Process message
211
- io.to(data.roomId).emit('message', data);
212
- });
213
-
214
- socket.on('disconnect', () => {
215
- limiter.reset(socket.id);
216
- });
217
- });
218
- ```
219
-
220
- ### Redis-Based Distributed Rate Limiting
221
-
222
- ```javascript
223
- const Redis = require('ioredis');
224
- const redis = new Redis();
225
-
226
- async function checkRateLimit(userId, maxRequests = 100, windowSec = 60) {
227
- const key = `rate_limit:${userId}`;
228
- const now = Date.now();
229
- const windowStart = now - (windowSec * 1000);
230
-
231
- const pipeline = redis.pipeline();
232
-
233
- // Remove old entries
234
- pipeline.zremrangebyscore(key, 0, windowStart);
235
-
236
- // Count requests in window
237
- pipeline.zcard(key);
238
-
239
- // Add current request
240
- pipeline.zadd(key, now, `${now}-${Math.random()}`);
241
-
242
- // Set expiry
243
- pipeline.expire(key, windowSec);
244
-
245
- const results = await pipeline.exec();
246
- const count = results[1][1];
247
-
248
- return count < maxRequests;
249
- }
250
-
251
- io.on('connection', (socket) => {
252
- socket.on('message', async (data) => {
253
- const allowed = await checkRateLimit(socket.userId, 50, 60);
254
-
255
- if (!allowed) {
256
- socket.emit('error', { message: 'Too many requests' });
257
- return;
258
- }
259
-
260
- io.to(data.roomId).emit('message', data);
261
- });
262
- });
263
- ```
264
-
265
- ## CORS Configuration
266
-
267
- ```javascript
268
- const io = require('socket.io')(3000, {
269
- cors: {
270
- origin: ['https://example.com', 'https://app.example.com'],
271
- methods: ['GET', 'POST'],
272
- credentials: true,
273
- allowedHeaders: ['Authorization']
274
- }
275
- });
276
-
277
- // Dynamic CORS
278
- io.engine.on('initial_headers', (headers, req) => {
279
- headers['Access-Control-Allow-Origin'] = req.headers.origin;
280
- });
281
- ```
282
-
283
- ## Input Validation
284
-
285
- ```javascript
286
- const Joi = require('joi');
287
-
288
- const messageSchema = Joi.object({
289
- roomId: Joi.string().uuid().required(),
290
- text: Joi.string().min(1).max(1000).required(),
291
- attachments: Joi.array().items(Joi.string().uri()).max(5).optional()
292
- });
293
-
294
- io.on('connection', (socket) => {
295
- socket.on('message', (data) => {
296
- // Validate input
297
- const { error, value } = messageSchema.validate(data);
298
-
299
- if (error) {
300
- socket.emit('error', {
301
- message: 'Invalid message format',
302
- details: error.details
303
- });
304
- return;
305
- }
306
-
307
- // Process validated data
308
- io.to(value.roomId).emit('message', {
309
- userId: socket.userId,
310
- ...value,
311
- timestamp: Date.now()
312
- });
313
- });
314
- });
315
- ```
316
-
317
- ## XSS Protection
318
-
319
- ```javascript
320
- const sanitizeHtml = require('sanitize-html');
321
-
322
- function sanitizeMessage(text) {
323
- return sanitizeHtml(text, {
324
- allowedTags: [], // Strip all HTML
325
- allowedAttributes: {},
326
- disallowedTagsMode: 'escape'
327
- });
328
- }
329
-
330
- io.on('connection', (socket) => {
331
- socket.on('message', (data) => {
332
- const sanitized = {
333
- ...data,
334
- text: sanitizeMessage(data.text)
335
- };
336
-
337
- io.to(data.roomId).emit('message', sanitized);
338
- });
339
- });
340
- ```
341
-
342
- ## DDoS Protection
343
-
344
- ### Connection Limiting
345
-
346
- ```javascript
347
- const connectionLimits = new Map();
348
- const MAX_CONNECTIONS_PER_IP = 10;
349
-
350
- io.engine.on('connection', (rawSocket) => {
351
- const ip = rawSocket.request.headers['x-forwarded-for'] ||
352
- rawSocket.request.connection.remoteAddress;
353
-
354
- const currentConnections = connectionLimits.get(ip) || 0;
355
-
356
- if (currentConnections >= MAX_CONNECTIONS_PER_IP) {
357
- rawSocket.close(1008, 'Too many connections from IP');
358
- return;
359
- }
360
-
361
- connectionLimits.set(ip, currentConnections + 1);
362
-
363
- rawSocket.on('close', () => {
364
- const count = connectionLimits.get(ip) - 1;
365
- if (count <= 0) {
366
- connectionLimits.delete(ip);
367
- } else {
368
- connectionLimits.set(ip, count);
369
- }
370
- });
371
- });
372
- ```
373
-
374
- ### Message Size Limits
375
-
376
- ```javascript
377
- const io = require('socket.io')(3000, {
378
- maxHttpBufferSize: 1e6, // 1MB max message size
379
- pingTimeout: 60000,
380
- pingInterval: 25000
381
- });
382
-
383
- io.on('connection', (socket) => {
384
- socket.on('message', (data) => {
385
- if (JSON.stringify(data).length > 10000) {
386
- socket.emit('error', { message: 'Message too large' });
387
- return;
388
- }
389
-
390
- // Process message
391
- });
392
- });
393
- ```
394
-
395
- ## Secure Session Management
396
-
397
- ```javascript
398
- const sessions = new Map();
399
-
400
- io.on('connection', (socket) => {
401
- const sessionId = generateSecureSessionId();
402
-
403
- sessions.set(socket.id, {
404
- sessionId,
405
- userId: socket.userId,
406
- createdAt: Date.now(),
407
- lastActivity: Date.now()
408
- });
409
-
410
- // Timeout inactive sessions
411
- const timeout = setTimeout(() => {
412
- socket.disconnect(true);
413
- }, 30 * 60 * 1000); // 30 minutes
414
-
415
- socket.on('message', () => {
416
- const session = sessions.get(socket.id);
417
- if (session) {
418
- session.lastActivity = Date.now();
419
- clearTimeout(timeout);
420
- }
421
- });
422
-
423
- socket.on('disconnect', () => {
424
- sessions.delete(socket.id);
425
- clearTimeout(timeout);
426
- });
427
- });
428
-
429
- function generateSecureSessionId() {
430
- return require('crypto').randomBytes(32).toString('hex');
431
- }
432
- ```
433
-
434
- ## Audit Logging
435
-
436
- ```javascript
437
- const winston = require('winston');
438
-
439
- const logger = winston.createLogger({
440
- level: 'info',
441
- format: winston.format.json(),
442
- transports: [
443
- new winston.transports.File({ filename: 'websocket-audit.log' })
444
- ]
445
- });
446
-
447
- io.on('connection', (socket) => {
448
- logger.info('Connection', {
449
- socketId: socket.id,
450
- userId: socket.userId,
451
- ip: socket.handshake.address,
452
- timestamp: Date.now()
453
- });
454
-
455
- socket.on('message', (data) => {
456
- logger.info('Message', {
457
- socketId: socket.id,
458
- userId: socket.userId,
459
- roomId: data.roomId,
460
- messageLength: data.text.length,
461
- timestamp: Date.now()
462
- });
463
- });
464
-
465
- socket.on('disconnect', (reason) => {
466
- logger.info('Disconnect', {
467
- socketId: socket.id,
468
- userId: socket.userId,
469
- reason,
470
- timestamp: Date.now()
471
- });
472
- });
473
- });
474
- ```