agileflow 2.95.2 → 2.96.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.
- package/CHANGELOG.md +10 -0
- package/README.md +6 -6
- package/lib/api-routes.js +605 -0
- package/lib/api-server.js +260 -0
- package/lib/claude-cli-bridge.js +221 -0
- package/lib/dashboard-protocol.js +541 -0
- package/lib/dashboard-server.js +1601 -0
- package/lib/drivers/claude-driver.ts +310 -0
- package/lib/drivers/codex-driver.ts +454 -0
- package/lib/drivers/driver-manager.ts +158 -0
- package/lib/drivers/gemini-driver.ts +485 -0
- package/lib/drivers/index.ts +17 -0
- package/lib/flag-detection.js +350 -0
- package/lib/git-operations.js +267 -0
- package/lib/lock-file.js +144 -0
- package/lib/merge-operations.js +959 -0
- package/lib/protocol/driver.ts +360 -0
- package/lib/protocol/index.ts +12 -0
- package/lib/protocol/ir.ts +271 -0
- package/lib/session-display.js +330 -0
- package/lib/worktree-operations.js +221 -0
- package/package.json +2 -2
- package/scripts/agileflow-welcome.js +272 -24
- package/scripts/api-server-runner.js +177 -0
- package/scripts/archive-completed-stories.sh +22 -0
- package/scripts/automation-run-due.js +126 -0
- package/scripts/backfill-ideation-status.js +124 -0
- package/scripts/claude-tmux.sh +62 -1
- package/scripts/context-loader.js +292 -0
- package/scripts/dashboard-serve.js +323 -0
- package/scripts/lib/automation-registry.js +544 -0
- package/scripts/lib/automation-runner.js +476 -0
- package/scripts/lib/concurrency-limiter.js +513 -0
- package/scripts/lib/configure-features.js +46 -0
- package/scripts/lib/context-formatter.js +61 -0
- package/scripts/lib/damage-control-utils.js +29 -4
- package/scripts/lib/hook-metrics.js +324 -0
- package/scripts/lib/ideation-index.js +1196 -0
- package/scripts/lib/process-cleanup.js +359 -0
- package/scripts/lib/quality-gates.js +574 -0
- package/scripts/lib/status-task-bridge.js +522 -0
- package/scripts/lib/sync-ideation-status.js +292 -0
- package/scripts/lib/task-registry-cache.js +490 -0
- package/scripts/lib/task-registry.js +1181 -0
- package/scripts/migrate-ideation-index.js +515 -0
- package/scripts/precompact-context.sh +104 -0
- package/scripts/ralph-loop.js +2 -2
- package/scripts/session-manager.js +363 -2770
- package/scripts/spawn-parallel.js +45 -9
- package/src/core/agents/api-validator.md +180 -0
- package/src/core/agents/api.md +2 -0
- package/src/core/agents/code-reviewer.md +289 -0
- package/src/core/agents/configuration/damage-control.md +17 -0
- package/src/core/agents/database.md +2 -0
- package/src/core/agents/error-analyzer.md +203 -0
- package/src/core/agents/logic-analyzer-edge.md +171 -0
- package/src/core/agents/logic-analyzer-flow.md +254 -0
- package/src/core/agents/logic-analyzer-invariant.md +207 -0
- package/src/core/agents/logic-analyzer-race.md +267 -0
- package/src/core/agents/logic-analyzer-type.md +218 -0
- package/src/core/agents/logic-consensus.md +256 -0
- package/src/core/agents/orchestrator.md +89 -1
- package/src/core/agents/schema-validator.md +451 -0
- package/src/core/agents/team-coordinator.md +328 -0
- package/src/core/agents/ui-validator.md +328 -0
- package/src/core/agents/ui.md +2 -0
- package/src/core/commands/api.md +267 -0
- package/src/core/commands/automate.md +415 -0
- package/src/core/commands/babysit.md +290 -9
- package/src/core/commands/ideate/history.md +403 -0
- package/src/core/commands/{ideate.md → ideate/new.md} +244 -34
- package/src/core/commands/logic/audit.md +368 -0
- package/src/core/commands/roadmap/analyze.md +1 -1
- package/src/core/experts/documentation/expertise.yaml +29 -2
- package/src/core/templates/CONTEXT.md.example +49 -0
- package/src/core/templates/claude-settings.advanced.example.json +4 -0
- package/tools/cli/commands/serve.js +456 -0
- package/tools/cli/installers/core/installer.js +7 -2
- package/tools/cli/installers/ide/claude-code.js +85 -0
- package/tools/cli/lib/content-injector.js +27 -1
- package/tools/cli/lib/ui.js +26 -57
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Driver
|
|
3
|
+
*
|
|
4
|
+
* Driver implementation for Claude Code CLI (Anthropic).
|
|
5
|
+
* Translates Claude's native protocol to the unified IR format.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
Driver,
|
|
10
|
+
DriverConfig,
|
|
11
|
+
DriverStatus,
|
|
12
|
+
Capability,
|
|
13
|
+
CapabilityName,
|
|
14
|
+
CLICommand,
|
|
15
|
+
IREventHandler,
|
|
16
|
+
CLAUDE_CAPABILITIES,
|
|
17
|
+
} from "../protocol/driver";
|
|
18
|
+
import {
|
|
19
|
+
IREnvelope,
|
|
20
|
+
IRSource,
|
|
21
|
+
createIREnvelope,
|
|
22
|
+
IRTextDelta,
|
|
23
|
+
IRToolStart,
|
|
24
|
+
IRToolResult,
|
|
25
|
+
IRSession,
|
|
26
|
+
IRInit,
|
|
27
|
+
IRTask,
|
|
28
|
+
IRGit,
|
|
29
|
+
IRError,
|
|
30
|
+
} from "../protocol/ir";
|
|
31
|
+
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// Tool Name Mapping (Claude -> IR normalized names)
|
|
34
|
+
// ============================================================================
|
|
35
|
+
|
|
36
|
+
const CLAUDE_TOOL_MAPPING: Record<string, string> = {
|
|
37
|
+
"Read": "file_read",
|
|
38
|
+
"Write": "file_write",
|
|
39
|
+
"Edit": "file_edit",
|
|
40
|
+
"Bash": "shell_exec",
|
|
41
|
+
"Glob": "file_glob",
|
|
42
|
+
"Grep": "file_grep",
|
|
43
|
+
"WebSearch": "web_search",
|
|
44
|
+
"WebFetch": "web_fetch",
|
|
45
|
+
"Task": "agent_spawn",
|
|
46
|
+
"TaskCreate": "todo_create",
|
|
47
|
+
"TaskUpdate": "todo_update",
|
|
48
|
+
"TaskList": "todo_list",
|
|
49
|
+
"TaskGet": "todo_get",
|
|
50
|
+
"AskUserQuestion": "user_question",
|
|
51
|
+
"EnterPlanMode": "plan_mode_enter",
|
|
52
|
+
"ExitPlanMode": "plan_mode_exit",
|
|
53
|
+
"Skill": "skill_invoke",
|
|
54
|
+
"NotebookEdit": "notebook_edit",
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Normalize Claude tool name to IR format
|
|
59
|
+
*/
|
|
60
|
+
function normalizeToolName(claudeName: string): string {
|
|
61
|
+
return CLAUDE_TOOL_MAPPING[claudeName] || claudeName.toLowerCase();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ============================================================================
|
|
65
|
+
// Claude Driver Implementation
|
|
66
|
+
// ============================================================================
|
|
67
|
+
|
|
68
|
+
export class ClaudeDriver implements Driver {
|
|
69
|
+
readonly id: IRSource = "claude";
|
|
70
|
+
readonly name = "Claude Code";
|
|
71
|
+
|
|
72
|
+
private _status: DriverStatus = {
|
|
73
|
+
state: "stopped",
|
|
74
|
+
provider: "claude",
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
private _capabilities: Capability[] = [...CLAUDE_CAPABILITIES];
|
|
78
|
+
private _eventHandlers: Set<IREventHandler> = new Set();
|
|
79
|
+
private _sessions: Map<string, { config: DriverConfig; seqCounter: number }> = new Map();
|
|
80
|
+
|
|
81
|
+
// -------------------------------------------------------------------------
|
|
82
|
+
// Getters
|
|
83
|
+
// -------------------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
get status(): DriverStatus {
|
|
86
|
+
return this._status;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// -------------------------------------------------------------------------
|
|
90
|
+
// Lifecycle
|
|
91
|
+
// -------------------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
async start(sessionId: string, config: DriverConfig): Promise<void> {
|
|
94
|
+
this._sessions.set(sessionId, { config, seqCounter: 0 });
|
|
95
|
+
|
|
96
|
+
this._status = {
|
|
97
|
+
state: "ready",
|
|
98
|
+
provider: "claude",
|
|
99
|
+
model: config.model || "claude-3-opus",
|
|
100
|
+
contextMax: config.maxTokens || 200000,
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// Emit init event
|
|
104
|
+
const initPayload: IRInit = {
|
|
105
|
+
provider: "claude",
|
|
106
|
+
version: "1.0.0", // TODO: Get actual version from CLI
|
|
107
|
+
capabilities: this._capabilities.filter(c => c.available).map(c => c.name),
|
|
108
|
+
maxContext: config.maxTokens || 200000,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
this._emit(createIREnvelope("init", sessionId, "claude", initPayload));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async stop(sessionId: string): Promise<void> {
|
|
115
|
+
this._sessions.delete(sessionId);
|
|
116
|
+
|
|
117
|
+
if (this._sessions.size === 0) {
|
|
118
|
+
this._status = {
|
|
119
|
+
...this._status,
|
|
120
|
+
state: "stopped",
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async isAvailable(): Promise<boolean> {
|
|
126
|
+
// Check if 'claude' command is available
|
|
127
|
+
// In a real implementation, this would use exec/spawn to check
|
|
128
|
+
return true; // Assume available for now
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// -------------------------------------------------------------------------
|
|
132
|
+
// Capabilities
|
|
133
|
+
// -------------------------------------------------------------------------
|
|
134
|
+
|
|
135
|
+
capabilities(): Capability[] {
|
|
136
|
+
return this._capabilities;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
hasCapability(name: CapabilityName): boolean {
|
|
140
|
+
const cap = this._capabilities.find(c => c.name === name);
|
|
141
|
+
return cap?.available ?? false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// -------------------------------------------------------------------------
|
|
145
|
+
// Communication
|
|
146
|
+
// -------------------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
async send(sessionId: string, command: CLICommand): Promise<void> {
|
|
149
|
+
// Mark as busy
|
|
150
|
+
this._status = { ...this._status, state: "busy" };
|
|
151
|
+
|
|
152
|
+
// This would normally send to the CLI process
|
|
153
|
+
// For now, just emit a session state change
|
|
154
|
+
const sessionPayload: IRSession = {
|
|
155
|
+
state: "thinking",
|
|
156
|
+
};
|
|
157
|
+
this._emit(createIREnvelope("session", sessionId, "claude", sessionPayload));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// -------------------------------------------------------------------------
|
|
161
|
+
// Message Translation (Claude -> IR)
|
|
162
|
+
// -------------------------------------------------------------------------
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Translate a Claude-native message to IR format
|
|
166
|
+
* Called by the dashboard server when it receives messages from Claude
|
|
167
|
+
*/
|
|
168
|
+
translateToIR(sessionId: string, claudeMessage: ClaudeNativeMessage): IREnvelope | null {
|
|
169
|
+
const session = this._sessions.get(sessionId);
|
|
170
|
+
if (!session) return null;
|
|
171
|
+
|
|
172
|
+
switch (claudeMessage.type) {
|
|
173
|
+
case "text":
|
|
174
|
+
return createIREnvelope<IRTextDelta>("text_delta", sessionId, "claude", {
|
|
175
|
+
text: claudeMessage.content,
|
|
176
|
+
done: claudeMessage.done ?? false,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
case "tool_use":
|
|
180
|
+
return createIREnvelope<IRToolStart>("tool_start", sessionId, "claude", {
|
|
181
|
+
id: claudeMessage.id || `tool_${Date.now()}`,
|
|
182
|
+
name: normalizeToolName(claudeMessage.tool),
|
|
183
|
+
nativeName: claudeMessage.tool,
|
|
184
|
+
input: claudeMessage.input || {},
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
case "tool_result":
|
|
188
|
+
return createIREnvelope<IRToolResult>("tool_result", sessionId, "claude", {
|
|
189
|
+
id: claudeMessage.id || "",
|
|
190
|
+
ok: !claudeMessage.error,
|
|
191
|
+
output: claudeMessage.content,
|
|
192
|
+
error: claudeMessage.error,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
case "task":
|
|
196
|
+
return createIREnvelope<IRTask>("task", sessionId, "claude", {
|
|
197
|
+
action: claudeMessage.action as "create" | "update" | "delete" | "list",
|
|
198
|
+
task: claudeMessage.task ? {
|
|
199
|
+
...claudeMessage.task,
|
|
200
|
+
status: claudeMessage.task.status as "pending" | "in_progress" | "completed",
|
|
201
|
+
} : undefined,
|
|
202
|
+
tasks: claudeMessage.tasks?.map((t: { id: string; subject: string; status: string }) => ({
|
|
203
|
+
...t,
|
|
204
|
+
status: t.status as "pending" | "in_progress" | "completed",
|
|
205
|
+
})),
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
case "git_status":
|
|
209
|
+
return createIREnvelope<IRGit>("git", sessionId, "claude", {
|
|
210
|
+
action: "status",
|
|
211
|
+
branch: claudeMessage.branch,
|
|
212
|
+
staged: claudeMessage.staged,
|
|
213
|
+
unstaged: claudeMessage.unstaged,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
case "session_state":
|
|
217
|
+
return createIREnvelope<IRSession>("session", sessionId, "claude", {
|
|
218
|
+
state: claudeMessage.state as "connected" | "thinking" | "idle" | "error",
|
|
219
|
+
message: claudeMessage.message,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
case "error":
|
|
223
|
+
return createIREnvelope<IRError>("error", sessionId, "claude", {
|
|
224
|
+
code: claudeMessage.code || "UNKNOWN",
|
|
225
|
+
message: claudeMessage.message,
|
|
226
|
+
details: claudeMessage.details,
|
|
227
|
+
recoverable: claudeMessage.recoverable ?? true,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
default:
|
|
231
|
+
// Unknown message type, skip
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Emit translated IR message to all handlers
|
|
238
|
+
*/
|
|
239
|
+
emitIR(envelope: IREnvelope): void {
|
|
240
|
+
this._emit(envelope);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// -------------------------------------------------------------------------
|
|
244
|
+
// Events
|
|
245
|
+
// -------------------------------------------------------------------------
|
|
246
|
+
|
|
247
|
+
onEvent(handler: IREventHandler): void {
|
|
248
|
+
this._eventHandlers.add(handler);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
offEvent(handler: IREventHandler): void {
|
|
252
|
+
this._eventHandlers.delete(handler);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
private _emit(envelope: IREnvelope): void {
|
|
256
|
+
Array.from(this._eventHandlers).forEach((handler) => {
|
|
257
|
+
try {
|
|
258
|
+
handler(envelope);
|
|
259
|
+
} catch (error) {
|
|
260
|
+
console.error("[ClaudeDriver] Event handler error:", error);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// ============================================================================
|
|
267
|
+
// Claude Native Message Types (from dashboard-protocol.js)
|
|
268
|
+
// ============================================================================
|
|
269
|
+
|
|
270
|
+
export interface ClaudeNativeMessage {
|
|
271
|
+
type: string;
|
|
272
|
+
id?: string;
|
|
273
|
+
content?: string;
|
|
274
|
+
done?: boolean;
|
|
275
|
+
tool?: string;
|
|
276
|
+
input?: Record<string, unknown>;
|
|
277
|
+
error?: string;
|
|
278
|
+
action?: string;
|
|
279
|
+
task?: {
|
|
280
|
+
id: string;
|
|
281
|
+
subject: string;
|
|
282
|
+
description?: string;
|
|
283
|
+
status: string;
|
|
284
|
+
activeForm?: string;
|
|
285
|
+
};
|
|
286
|
+
tasks?: Array<{
|
|
287
|
+
id: string;
|
|
288
|
+
subject: string;
|
|
289
|
+
status: string;
|
|
290
|
+
}>;
|
|
291
|
+
branch?: string;
|
|
292
|
+
staged?: Array<{ path: string; status: string }>;
|
|
293
|
+
unstaged?: Array<{ path: string; status: string }>;
|
|
294
|
+
state?: string;
|
|
295
|
+
message?: string;
|
|
296
|
+
code?: string;
|
|
297
|
+
details?: unknown;
|
|
298
|
+
recoverable?: boolean;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// ============================================================================
|
|
302
|
+
// Factory Function
|
|
303
|
+
// ============================================================================
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Create a new Claude driver instance
|
|
307
|
+
*/
|
|
308
|
+
export function createClaudeDriver(): ClaudeDriver {
|
|
309
|
+
return new ClaudeDriver();
|
|
310
|
+
}
|