aios-core 3.7.0 → 3.9.1
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.
- package/.aios-core/core/session/context-detector.js +3 -0
- package/.aios-core/core/session/context-loader.js +154 -0
- package/.aios-core/data/learned-patterns.yaml +3 -0
- package/.aios-core/data/workflow-patterns.yaml +347 -3
- package/.aios-core/development/agents/dev.md +6 -0
- package/.aios-core/development/agents/squad-creator.md +30 -0
- package/.aios-core/development/scripts/squad/squad-analyzer.js +638 -0
- package/.aios-core/development/scripts/squad/squad-extender.js +871 -0
- package/.aios-core/development/scripts/squad/squad-generator.js +107 -19
- package/.aios-core/development/scripts/squad/squad-migrator.js +3 -5
- package/.aios-core/development/scripts/squad/squad-validator.js +98 -0
- package/.aios-core/development/tasks/next.md +294 -0
- package/.aios-core/development/tasks/patterns.md +334 -0
- package/.aios-core/development/tasks/squad-creator-analyze.md +315 -0
- package/.aios-core/development/tasks/squad-creator-create.md +26 -3
- package/.aios-core/development/tasks/squad-creator-extend.md +411 -0
- package/.aios-core/development/tasks/squad-creator-validate.md +9 -1
- package/.aios-core/development/tasks/waves.md +205 -0
- package/.aios-core/development/templates/squad/agent-template.md +69 -0
- package/.aios-core/development/templates/squad/checklist-template.md +82 -0
- package/.aios-core/development/templates/squad/data-template.yaml +105 -0
- package/.aios-core/development/templates/squad/script-template.js +179 -0
- package/.aios-core/development/templates/squad/task-template.md +125 -0
- package/.aios-core/development/templates/squad/template-template.md +97 -0
- package/.aios-core/development/templates/squad/tool-template.js +103 -0
- package/.aios-core/development/templates/squad/workflow-template.yaml +108 -0
- package/.aios-core/infrastructure/scripts/test-generator.js +8 -8
- package/.aios-core/infrastructure/scripts/test-quality-assessment.js +5 -5
- package/.aios-core/infrastructure/scripts/test-utilities.js +3 -3
- package/.aios-core/install-manifest.yaml +97 -33
- package/.aios-core/quality/metrics-collector.js +27 -0
- package/.aios-core/scripts/session-context-loader.js +13 -254
- package/.aios-core/scripts/test-template-system.js +6 -6
- package/.aios-core/utils/aios-validator.js +25 -0
- package/.aios-core/workflow-intelligence/__tests__/confidence-scorer.test.js +334 -0
- package/.aios-core/workflow-intelligence/__tests__/integration.test.js +337 -0
- package/.aios-core/workflow-intelligence/__tests__/suggestion-engine.test.js +431 -0
- package/.aios-core/workflow-intelligence/__tests__/wave-analyzer.test.js +458 -0
- package/.aios-core/workflow-intelligence/__tests__/workflow-registry.test.js +302 -0
- package/.aios-core/workflow-intelligence/engine/confidence-scorer.js +305 -0
- package/.aios-core/workflow-intelligence/engine/output-formatter.js +285 -0
- package/.aios-core/workflow-intelligence/engine/suggestion-engine.js +603 -0
- package/.aios-core/workflow-intelligence/engine/wave-analyzer.js +676 -0
- package/.aios-core/workflow-intelligence/index.js +327 -0
- package/.aios-core/workflow-intelligence/learning/capture-hook.js +147 -0
- package/.aios-core/workflow-intelligence/learning/index.js +230 -0
- package/.aios-core/workflow-intelligence/learning/pattern-capture.js +340 -0
- package/.aios-core/workflow-intelligence/learning/pattern-store.js +498 -0
- package/.aios-core/workflow-intelligence/learning/pattern-validator.js +309 -0
- package/.aios-core/workflow-intelligence/registry/workflow-registry.js +358 -0
- package/package.json +1 -1
- package/src/installer/brownfield-upgrader.js +1 -1
- package/bin/aios-init.backup-v1.1.4.js +0 -352
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module PatternCapture
|
|
3
|
+
* @description Captures workflow patterns from user sessions
|
|
4
|
+
* @story WIS-5 - Pattern Capture (Internal)
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const crypto = require('crypto');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Default minimum sequence length for pattern capture
|
|
14
|
+
* @type {number}
|
|
15
|
+
*/
|
|
16
|
+
const DEFAULT_MIN_SEQUENCE_LENGTH = 3;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Key workflow commands that trigger pattern capture
|
|
20
|
+
* @type {string[]}
|
|
21
|
+
*/
|
|
22
|
+
const KEY_WORKFLOW_COMMANDS = [
|
|
23
|
+
'develop',
|
|
24
|
+
'review-qa',
|
|
25
|
+
'apply-qa-fixes',
|
|
26
|
+
'validate-story-draft',
|
|
27
|
+
'create-story',
|
|
28
|
+
'create-next-story',
|
|
29
|
+
'run-tests',
|
|
30
|
+
'create-pr'
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* PatternCapture class for capturing workflow patterns from sessions
|
|
35
|
+
*/
|
|
36
|
+
class PatternCapture {
|
|
37
|
+
/**
|
|
38
|
+
* Create a PatternCapture instance
|
|
39
|
+
* @param {Object} options - Configuration options
|
|
40
|
+
* @param {number} options.minSequenceLength - Minimum sequence length (default: 3)
|
|
41
|
+
* @param {string[]} options.keyCommands - Commands that trigger capture
|
|
42
|
+
* @param {boolean} options.enabled - Whether capture is enabled
|
|
43
|
+
*/
|
|
44
|
+
constructor(options = {}) {
|
|
45
|
+
this.minSequenceLength = options.minSequenceLength || DEFAULT_MIN_SEQUENCE_LENGTH;
|
|
46
|
+
this.keyCommands = options.keyCommands || KEY_WORKFLOW_COMMANDS;
|
|
47
|
+
this.enabled = options.enabled !== false && process.env.AIOS_PATTERN_CAPTURE !== 'false';
|
|
48
|
+
this.sessionBuffer = new Map(); // Track ongoing sessions
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Capture a completed session as a pattern
|
|
53
|
+
* @param {Object} sessionData - Session data to capture
|
|
54
|
+
* @param {string[]} sessionData.agentSequence - Sequence of agents used
|
|
55
|
+
* @param {string[]} sessionData.commands - Sequence of commands executed
|
|
56
|
+
* @param {boolean} sessionData.success - Whether workflow completed successfully
|
|
57
|
+
* @param {number} sessionData.timestamp - Session timestamp
|
|
58
|
+
* @param {string} sessionData.sessionId - Unique session identifier
|
|
59
|
+
* @returns {Object} Captured pattern with validity info
|
|
60
|
+
*/
|
|
61
|
+
captureSession(sessionData) {
|
|
62
|
+
if (!this.enabled) {
|
|
63
|
+
return { valid: false, reason: 'Pattern capture disabled' };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!sessionData || !sessionData.commands) {
|
|
67
|
+
return { valid: false, reason: 'Invalid session data' };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Only capture successful workflows
|
|
71
|
+
if (!sessionData.success) {
|
|
72
|
+
return { valid: false, reason: 'Workflow not successful' };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Check minimum sequence length
|
|
76
|
+
if (sessionData.commands.length < this.minSequenceLength) {
|
|
77
|
+
return {
|
|
78
|
+
valid: false,
|
|
79
|
+
reason: `Sequence too short (${sessionData.commands.length} < ${this.minSequenceLength})`
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Extract normalized command sequence
|
|
84
|
+
const sequence = this._normalizeCommands(sessionData.commands);
|
|
85
|
+
const agents = this._normalizeAgents(sessionData.agentSequence || []);
|
|
86
|
+
|
|
87
|
+
// Build pattern object
|
|
88
|
+
const pattern = {
|
|
89
|
+
id: crypto.randomUUID(),
|
|
90
|
+
sequence: sequence,
|
|
91
|
+
agents: agents,
|
|
92
|
+
occurrences: 1,
|
|
93
|
+
successRate: 1.0,
|
|
94
|
+
firstSeen: new Date(sessionData.timestamp || Date.now()).toISOString(),
|
|
95
|
+
lastSeen: new Date(sessionData.timestamp || Date.now()).toISOString(),
|
|
96
|
+
sessionId: sessionData.sessionId || crypto.randomUUID(),
|
|
97
|
+
workflow: this._detectWorkflow(sequence),
|
|
98
|
+
status: 'pending'
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
valid: true,
|
|
103
|
+
pattern: pattern,
|
|
104
|
+
sequence: sequence
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Extract pattern candidates from command history
|
|
110
|
+
* @param {string[]} commandHistory - Full command history
|
|
111
|
+
* @returns {Object[]} Array of pattern candidates
|
|
112
|
+
*/
|
|
113
|
+
extractPatterns(commandHistory) {
|
|
114
|
+
if (!commandHistory || commandHistory.length < this.minSequenceLength) {
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const patterns = [];
|
|
119
|
+
const normalized = this._normalizeCommands(commandHistory);
|
|
120
|
+
|
|
121
|
+
// Use sliding window to find subsequences
|
|
122
|
+
for (let length = this.minSequenceLength; length <= Math.min(normalized.length, 7); length++) {
|
|
123
|
+
for (let i = 0; i <= normalized.length - length; i++) {
|
|
124
|
+
const subsequence = normalized.slice(i, i + length);
|
|
125
|
+
|
|
126
|
+
// Only include if it contains at least one key command
|
|
127
|
+
if (this._containsKeyCommand(subsequence)) {
|
|
128
|
+
patterns.push({
|
|
129
|
+
sequence: subsequence,
|
|
130
|
+
startIndex: i,
|
|
131
|
+
length: length
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return patterns;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get the minimum sequence length setting
|
|
142
|
+
* @returns {number} Minimum sequence length
|
|
143
|
+
*/
|
|
144
|
+
getMinimumSequenceLength() {
|
|
145
|
+
return this.minSequenceLength;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Handle task completion event
|
|
150
|
+
* @param {string} taskName - Name of completed task
|
|
151
|
+
* @param {Object} context - Task context
|
|
152
|
+
* @returns {Promise<Object>} Capture result
|
|
153
|
+
*/
|
|
154
|
+
async onTaskComplete(taskName, context) {
|
|
155
|
+
if (!this.enabled) {
|
|
156
|
+
return { captured: false, reason: 'disabled' };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const sessionId = context.sessionId || 'default';
|
|
160
|
+
|
|
161
|
+
// Get or create session buffer
|
|
162
|
+
if (!this.sessionBuffer.has(sessionId)) {
|
|
163
|
+
this.sessionBuffer.set(sessionId, {
|
|
164
|
+
commands: [],
|
|
165
|
+
agents: [],
|
|
166
|
+
startTime: Date.now(),
|
|
167
|
+
success: true
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const session = this.sessionBuffer.get(sessionId);
|
|
172
|
+
|
|
173
|
+
// Add command to buffer
|
|
174
|
+
const normalizedTask = this._normalizeCommand(taskName);
|
|
175
|
+
session.commands.push(normalizedTask);
|
|
176
|
+
|
|
177
|
+
// Track agent if provided
|
|
178
|
+
if (context.agentId) {
|
|
179
|
+
const normalizedAgent = context.agentId.replace('@', '');
|
|
180
|
+
if (!session.agents.includes(normalizedAgent)) {
|
|
181
|
+
session.agents.push(normalizedAgent);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Check if this is a workflow-ending command
|
|
186
|
+
if (this._isWorkflowEnd(normalizedTask)) {
|
|
187
|
+
const result = this.captureSession({
|
|
188
|
+
commands: session.commands,
|
|
189
|
+
agentSequence: session.agents,
|
|
190
|
+
success: session.success,
|
|
191
|
+
timestamp: Date.now(),
|
|
192
|
+
sessionId: sessionId
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// Clear session buffer
|
|
196
|
+
this.sessionBuffer.delete(sessionId);
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
captured: result.valid,
|
|
200
|
+
pattern: result.pattern,
|
|
201
|
+
reason: result.reason
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return { captured: false, reason: 'workflow_in_progress' };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Mark current session as failed
|
|
210
|
+
* @param {string} sessionId - Session identifier
|
|
211
|
+
*/
|
|
212
|
+
markSessionFailed(sessionId) {
|
|
213
|
+
const session = this.sessionBuffer.get(sessionId || 'default');
|
|
214
|
+
if (session) {
|
|
215
|
+
session.success = false;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Clear session buffer
|
|
221
|
+
* @param {string} sessionId - Session identifier (optional, clears all if not provided)
|
|
222
|
+
*/
|
|
223
|
+
clearSession(sessionId) {
|
|
224
|
+
if (sessionId) {
|
|
225
|
+
this.sessionBuffer.delete(sessionId);
|
|
226
|
+
} else {
|
|
227
|
+
this.sessionBuffer.clear();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Normalize command name
|
|
233
|
+
* @param {string} command - Command to normalize
|
|
234
|
+
* @returns {string} Normalized command
|
|
235
|
+
* @private
|
|
236
|
+
*/
|
|
237
|
+
_normalizeCommand(command) {
|
|
238
|
+
if (!command) return '';
|
|
239
|
+
return command
|
|
240
|
+
.replace(/^\*/, '') // Remove * prefix
|
|
241
|
+
.replace(/-/g, '-') // Keep hyphens
|
|
242
|
+
.toLowerCase()
|
|
243
|
+
.trim();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Normalize array of commands
|
|
248
|
+
* @param {string[]} commands - Commands to normalize
|
|
249
|
+
* @returns {string[]} Normalized commands
|
|
250
|
+
* @private
|
|
251
|
+
*/
|
|
252
|
+
_normalizeCommands(commands) {
|
|
253
|
+
return commands
|
|
254
|
+
.map(cmd => this._normalizeCommand(cmd))
|
|
255
|
+
.filter(cmd => cmd.length > 0);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Normalize array of agent IDs
|
|
260
|
+
* @param {string[]} agents - Agent IDs to normalize
|
|
261
|
+
* @returns {string[]} Normalized agent IDs
|
|
262
|
+
* @private
|
|
263
|
+
*/
|
|
264
|
+
_normalizeAgents(agents) {
|
|
265
|
+
return agents
|
|
266
|
+
.map(agent => agent.replace('@', '').toLowerCase().trim())
|
|
267
|
+
.filter(agent => agent.length > 0);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Check if sequence contains at least one key workflow command
|
|
272
|
+
* @param {string[]} sequence - Command sequence
|
|
273
|
+
* @returns {boolean} True if contains key command
|
|
274
|
+
* @private
|
|
275
|
+
*/
|
|
276
|
+
_containsKeyCommand(sequence) {
|
|
277
|
+
return sequence.some(cmd =>
|
|
278
|
+
this.keyCommands.some(key => cmd.includes(key))
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Detect workflow type from command sequence
|
|
284
|
+
* @param {string[]} sequence - Command sequence
|
|
285
|
+
* @returns {string|null} Detected workflow name or null
|
|
286
|
+
* @private
|
|
287
|
+
*/
|
|
288
|
+
_detectWorkflow(sequence) {
|
|
289
|
+
const joined = sequence.join(' ');
|
|
290
|
+
|
|
291
|
+
if (joined.includes('develop') && (joined.includes('review-qa') || joined.includes('qa'))) {
|
|
292
|
+
return 'story_development';
|
|
293
|
+
}
|
|
294
|
+
if (joined.includes('create-story') || joined.includes('validate-story')) {
|
|
295
|
+
return 'story_creation';
|
|
296
|
+
}
|
|
297
|
+
if (joined.includes('create-epic')) {
|
|
298
|
+
return 'epic_creation';
|
|
299
|
+
}
|
|
300
|
+
if (joined.includes('create-pr') || joined.includes('push')) {
|
|
301
|
+
return 'deployment';
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Check if command indicates end of workflow
|
|
309
|
+
* @param {string} command - Command to check
|
|
310
|
+
* @returns {boolean} True if workflow-ending command
|
|
311
|
+
* @private
|
|
312
|
+
*/
|
|
313
|
+
_isWorkflowEnd(command) {
|
|
314
|
+
const endCommands = [
|
|
315
|
+
'create-pr',
|
|
316
|
+
'push',
|
|
317
|
+
'deploy',
|
|
318
|
+
'complete',
|
|
319
|
+
'done',
|
|
320
|
+
'finish'
|
|
321
|
+
];
|
|
322
|
+
return endCommands.some(end => command.includes(end));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Create a new PatternCapture instance
|
|
328
|
+
* @param {Object} options - Configuration options
|
|
329
|
+
* @returns {PatternCapture} New instance
|
|
330
|
+
*/
|
|
331
|
+
function createPatternCapture(options = {}) {
|
|
332
|
+
return new PatternCapture(options);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
module.exports = {
|
|
336
|
+
PatternCapture,
|
|
337
|
+
createPatternCapture,
|
|
338
|
+
DEFAULT_MIN_SEQUENCE_LENGTH,
|
|
339
|
+
KEY_WORKFLOW_COMMANDS
|
|
340
|
+
};
|