@camilyos/codex-antigravity-kit 0.1.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/AGENTS.md +13 -0
- package/README.md +234 -0
- package/dist/chunk-URIBUKLX.js +1747 -0
- package/dist/cli.cjs +1808 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +84 -0
- package/dist/index.cjs +1794 -0
- package/dist/index.d.cts +186 -0
- package/dist/index.d.ts +186 -0
- package/dist/index.js +44 -0
- package/package.json +56 -0
package/dist/cli.cjs
ADDED
|
@@ -0,0 +1,1808 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// src/cli.ts
|
|
5
|
+
var import_commander = require("commander");
|
|
6
|
+
var import_node_path6 = require("path");
|
|
7
|
+
|
|
8
|
+
// src/commands/brainstorm.ts
|
|
9
|
+
var import_node_fs3 = require("fs");
|
|
10
|
+
|
|
11
|
+
// src/core/agent-router.ts
|
|
12
|
+
var import_node_fs = require("fs");
|
|
13
|
+
var import_node_path = require("path");
|
|
14
|
+
var KNOWN_AGENTS = {
|
|
15
|
+
"web-engineer": {
|
|
16
|
+
id: "web-engineer",
|
|
17
|
+
name: "Web Engineer",
|
|
18
|
+
agentFile: "web-engineer.md",
|
|
19
|
+
skillFile: "web-engineering.md",
|
|
20
|
+
description: "Modern web fullstack architecture, frontend, APIs, CSS, and performance",
|
|
21
|
+
keywords: [
|
|
22
|
+
"web",
|
|
23
|
+
"frontend",
|
|
24
|
+
"backend",
|
|
25
|
+
"html",
|
|
26
|
+
"css",
|
|
27
|
+
"react",
|
|
28
|
+
"next.js",
|
|
29
|
+
"nextjs",
|
|
30
|
+
"vue",
|
|
31
|
+
"svelte",
|
|
32
|
+
"angular",
|
|
33
|
+
"rest api",
|
|
34
|
+
"graphql",
|
|
35
|
+
"websocket",
|
|
36
|
+
"http",
|
|
37
|
+
"endpoint",
|
|
38
|
+
"tailwind",
|
|
39
|
+
"responsive",
|
|
40
|
+
"core web vitals",
|
|
41
|
+
"lcp",
|
|
42
|
+
"inp",
|
|
43
|
+
"browser",
|
|
44
|
+
"dom"
|
|
45
|
+
],
|
|
46
|
+
repoIndicators: [
|
|
47
|
+
"next.config.js",
|
|
48
|
+
"next.config.mjs",
|
|
49
|
+
"next.config.ts",
|
|
50
|
+
"vite.config.ts",
|
|
51
|
+
"vite.config.js",
|
|
52
|
+
"svelte.config.js",
|
|
53
|
+
"angular.json",
|
|
54
|
+
"tsconfig.json"
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
"mobile-engineer": {
|
|
58
|
+
id: "mobile-engineer",
|
|
59
|
+
name: "Mobile Engineer",
|
|
60
|
+
agentFile: "mobile-engineer.md",
|
|
61
|
+
skillFile: "mobile-engineering.md",
|
|
62
|
+
description: "Mobile applications across Native (iOS/Android) and Cross-Platform (Flutter, React Native)",
|
|
63
|
+
keywords: [
|
|
64
|
+
"mobile",
|
|
65
|
+
"ios",
|
|
66
|
+
"android",
|
|
67
|
+
"flutter",
|
|
68
|
+
"dart",
|
|
69
|
+
"react native",
|
|
70
|
+
"react-native",
|
|
71
|
+
"expo",
|
|
72
|
+
"swift",
|
|
73
|
+
"swiftui",
|
|
74
|
+
"uikit",
|
|
75
|
+
"kotlin",
|
|
76
|
+
"jetpack compose",
|
|
77
|
+
"apk",
|
|
78
|
+
"ipa",
|
|
79
|
+
"push notification",
|
|
80
|
+
"biometrics",
|
|
81
|
+
"app store",
|
|
82
|
+
"play store",
|
|
83
|
+
"offline-first",
|
|
84
|
+
"sqlite"
|
|
85
|
+
],
|
|
86
|
+
repoIndicators: [
|
|
87
|
+
"pubspec.yaml",
|
|
88
|
+
"Podfile",
|
|
89
|
+
"android/build.gradle",
|
|
90
|
+
"ios/Podfile",
|
|
91
|
+
"build.gradle",
|
|
92
|
+
"build.gradle.kts"
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
"game-engineer": {
|
|
96
|
+
id: "game-engineer",
|
|
97
|
+
name: "Game Engineer",
|
|
98
|
+
agentFile: "game-engineer.md",
|
|
99
|
+
skillFile: "game-engineering.md",
|
|
100
|
+
description: "Game architecture and mechanics across Unity, Godot, and Cocos Creator",
|
|
101
|
+
keywords: [
|
|
102
|
+
"game",
|
|
103
|
+
"gameplay",
|
|
104
|
+
"game loop",
|
|
105
|
+
"unity",
|
|
106
|
+
"godot",
|
|
107
|
+
"cocos",
|
|
108
|
+
"cocos creator",
|
|
109
|
+
"physics",
|
|
110
|
+
"rigidbody",
|
|
111
|
+
"collider",
|
|
112
|
+
"collision",
|
|
113
|
+
"sprite",
|
|
114
|
+
"tilemap",
|
|
115
|
+
"prefab",
|
|
116
|
+
"shader",
|
|
117
|
+
"draw call",
|
|
118
|
+
"fps",
|
|
119
|
+
"ecs",
|
|
120
|
+
"fixedupdate",
|
|
121
|
+
"_physics_process",
|
|
122
|
+
"player controller"
|
|
123
|
+
],
|
|
124
|
+
repoIndicators: [
|
|
125
|
+
"project.godot",
|
|
126
|
+
"ProjectSettings/ProjectVersion.txt",
|
|
127
|
+
"Assets",
|
|
128
|
+
"cocos.config.json",
|
|
129
|
+
"project.json"
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
"researcher": {
|
|
133
|
+
id: "researcher",
|
|
134
|
+
name: "Technical Researcher",
|
|
135
|
+
agentFile: "researcher.md",
|
|
136
|
+
skillFile: "research.md",
|
|
137
|
+
description: "Deep technical research, feasibility studies, spikes, and architecture trade-offs",
|
|
138
|
+
keywords: [
|
|
139
|
+
"research",
|
|
140
|
+
"spike",
|
|
141
|
+
"feasibility",
|
|
142
|
+
"investigate",
|
|
143
|
+
"benchmark",
|
|
144
|
+
"comparison",
|
|
145
|
+
"trade-off",
|
|
146
|
+
"tradeoff",
|
|
147
|
+
"evaluate library",
|
|
148
|
+
"proof of concept",
|
|
149
|
+
"poc",
|
|
150
|
+
"state-of-the-art",
|
|
151
|
+
"options analysis",
|
|
152
|
+
"architectural evaluation"
|
|
153
|
+
],
|
|
154
|
+
repoIndicators: []
|
|
155
|
+
},
|
|
156
|
+
"business-analyst": {
|
|
157
|
+
id: "business-analyst",
|
|
158
|
+
name: "Business Analyst",
|
|
159
|
+
agentFile: "business-analyst.md",
|
|
160
|
+
skillFile: "requirements-analysis.md",
|
|
161
|
+
description: "Requirements elicitation, user stories, domain modeling, and Gherkin acceptance criteria",
|
|
162
|
+
keywords: [
|
|
163
|
+
"requirements",
|
|
164
|
+
"requirement",
|
|
165
|
+
"user story",
|
|
166
|
+
"user stories",
|
|
167
|
+
"acceptance criteria",
|
|
168
|
+
"given ",
|
|
169
|
+
"when ",
|
|
170
|
+
"then ",
|
|
171
|
+
"persona",
|
|
172
|
+
"personas",
|
|
173
|
+
"business logic",
|
|
174
|
+
"prd",
|
|
175
|
+
"functional requirement",
|
|
176
|
+
"non-functional",
|
|
177
|
+
"workflow diagram",
|
|
178
|
+
"user journey"
|
|
179
|
+
],
|
|
180
|
+
repoIndicators: []
|
|
181
|
+
},
|
|
182
|
+
"codex": {
|
|
183
|
+
id: "codex",
|
|
184
|
+
name: "Codex Lead",
|
|
185
|
+
agentFile: "codex.md",
|
|
186
|
+
skillFile: "codex-workflow.md",
|
|
187
|
+
description: "General technical lead, architect, and orchestrator",
|
|
188
|
+
keywords: ["orchestration", "workflow", "general", "architecture"],
|
|
189
|
+
repoIndicators: []
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
function detectAgent(options) {
|
|
193
|
+
const { root, content = "", explicitAgent } = options;
|
|
194
|
+
if (explicitAgent && explicitAgent.trim().length > 0) {
|
|
195
|
+
const normalized = explicitAgent.trim().toLowerCase();
|
|
196
|
+
const match = KNOWN_AGENTS[normalized];
|
|
197
|
+
if (!match) {
|
|
198
|
+
const valid = Object.keys(KNOWN_AGENTS).join(", ");
|
|
199
|
+
throw new Error(`Unknown agent: "${explicitAgent}". Available agents: ${valid}`);
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
agent: match,
|
|
203
|
+
isExplicit: true,
|
|
204
|
+
confidence: 1,
|
|
205
|
+
reason: `Explicitly requested via --agent ${match.id}`,
|
|
206
|
+
instructions: loadAgentInstructions(root, match.agentFile),
|
|
207
|
+
skillInstructions: loadSkillInstructions(root, match.skillFile)
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
const normalizedText = ` ${content.toLowerCase()} `;
|
|
211
|
+
const candidateScores = {
|
|
212
|
+
"game-engineer": { score: 0, reasons: [] },
|
|
213
|
+
"mobile-engineer": { score: 0, reasons: [] },
|
|
214
|
+
"web-engineer": { score: 0, reasons: [] },
|
|
215
|
+
"researcher": { score: 0, reasons: [] },
|
|
216
|
+
"business-analyst": { score: 0, reasons: [] }
|
|
217
|
+
};
|
|
218
|
+
for (const [id, candidate] of Object.entries(candidateScores)) {
|
|
219
|
+
const def = KNOWN_AGENTS[id];
|
|
220
|
+
if (!def) continue;
|
|
221
|
+
for (const kw of def.keywords) {
|
|
222
|
+
if (normalizedText.includes(kw)) {
|
|
223
|
+
candidate.score += 2;
|
|
224
|
+
if (candidate.reasons.length < 3) {
|
|
225
|
+
candidate.reasons.push(`keyword "${kw}"`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
for (const [id, candidate] of Object.entries(candidateScores)) {
|
|
231
|
+
const def = KNOWN_AGENTS[id];
|
|
232
|
+
if (!def) continue;
|
|
233
|
+
for (const fileIndicator of def.repoIndicators) {
|
|
234
|
+
if ((0, import_node_fs.existsSync)((0, import_node_path.join)(root, fileIndicator))) {
|
|
235
|
+
candidate.score += 3;
|
|
236
|
+
if (candidate.reasons.length < 4) {
|
|
237
|
+
candidate.reasons.push(`repo file "${fileIndicator}"`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const packageJsonPath = (0, import_node_path.join)(root, "package.json");
|
|
243
|
+
if ((0, import_node_fs.existsSync)(packageJsonPath)) {
|
|
244
|
+
try {
|
|
245
|
+
const rawPkg = (0, import_node_fs.readFileSync)(packageJsonPath, "utf8");
|
|
246
|
+
if (rawPkg.includes("react-native") || rawPkg.includes("expo")) {
|
|
247
|
+
candidateScores["mobile-engineer"].score += 3;
|
|
248
|
+
candidateScores["mobile-engineer"].reasons.push("package.json (react-native)");
|
|
249
|
+
} else if (rawPkg.includes("react") || rawPkg.includes("next") || rawPkg.includes("vue") || rawPkg.includes("svelte")) {
|
|
250
|
+
candidateScores["web-engineer"].score += 2;
|
|
251
|
+
candidateScores["web-engineer"].reasons.push("package.json (web framework)");
|
|
252
|
+
}
|
|
253
|
+
} catch {
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
let bestCandidateId = "codex";
|
|
257
|
+
let maxScore = 0;
|
|
258
|
+
let matchReasons = [];
|
|
259
|
+
for (const [id, data] of Object.entries(candidateScores)) {
|
|
260
|
+
if (data.score > maxScore) {
|
|
261
|
+
maxScore = data.score;
|
|
262
|
+
bestCandidateId = id;
|
|
263
|
+
matchReasons = data.reasons;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const selectedDef = KNOWN_AGENTS[bestCandidateId] ?? KNOWN_AGENTS["codex"];
|
|
267
|
+
const confidence = Math.min(1, maxScore / 6);
|
|
268
|
+
const reason = maxScore > 0 ? `Auto-detected based on ${matchReasons.join(", ")}` : "Defaulted to Codex General Lead (no specific domain signals found)";
|
|
269
|
+
return {
|
|
270
|
+
agent: selectedDef,
|
|
271
|
+
isExplicit: false,
|
|
272
|
+
confidence,
|
|
273
|
+
reason,
|
|
274
|
+
instructions: loadAgentInstructions(root, selectedDef.agentFile),
|
|
275
|
+
skillInstructions: loadSkillInstructions(root, selectedDef.skillFile)
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function loadAgentInstructions(root, fileName) {
|
|
279
|
+
const customPath = (0, import_node_path.join)(root, ".codex", "agents", fileName);
|
|
280
|
+
if ((0, import_node_fs.existsSync)(customPath)) {
|
|
281
|
+
return (0, import_node_fs.readFileSync)(customPath, "utf8");
|
|
282
|
+
}
|
|
283
|
+
return "";
|
|
284
|
+
}
|
|
285
|
+
function loadSkillInstructions(root, fileName) {
|
|
286
|
+
const customPath = (0, import_node_path.join)(root, ".codex", "skills", fileName);
|
|
287
|
+
if ((0, import_node_fs.existsSync)(customPath)) {
|
|
288
|
+
return (0, import_node_fs.readFileSync)(customPath, "utf8");
|
|
289
|
+
}
|
|
290
|
+
return "";
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// src/core/state-machine.ts
|
|
294
|
+
var WorkflowState = /* @__PURE__ */ ((WorkflowState2) => {
|
|
295
|
+
WorkflowState2["IDLE"] = "IDLE";
|
|
296
|
+
WorkflowState2["DISCOVERY"] = "DISCOVERY";
|
|
297
|
+
WorkflowState2["CLARIFICATION_REQUIRED"] = "CLARIFICATION_REQUIRED";
|
|
298
|
+
WorkflowState2["BRAINSTORMING"] = "BRAINSTORMING";
|
|
299
|
+
WorkflowState2["PLANNING"] = "PLANNING";
|
|
300
|
+
WorkflowState2["READY"] = "READY";
|
|
301
|
+
WorkflowState2["IMPLEMENTING"] = "IMPLEMENTING";
|
|
302
|
+
WorkflowState2["VERIFYING"] = "VERIFYING";
|
|
303
|
+
WorkflowState2["REVIEWING"] = "REVIEWING";
|
|
304
|
+
WorkflowState2["REPAIR_REQUIRED"] = "REPAIR_REQUIRED";
|
|
305
|
+
WorkflowState2["COMPLETED"] = "COMPLETED";
|
|
306
|
+
WorkflowState2["BLOCKED"] = "BLOCKED";
|
|
307
|
+
WorkflowState2["ESCALATION_REQUIRED"] = "ESCALATION_REQUIRED";
|
|
308
|
+
return WorkflowState2;
|
|
309
|
+
})(WorkflowState || {});
|
|
310
|
+
var transitions = {
|
|
311
|
+
["IDLE" /* IDLE */]: ["DISCOVERY" /* DISCOVERY */],
|
|
312
|
+
["DISCOVERY" /* DISCOVERY */]: [
|
|
313
|
+
"CLARIFICATION_REQUIRED" /* CLARIFICATION_REQUIRED */,
|
|
314
|
+
"BRAINSTORMING" /* BRAINSTORMING */
|
|
315
|
+
],
|
|
316
|
+
["CLARIFICATION_REQUIRED" /* CLARIFICATION_REQUIRED */]: [
|
|
317
|
+
"BRAINSTORMING" /* BRAINSTORMING */,
|
|
318
|
+
"ESCALATION_REQUIRED" /* ESCALATION_REQUIRED */
|
|
319
|
+
],
|
|
320
|
+
["BRAINSTORMING" /* BRAINSTORMING */]: ["PLANNING" /* PLANNING */],
|
|
321
|
+
["PLANNING" /* PLANNING */]: ["READY" /* READY */],
|
|
322
|
+
["READY" /* READY */]: ["IMPLEMENTING" /* IMPLEMENTING */],
|
|
323
|
+
["IMPLEMENTING" /* IMPLEMENTING */]: [
|
|
324
|
+
"VERIFYING" /* VERIFYING */,
|
|
325
|
+
"BLOCKED" /* BLOCKED */,
|
|
326
|
+
"ESCALATION_REQUIRED" /* ESCALATION_REQUIRED */
|
|
327
|
+
],
|
|
328
|
+
["VERIFYING" /* VERIFYING */]: ["REVIEWING" /* REVIEWING */, "BLOCKED" /* BLOCKED */],
|
|
329
|
+
["REVIEWING" /* REVIEWING */]: [
|
|
330
|
+
"COMPLETED" /* COMPLETED */,
|
|
331
|
+
"REPAIR_REQUIRED" /* REPAIR_REQUIRED */,
|
|
332
|
+
"ESCALATION_REQUIRED" /* ESCALATION_REQUIRED */,
|
|
333
|
+
"BLOCKED" /* BLOCKED */
|
|
334
|
+
],
|
|
335
|
+
["REPAIR_REQUIRED" /* REPAIR_REQUIRED */]: ["IMPLEMENTING" /* IMPLEMENTING */],
|
|
336
|
+
["COMPLETED" /* COMPLETED */]: ["IDLE" /* IDLE */],
|
|
337
|
+
["BLOCKED" /* BLOCKED */]: ["ESCALATION_REQUIRED" /* ESCALATION_REQUIRED */],
|
|
338
|
+
["ESCALATION_REQUIRED" /* ESCALATION_REQUIRED */]: ["IDLE" /* IDLE */]
|
|
339
|
+
};
|
|
340
|
+
function canTransition(from, to) {
|
|
341
|
+
return transitions[from].includes(to);
|
|
342
|
+
}
|
|
343
|
+
function transitionOrThrow(from, to) {
|
|
344
|
+
if (!canTransition(from, to)) {
|
|
345
|
+
throw new Error(`Invalid state transition: ${from} -> ${to}`);
|
|
346
|
+
}
|
|
347
|
+
return to;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// src/fs/workflow-store.ts
|
|
351
|
+
var import_node_fs2 = require("fs");
|
|
352
|
+
var import_node_path2 = require("path");
|
|
353
|
+
var WorkflowStore = class {
|
|
354
|
+
root;
|
|
355
|
+
workflowDir;
|
|
356
|
+
tasksDir;
|
|
357
|
+
statePath;
|
|
358
|
+
configPath;
|
|
359
|
+
constructor(root) {
|
|
360
|
+
this.root = root;
|
|
361
|
+
this.workflowDir = (0, import_node_path2.join)(root, ".agent-workflow");
|
|
362
|
+
this.tasksDir = (0, import_node_path2.join)(this.workflowDir, "tasks");
|
|
363
|
+
this.statePath = (0, import_node_path2.join)(this.workflowDir, "STATE.md");
|
|
364
|
+
this.configPath = (0, import_node_path2.join)(this.workflowDir, "config.json");
|
|
365
|
+
}
|
|
366
|
+
ensureBaseStructure() {
|
|
367
|
+
(0, import_node_fs2.mkdirSync)(this.workflowDir, { recursive: true });
|
|
368
|
+
(0, import_node_fs2.mkdirSync)(this.tasksDir, { recursive: true });
|
|
369
|
+
}
|
|
370
|
+
ensureTask(taskId) {
|
|
371
|
+
const taskDir = (0, import_node_path2.join)(this.tasksDir, taskId);
|
|
372
|
+
(0, import_node_fs2.mkdirSync)(taskDir, { recursive: true });
|
|
373
|
+
return taskDir;
|
|
374
|
+
}
|
|
375
|
+
writeTaskFile(taskId, fileName, content) {
|
|
376
|
+
const taskDir = this.ensureTask(taskId);
|
|
377
|
+
const path = (0, import_node_path2.join)(taskDir, fileName);
|
|
378
|
+
(0, import_node_fs2.writeFileSync)(path, content, "utf8");
|
|
379
|
+
return path;
|
|
380
|
+
}
|
|
381
|
+
readTaskFile(taskId, fileName) {
|
|
382
|
+
const path = (0, import_node_path2.join)(this.tasksDir, taskId, fileName);
|
|
383
|
+
return (0, import_node_fs2.readFileSync)(path, "utf8");
|
|
384
|
+
}
|
|
385
|
+
hasTaskFile(taskId, fileName) {
|
|
386
|
+
const path = (0, import_node_path2.join)(this.tasksDir, taskId, fileName);
|
|
387
|
+
return (0, import_node_fs2.existsSync)(path);
|
|
388
|
+
}
|
|
389
|
+
writeConfig(config) {
|
|
390
|
+
this.ensureBaseStructure();
|
|
391
|
+
(0, import_node_fs2.writeFileSync)(this.configPath, `${JSON.stringify(config, null, 2)}
|
|
392
|
+
`, "utf8");
|
|
393
|
+
}
|
|
394
|
+
readConfig() {
|
|
395
|
+
const raw = (0, import_node_fs2.readFileSync)(this.configPath, "utf8");
|
|
396
|
+
return JSON.parse(raw);
|
|
397
|
+
}
|
|
398
|
+
writeState(snapshot) {
|
|
399
|
+
this.ensureBaseStructure();
|
|
400
|
+
const content = toStateMarkdown(snapshot);
|
|
401
|
+
(0, import_node_fs2.writeFileSync)(this.statePath, content, "utf8");
|
|
402
|
+
}
|
|
403
|
+
readState() {
|
|
404
|
+
if (!(0, import_node_fs2.existsSync)(this.statePath)) {
|
|
405
|
+
return defaultState();
|
|
406
|
+
}
|
|
407
|
+
const raw = (0, import_node_fs2.readFileSync)(this.statePath, "utf8");
|
|
408
|
+
return parseStateMarkdown(raw);
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
function defaultState() {
|
|
412
|
+
return {
|
|
413
|
+
state: "IDLE" /* IDLE */,
|
|
414
|
+
currentPhase: "none",
|
|
415
|
+
currentTask: "none",
|
|
416
|
+
reviewAttempt: 0,
|
|
417
|
+
repairAttempt: 0,
|
|
418
|
+
nextAction: "Run init",
|
|
419
|
+
blockingIssues: [],
|
|
420
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
function toStateMarkdown(snapshot) {
|
|
424
|
+
const issues = snapshot.blockingIssues.length === 0 ? "- None" : snapshot.blockingIssues.map((issue) => `- ${issue}`).join("\n");
|
|
425
|
+
return [
|
|
426
|
+
"# Current State",
|
|
427
|
+
"",
|
|
428
|
+
`State: ${snapshot.state}`,
|
|
429
|
+
`Current phase: ${snapshot.currentPhase}`,
|
|
430
|
+
`Current task: ${snapshot.currentTask}`,
|
|
431
|
+
`Review attempt: ${snapshot.reviewAttempt}`,
|
|
432
|
+
`Repair attempt: ${snapshot.repairAttempt}`,
|
|
433
|
+
"",
|
|
434
|
+
"## Blocking Issues",
|
|
435
|
+
issues,
|
|
436
|
+
"",
|
|
437
|
+
"## Next",
|
|
438
|
+
snapshot.nextAction,
|
|
439
|
+
"",
|
|
440
|
+
`Updated at: ${snapshot.updatedAt}`,
|
|
441
|
+
""
|
|
442
|
+
].join("\n");
|
|
443
|
+
}
|
|
444
|
+
function parseStateMarkdown(markdown) {
|
|
445
|
+
const line = (prefix) => markdown.split(/\r?\n/).find((item) => item.startsWith(prefix))?.slice(prefix.length).trim();
|
|
446
|
+
const stateValue = line("State: ");
|
|
447
|
+
const currentPhase = line("Current phase: ") ?? "none";
|
|
448
|
+
const currentTask = line("Current task: ") ?? "none";
|
|
449
|
+
const reviewAttempt = Number(line("Review attempt: ") ?? "0");
|
|
450
|
+
const repairAttempt = Number(line("Repair attempt: ") ?? "0");
|
|
451
|
+
const updatedAt = line("Updated at: ") ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
452
|
+
const state = Object.values(WorkflowState).find((value) => value === stateValue) ?? "IDLE" /* IDLE */;
|
|
453
|
+
const nextSection = markdown.split("## Next\n")[1] ?? "";
|
|
454
|
+
const nextAction = (nextSection.split(/\r?\n/)[0] ?? "Run init").trim();
|
|
455
|
+
const blockingSection = markdown.split("## Blocking Issues\n")[1] ?? "";
|
|
456
|
+
const blockingRaw = blockingSection.split("\n## Next")[0] ?? "";
|
|
457
|
+
const blockingIssues = blockingRaw.split(/\r?\n/).map((item) => item.trim()).filter((item) => item.startsWith("- ") && item !== "- None").map((item) => item.slice(2));
|
|
458
|
+
return {
|
|
459
|
+
state,
|
|
460
|
+
currentPhase,
|
|
461
|
+
currentTask,
|
|
462
|
+
reviewAttempt,
|
|
463
|
+
repairAttempt,
|
|
464
|
+
nextAction,
|
|
465
|
+
blockingIssues,
|
|
466
|
+
updatedAt
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// src/commands/brainstorm.ts
|
|
471
|
+
function runBrainstorm(options) {
|
|
472
|
+
const store = new WorkflowStore(options.root);
|
|
473
|
+
store.ensureBaseStructure();
|
|
474
|
+
let spec = "";
|
|
475
|
+
if (options.spec && (0, import_node_fs3.existsSync)(options.spec)) {
|
|
476
|
+
spec = (0, import_node_fs3.readFileSync)(options.spec, "utf8");
|
|
477
|
+
store.writeTaskFile(options.task, "SPEC.md", spec);
|
|
478
|
+
} else if (options.prompt) {
|
|
479
|
+
spec = options.prompt;
|
|
480
|
+
store.writeTaskFile(options.task, "SPEC.md", spec);
|
|
481
|
+
} else if (store.hasTaskFile(options.task, "SPEC.md")) {
|
|
482
|
+
spec = store.readTaskFile(options.task, "SPEC.md");
|
|
483
|
+
} else {
|
|
484
|
+
throw new Error(
|
|
485
|
+
`Missing spec for task ${options.task}. Provide --spec <path>, --prompt <text>, or create .agent-workflow/tasks/${options.task}/SPEC.md`
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
const agentResolution = detectAgent({
|
|
489
|
+
root: options.root,
|
|
490
|
+
content: spec,
|
|
491
|
+
explicitAgent: options.agent
|
|
492
|
+
});
|
|
493
|
+
console.log(`[Agent Router] Assigned: ${agentResolution.agent.name} (${agentResolution.agent.id})`);
|
|
494
|
+
console.log(`[Agent Router] Reason: ${agentResolution.reason}`);
|
|
495
|
+
const brainstorm = buildBrainstormMarkdown(options.task, spec, agentResolution);
|
|
496
|
+
store.writeTaskFile(options.task, "BRAINSTORM.md", brainstorm);
|
|
497
|
+
const state = store.readState();
|
|
498
|
+
state.state = "DISCOVERY" /* DISCOVERY */;
|
|
499
|
+
state.state = "BRAINSTORMING" /* BRAINSTORMING */;
|
|
500
|
+
state.currentTask = options.task;
|
|
501
|
+
state.currentPhase = "brainstorming";
|
|
502
|
+
state.nextAction = "Run plan command to convert brainstorm into phases and tasks";
|
|
503
|
+
state.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
504
|
+
store.writeState(state);
|
|
505
|
+
console.log(brainstorm);
|
|
506
|
+
}
|
|
507
|
+
function buildBrainstormMarkdown(task, spec, agentResolution) {
|
|
508
|
+
return [
|
|
509
|
+
"# Brainstorm",
|
|
510
|
+
"",
|
|
511
|
+
`Task: ${task}`,
|
|
512
|
+
`Assigned Agent: ${agentResolution.agent.name} (${agentResolution.agent.id})`,
|
|
513
|
+
`Agent Selection: ${agentResolution.reason}`,
|
|
514
|
+
"",
|
|
515
|
+
"## Goal",
|
|
516
|
+
`Task ${task}`,
|
|
517
|
+
"",
|
|
518
|
+
"## Current System",
|
|
519
|
+
"Repository contains an orchestration kit with Codex planning and Antigravity execution boundaries.",
|
|
520
|
+
"",
|
|
521
|
+
"## Requirements",
|
|
522
|
+
spec.trim(),
|
|
523
|
+
"",
|
|
524
|
+
"## Constraints",
|
|
525
|
+
"- Keep context small and deterministic",
|
|
526
|
+
"- Use filesystem artifacts as durable state",
|
|
527
|
+
"- Do not invent requirements",
|
|
528
|
+
"",
|
|
529
|
+
"## Relevant Existing Architecture",
|
|
530
|
+
"- Codex owns clarification, planning, review, and verification",
|
|
531
|
+
"- Antigravity owns implementation",
|
|
532
|
+
"- Agy is the worker CLI bridge",
|
|
533
|
+
"",
|
|
534
|
+
"## Options Considered",
|
|
535
|
+
"### Option A",
|
|
536
|
+
"Pros: Simple artifact-first workflow",
|
|
537
|
+
"Cons: Requires explicit commands",
|
|
538
|
+
"",
|
|
539
|
+
"### Option B",
|
|
540
|
+
"Pros: More automation",
|
|
541
|
+
"Cons: Higher complexity and harder debugging",
|
|
542
|
+
"",
|
|
543
|
+
"## Recommended Approach",
|
|
544
|
+
"Use an artifact-first command flow: brainstorm -> plan -> execute -> review.",
|
|
545
|
+
"",
|
|
546
|
+
"## Why",
|
|
547
|
+
"This keeps the workflow small, inspectable, and easy to recover.",
|
|
548
|
+
"",
|
|
549
|
+
"## Risks",
|
|
550
|
+
"- Incomplete specs can still block execution",
|
|
551
|
+
"- Worker output may need repair",
|
|
552
|
+
"",
|
|
553
|
+
"## Open Questions",
|
|
554
|
+
"None",
|
|
555
|
+
""
|
|
556
|
+
].join("\n");
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// src/commands/execute.ts
|
|
560
|
+
var import_node_fs4 = require("fs");
|
|
561
|
+
var import_node_path3 = require("path");
|
|
562
|
+
|
|
563
|
+
// src/bridge/shell-agy-adapter.ts
|
|
564
|
+
var import_node_child_process = require("child_process");
|
|
565
|
+
var ShellAgyAdapter = class {
|
|
566
|
+
command;
|
|
567
|
+
baseArgs;
|
|
568
|
+
constructor(options) {
|
|
569
|
+
this.command = options.command;
|
|
570
|
+
this.baseArgs = options.baseArgs ?? [];
|
|
571
|
+
}
|
|
572
|
+
async run(request) {
|
|
573
|
+
return new Promise((resolve2) => {
|
|
574
|
+
const startedAt = Date.now();
|
|
575
|
+
const args = [
|
|
576
|
+
...this.baseArgs,
|
|
577
|
+
"--add-dir",
|
|
578
|
+
request.repoPath,
|
|
579
|
+
"--print",
|
|
580
|
+
request.prompt,
|
|
581
|
+
"--output-format",
|
|
582
|
+
"text",
|
|
583
|
+
"--print-timeout",
|
|
584
|
+
`${Math.ceil(request.timeoutMs / 1e3)}s`
|
|
585
|
+
];
|
|
586
|
+
const child = (0, import_node_child_process.spawn)(this.command, args, {
|
|
587
|
+
cwd: request.repoPath,
|
|
588
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
589
|
+
});
|
|
590
|
+
let stdout = "";
|
|
591
|
+
let stderr = "";
|
|
592
|
+
let timedOut = false;
|
|
593
|
+
const timer = setTimeout(() => {
|
|
594
|
+
timedOut = true;
|
|
595
|
+
child.kill("SIGTERM");
|
|
596
|
+
}, request.timeoutMs);
|
|
597
|
+
child.stdout.on("data", (chunk) => {
|
|
598
|
+
stdout += chunk.toString("utf8");
|
|
599
|
+
});
|
|
600
|
+
child.stderr.on("data", (chunk) => {
|
|
601
|
+
stderr += chunk.toString("utf8");
|
|
602
|
+
});
|
|
603
|
+
child.on("error", (error) => {
|
|
604
|
+
clearTimeout(timer);
|
|
605
|
+
resolve2({
|
|
606
|
+
ok: false,
|
|
607
|
+
timedOut,
|
|
608
|
+
exitCode: null,
|
|
609
|
+
stdout,
|
|
610
|
+
stderr: `${stderr}
|
|
611
|
+
${error.message}`.trim(),
|
|
612
|
+
durationMs: Date.now() - startedAt
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
child.on("close", (exitCode) => {
|
|
616
|
+
clearTimeout(timer);
|
|
617
|
+
resolve2({
|
|
618
|
+
ok: !timedOut && exitCode === 0,
|
|
619
|
+
timedOut,
|
|
620
|
+
exitCode,
|
|
621
|
+
stdout,
|
|
622
|
+
stderr,
|
|
623
|
+
durationMs: Date.now() - startedAt
|
|
624
|
+
});
|
|
625
|
+
});
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
|
|
630
|
+
// src/core/result-parser.ts
|
|
631
|
+
var knownStatuses = ["DONE", "BLOCKED", "FAILED"];
|
|
632
|
+
function parseWorkerResult(raw) {
|
|
633
|
+
const lines = raw.split(/\r?\n/).map((line) => line.trim());
|
|
634
|
+
const statusLine = lines.find(
|
|
635
|
+
(line) => knownStatuses.some((status2) => line.toUpperCase().includes(status2))
|
|
636
|
+
);
|
|
637
|
+
const status = knownStatuses.find((value) => statusLine?.toUpperCase().includes(value)) ?? "FAILED";
|
|
638
|
+
const summary = lines.find((line) => line.length > 0 && !line.startsWith("#")) ?? "No summary provided by worker.";
|
|
639
|
+
return { status, summary };
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// src/commands/execute.ts
|
|
643
|
+
async function runExecute(options) {
|
|
644
|
+
const store = new WorkflowStore(options.root);
|
|
645
|
+
if (!(0, import_node_fs4.existsSync)(store.configPath)) {
|
|
646
|
+
throw new Error("Missing .agent-workflow/config.json. Run init first.");
|
|
647
|
+
}
|
|
648
|
+
const config = store.readConfig();
|
|
649
|
+
const adapter = new ShellAgyAdapter({
|
|
650
|
+
command: config.agyCommand,
|
|
651
|
+
baseArgs: config.agyArgs
|
|
652
|
+
});
|
|
653
|
+
await runExecuteWithAdapter(options, adapter);
|
|
654
|
+
}
|
|
655
|
+
async function runExecuteWithAdapter(options, adapter) {
|
|
656
|
+
const store = new WorkflowStore(options.root);
|
|
657
|
+
store.ensureBaseStructure();
|
|
658
|
+
const current = store.readState();
|
|
659
|
+
let contextSource = "";
|
|
660
|
+
let contextContent = "";
|
|
661
|
+
if (options.file && (0, import_node_fs4.existsSync)(options.file)) {
|
|
662
|
+
contextSource = options.file;
|
|
663
|
+
contextContent = (0, import_node_fs4.readFileSync)(options.file, "utf8");
|
|
664
|
+
store.writeTaskFile(options.task, "PLAN.md", contextContent);
|
|
665
|
+
} else if (options.plan && (0, import_node_fs4.existsSync)(options.plan)) {
|
|
666
|
+
contextSource = options.plan;
|
|
667
|
+
contextContent = (0, import_node_fs4.readFileSync)(options.plan, "utf8");
|
|
668
|
+
store.writeTaskFile(options.task, "PLAN.md", contextContent);
|
|
669
|
+
} else if (store.hasTaskFile(options.task, "PLAN.md")) {
|
|
670
|
+
contextSource = (0, import_node_path3.join)(store.tasksDir, options.task, "PLAN.md");
|
|
671
|
+
contextContent = store.readTaskFile(options.task, "PLAN.md");
|
|
672
|
+
} else if (options.spec && (0, import_node_fs4.existsSync)(options.spec)) {
|
|
673
|
+
contextSource = options.spec;
|
|
674
|
+
contextContent = (0, import_node_fs4.readFileSync)(options.spec, "utf8");
|
|
675
|
+
store.writeTaskFile(options.task, "SPEC.md", contextContent);
|
|
676
|
+
} else if (store.hasTaskFile(options.task, "SPEC.md")) {
|
|
677
|
+
contextSource = (0, import_node_path3.join)(store.tasksDir, options.task, "SPEC.md");
|
|
678
|
+
contextContent = store.readTaskFile(options.task, "SPEC.md");
|
|
679
|
+
} else {
|
|
680
|
+
throw new Error(
|
|
681
|
+
`No context markdown file found to execute for task ${options.task}. Run 'plan' or provide --plan, --file, or --spec.`
|
|
682
|
+
);
|
|
683
|
+
}
|
|
684
|
+
let repairContent = "";
|
|
685
|
+
if (options.repairRequest && (0, import_node_fs4.existsSync)(options.repairRequest)) {
|
|
686
|
+
repairContent = (0, import_node_fs4.readFileSync)(options.repairRequest, "utf8");
|
|
687
|
+
store.writeTaskFile(options.task, "REPAIR_REQUEST.md", repairContent);
|
|
688
|
+
} else if (store.hasTaskFile(options.task, "REPAIR_REQUEST.md")) {
|
|
689
|
+
repairContent = store.readTaskFile(options.task, "REPAIR_REQUEST.md");
|
|
690
|
+
}
|
|
691
|
+
const agentResolution = detectAgent({
|
|
692
|
+
root: options.root,
|
|
693
|
+
content: contextContent,
|
|
694
|
+
explicitAgent: options.agent
|
|
695
|
+
});
|
|
696
|
+
console.log(`[Agent Router] Assigned: ${agentResolution.agent.name} (${agentResolution.agent.id})`);
|
|
697
|
+
console.log(`[Agent Router] Reason: ${agentResolution.reason}`);
|
|
698
|
+
const executeArtifact = buildExecuteMarkdown(options.task, contextSource, contextContent, agentResolution);
|
|
699
|
+
store.writeTaskFile(options.task, "EXECUTE.md", executeArtifact);
|
|
700
|
+
advanceStateToImplementing(current);
|
|
701
|
+
current.currentTask = options.task;
|
|
702
|
+
current.currentPhase = "implementation";
|
|
703
|
+
current.nextAction = "Wait for worker execution result";
|
|
704
|
+
current.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
705
|
+
store.writeState(current);
|
|
706
|
+
const workerRulesPath = (0, import_node_path3.join)(options.root, ".antigravity", "WORKER_RULES.md");
|
|
707
|
+
const workerRules = (0, import_node_fs4.existsSync)(workerRulesPath) ? (0, import_node_fs4.readFileSync)(workerRulesPath, "utf8") : "";
|
|
708
|
+
const prompt = buildWorkerPrompt({
|
|
709
|
+
taskId: options.task,
|
|
710
|
+
workerRules,
|
|
711
|
+
context: contextContent,
|
|
712
|
+
repairRequest: repairContent,
|
|
713
|
+
agentResolution
|
|
714
|
+
});
|
|
715
|
+
const timeoutMs = options.timeoutMs ?? 6e5;
|
|
716
|
+
const execution = await adapter.run({
|
|
717
|
+
repoPath: options.root,
|
|
718
|
+
taskId: options.task,
|
|
719
|
+
prompt,
|
|
720
|
+
timeoutMs
|
|
721
|
+
});
|
|
722
|
+
const resultContent = toResultMarkdown(
|
|
723
|
+
execution.stdout,
|
|
724
|
+
execution.stderr,
|
|
725
|
+
execution.exitCode,
|
|
726
|
+
execution.durationMs
|
|
727
|
+
);
|
|
728
|
+
store.writeTaskFile(options.task, "RESULT.md", resultContent);
|
|
729
|
+
current.state = transitionOrThrow(current.state, "VERIFYING" /* VERIFYING */);
|
|
730
|
+
if (!execution.ok) {
|
|
731
|
+
current.state = "BLOCKED" /* BLOCKED */;
|
|
732
|
+
current.blockingIssues = [
|
|
733
|
+
execution.timedOut ? "Worker execution timed out" : `Worker failed with exit code ${execution.exitCode}`
|
|
734
|
+
];
|
|
735
|
+
current.nextAction = "Inspect RESULT.md and decide escalation or retry";
|
|
736
|
+
current.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
737
|
+
store.writeState(current);
|
|
738
|
+
console.log("Worker execution failed or timed out. See RESULT.md");
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
const parsed = parseWorkerResult(execution.stdout);
|
|
742
|
+
applyParsedResultState(current, parsed);
|
|
743
|
+
current.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
744
|
+
store.writeState(current);
|
|
745
|
+
console.log(`Worker status: ${parsed.status}`);
|
|
746
|
+
console.log(`Summary: ${parsed.summary}`);
|
|
747
|
+
}
|
|
748
|
+
function advanceStateToImplementing(snapshot) {
|
|
749
|
+
if (snapshot.state === "IMPLEMENTING" /* IMPLEMENTING */) {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
if (snapshot.state === "REPAIR_REQUIRED" /* REPAIR_REQUIRED */) {
|
|
753
|
+
snapshot.state = transitionOrThrow(snapshot.state, "IMPLEMENTING" /* IMPLEMENTING */);
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
if (snapshot.state === "READY" /* READY */) {
|
|
757
|
+
snapshot.state = transitionOrThrow(snapshot.state, "IMPLEMENTING" /* IMPLEMENTING */);
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
if (snapshot.state === "PLANNING" /* PLANNING */) {
|
|
761
|
+
snapshot.state = transitionOrThrow(snapshot.state, "READY" /* READY */);
|
|
762
|
+
snapshot.state = transitionOrThrow(snapshot.state, "IMPLEMENTING" /* IMPLEMENTING */);
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
if (snapshot.state === "BRAINSTORMING" /* BRAINSTORMING */) {
|
|
766
|
+
snapshot.state = transitionOrThrow(snapshot.state, "PLANNING" /* PLANNING */);
|
|
767
|
+
snapshot.state = transitionOrThrow(snapshot.state, "READY" /* READY */);
|
|
768
|
+
snapshot.state = transitionOrThrow(snapshot.state, "IMPLEMENTING" /* IMPLEMENTING */);
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
if (snapshot.state === "DISCOVERY" /* DISCOVERY */) {
|
|
772
|
+
snapshot.state = transitionOrThrow(snapshot.state, "BRAINSTORMING" /* BRAINSTORMING */);
|
|
773
|
+
snapshot.state = transitionOrThrow(snapshot.state, "PLANNING" /* PLANNING */);
|
|
774
|
+
snapshot.state = transitionOrThrow(snapshot.state, "READY" /* READY */);
|
|
775
|
+
snapshot.state = transitionOrThrow(snapshot.state, "IMPLEMENTING" /* IMPLEMENTING */);
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
snapshot.state = transitionOrThrow(snapshot.state, "DISCOVERY" /* DISCOVERY */);
|
|
779
|
+
snapshot.state = transitionOrThrow(snapshot.state, "BRAINSTORMING" /* BRAINSTORMING */);
|
|
780
|
+
snapshot.state = transitionOrThrow(snapshot.state, "PLANNING" /* PLANNING */);
|
|
781
|
+
snapshot.state = transitionOrThrow(snapshot.state, "READY" /* READY */);
|
|
782
|
+
snapshot.state = transitionOrThrow(snapshot.state, "IMPLEMENTING" /* IMPLEMENTING */);
|
|
783
|
+
}
|
|
784
|
+
function buildWorkerPrompt(input) {
|
|
785
|
+
const parts = [
|
|
786
|
+
"You are Antigravity implementation worker.",
|
|
787
|
+
"",
|
|
788
|
+
input.workerRules,
|
|
789
|
+
"",
|
|
790
|
+
`# Task ID
|
|
791
|
+
${input.taskId}`,
|
|
792
|
+
"",
|
|
793
|
+
`# Assigned Role
|
|
794
|
+
Agent: ${input.agentResolution.agent.name} (${input.agentResolution.agent.id})
|
|
795
|
+
Reason: ${input.agentResolution.reason}`
|
|
796
|
+
];
|
|
797
|
+
if (input.agentResolution.instructions) {
|
|
798
|
+
parts.push("# Agent Operational Guidelines\n" + input.agentResolution.instructions);
|
|
799
|
+
}
|
|
800
|
+
if (input.agentResolution.skillInstructions) {
|
|
801
|
+
parts.push("# Recommended Skill Practices\n" + input.agentResolution.skillInstructions);
|
|
802
|
+
}
|
|
803
|
+
parts.push("# Implementation Context & Specification\n" + input.context);
|
|
804
|
+
if (input.repairRequest) {
|
|
805
|
+
parts.push("# REPAIR REQUEST\n" + input.repairRequest);
|
|
806
|
+
}
|
|
807
|
+
parts.push("Return only concise Implementation Result markdown with status DONE | BLOCKED | FAILED.");
|
|
808
|
+
return parts.filter(Boolean).join("\n\n");
|
|
809
|
+
}
|
|
810
|
+
function applyParsedResultState(state, result) {
|
|
811
|
+
state.state = transitionOrThrow(state.state, "REVIEWING" /* REVIEWING */);
|
|
812
|
+
if (result.status === "DONE") {
|
|
813
|
+
state.nextAction = "Run review and record PASS/FAIL";
|
|
814
|
+
state.blockingIssues = [];
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
if (result.status === "FAILED") {
|
|
818
|
+
state.state = "REPAIR_REQUIRED" /* REPAIR_REQUIRED */;
|
|
819
|
+
state.repairAttempt += 1;
|
|
820
|
+
state.nextAction = "Create repair request and execute again";
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
state.state = "ESCALATION_REQUIRED" /* ESCALATION_REQUIRED */;
|
|
824
|
+
state.blockingIssues = ["Worker returned BLOCKED status"];
|
|
825
|
+
state.nextAction = "Resolve blocking decision with user";
|
|
826
|
+
}
|
|
827
|
+
function buildExecuteMarkdown(task, source, context, agentResolution) {
|
|
828
|
+
return [
|
|
829
|
+
"# Execute",
|
|
830
|
+
"",
|
|
831
|
+
`Task: ${task}`,
|
|
832
|
+
`Source: ${source}`,
|
|
833
|
+
`Assigned Agent: ${agentResolution.agent.name} (${agentResolution.agent.id})`,
|
|
834
|
+
`Agent Selection: ${agentResolution.reason}`,
|
|
835
|
+
"",
|
|
836
|
+
"## Context & Plan Package",
|
|
837
|
+
context.trim(),
|
|
838
|
+
"",
|
|
839
|
+
"## Expected Worker Result",
|
|
840
|
+
"- DONE when implementation and tests complete",
|
|
841
|
+
"- FAILED when implementation needs repair",
|
|
842
|
+
"- BLOCKED when missing context/decision",
|
|
843
|
+
""
|
|
844
|
+
].join("\n");
|
|
845
|
+
}
|
|
846
|
+
function toResultMarkdown(stdout, stderr, exitCode, durationMs) {
|
|
847
|
+
return [
|
|
848
|
+
"# Implementation Result",
|
|
849
|
+
"",
|
|
850
|
+
"## Execution",
|
|
851
|
+
`- Exit code: ${String(exitCode)}`,
|
|
852
|
+
`- Duration ms: ${durationMs}`,
|
|
853
|
+
"",
|
|
854
|
+
"## Stdout",
|
|
855
|
+
"```text",
|
|
856
|
+
stdout.trim() || "(empty)",
|
|
857
|
+
"```",
|
|
858
|
+
"",
|
|
859
|
+
"## Stderr",
|
|
860
|
+
"```text",
|
|
861
|
+
stderr.trim() || "(empty)",
|
|
862
|
+
"```",
|
|
863
|
+
""
|
|
864
|
+
].join("\n");
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// src/commands/delegate.ts
|
|
868
|
+
var import_node_fs5 = require("fs");
|
|
869
|
+
var import_node_path4 = require("path");
|
|
870
|
+
async function runDelegate(options) {
|
|
871
|
+
const store = new WorkflowStore(options.root);
|
|
872
|
+
if (!(0, import_node_fs5.existsSync)(store.configPath)) {
|
|
873
|
+
throw new Error("Missing .agent-workflow/config.json. Run init first.");
|
|
874
|
+
}
|
|
875
|
+
const config = store.readConfig();
|
|
876
|
+
const adapter = new ShellAgyAdapter({
|
|
877
|
+
command: config.agyCommand,
|
|
878
|
+
baseArgs: config.agyArgs
|
|
879
|
+
});
|
|
880
|
+
await runDelegateWithAdapter(options, adapter);
|
|
881
|
+
}
|
|
882
|
+
async function runDelegateWithAdapter(options, adapter) {
|
|
883
|
+
const store = new WorkflowStore(options.root);
|
|
884
|
+
store.ensureBaseStructure();
|
|
885
|
+
const current = store.readState();
|
|
886
|
+
const specContent = (0, import_node_fs5.readFileSync)(options.spec, "utf8");
|
|
887
|
+
store.writeTaskFile(options.task, "SPEC.md", specContent);
|
|
888
|
+
let repairContent = "";
|
|
889
|
+
if (options.repairRequest) {
|
|
890
|
+
repairContent = (0, import_node_fs5.readFileSync)(options.repairRequest, "utf8");
|
|
891
|
+
store.writeTaskFile(options.task, "REPAIR_REQUEST.md", repairContent);
|
|
892
|
+
}
|
|
893
|
+
advanceStateToImplementing2(current);
|
|
894
|
+
current.currentTask = options.task;
|
|
895
|
+
current.currentPhase = "implementation";
|
|
896
|
+
current.nextAction = "Wait for worker execution result";
|
|
897
|
+
current.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
898
|
+
store.writeState(current);
|
|
899
|
+
const workerRulesPath = (0, import_node_path4.join)(options.root, ".antigravity", "WORKER_RULES.md");
|
|
900
|
+
const workerRules = (0, import_node_fs5.existsSync)(workerRulesPath) ? (0, import_node_fs5.readFileSync)(workerRulesPath, "utf8") : "";
|
|
901
|
+
const prompt = buildWorkerPrompt2({
|
|
902
|
+
taskId: options.task,
|
|
903
|
+
workerRules,
|
|
904
|
+
spec: specContent,
|
|
905
|
+
repairRequest: repairContent
|
|
906
|
+
});
|
|
907
|
+
const execution = await adapter.run({
|
|
908
|
+
repoPath: options.root,
|
|
909
|
+
taskId: options.task,
|
|
910
|
+
prompt,
|
|
911
|
+
timeoutMs: options.timeoutMs
|
|
912
|
+
});
|
|
913
|
+
const resultContent = toResultMarkdown2(execution.stdout, execution.stderr, execution.exitCode, execution.durationMs);
|
|
914
|
+
store.writeTaskFile(options.task, "RESULT.md", resultContent);
|
|
915
|
+
current.state = transitionOrThrow(current.state, "VERIFYING" /* VERIFYING */);
|
|
916
|
+
if (!execution.ok) {
|
|
917
|
+
current.state = "BLOCKED" /* BLOCKED */;
|
|
918
|
+
current.blockingIssues = [
|
|
919
|
+
execution.timedOut ? "Worker execution timed out" : `Worker failed with exit code ${execution.exitCode}`
|
|
920
|
+
];
|
|
921
|
+
current.nextAction = "Inspect RESULT.md and decide escalation or retry";
|
|
922
|
+
current.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
923
|
+
store.writeState(current);
|
|
924
|
+
console.log("Worker execution failed or timed out. See RESULT.md");
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
const parsed = parseWorkerResult(execution.stdout);
|
|
928
|
+
applyParsedResultState2(current, parsed);
|
|
929
|
+
current.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
930
|
+
store.writeState(current);
|
|
931
|
+
console.log(`Worker status: ${parsed.status}`);
|
|
932
|
+
console.log(`Summary: ${parsed.summary}`);
|
|
933
|
+
}
|
|
934
|
+
function buildWorkerPrompt2(input) {
|
|
935
|
+
return [
|
|
936
|
+
"You are Antigravity implementation worker.",
|
|
937
|
+
"",
|
|
938
|
+
input.workerRules,
|
|
939
|
+
"",
|
|
940
|
+
`# Task ID
|
|
941
|
+
${input.taskId}`,
|
|
942
|
+
"",
|
|
943
|
+
"# SPEC",
|
|
944
|
+
input.spec,
|
|
945
|
+
input.repairRequest ? "# REPAIR REQUEST\n" + input.repairRequest : "",
|
|
946
|
+
"",
|
|
947
|
+
"Return only concise Implementation Result markdown with status DONE | BLOCKED | FAILED."
|
|
948
|
+
].filter(Boolean).join("\n");
|
|
949
|
+
}
|
|
950
|
+
function applyParsedResultState2(state, result) {
|
|
951
|
+
state.state = transitionOrThrow(state.state, "REVIEWING" /* REVIEWING */);
|
|
952
|
+
if (result.status === "DONE") {
|
|
953
|
+
state.nextAction = "Run review and record PASS/FAIL";
|
|
954
|
+
state.blockingIssues = [];
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
if (result.status === "FAILED") {
|
|
958
|
+
state.state = "REPAIR_REQUIRED" /* REPAIR_REQUIRED */;
|
|
959
|
+
state.repairAttempt += 1;
|
|
960
|
+
state.nextAction = "Create repair request and delegate again";
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
state.state = "ESCALATION_REQUIRED" /* ESCALATION_REQUIRED */;
|
|
964
|
+
state.blockingIssues = ["Worker returned BLOCKED status"];
|
|
965
|
+
state.nextAction = "Resolve blocking decision with user";
|
|
966
|
+
}
|
|
967
|
+
function toResultMarkdown2(stdout, stderr, exitCode, durationMs) {
|
|
968
|
+
return [
|
|
969
|
+
"# Implementation Result",
|
|
970
|
+
"",
|
|
971
|
+
"## Execution",
|
|
972
|
+
`- Exit code: ${String(exitCode)}`,
|
|
973
|
+
`- Duration ms: ${durationMs}`,
|
|
974
|
+
"",
|
|
975
|
+
"## Stdout",
|
|
976
|
+
"```text",
|
|
977
|
+
stdout.trim() || "(empty)",
|
|
978
|
+
"```",
|
|
979
|
+
"",
|
|
980
|
+
"## Stderr",
|
|
981
|
+
"```text",
|
|
982
|
+
stderr.trim() || "(empty)",
|
|
983
|
+
"```",
|
|
984
|
+
""
|
|
985
|
+
].join("\n");
|
|
986
|
+
}
|
|
987
|
+
function advanceStateToImplementing2(snapshot) {
|
|
988
|
+
if (snapshot.state === "IMPLEMENTING" /* IMPLEMENTING */) {
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
if (snapshot.state === "REPAIR_REQUIRED" /* REPAIR_REQUIRED */) {
|
|
992
|
+
snapshot.state = transitionOrThrow(snapshot.state, "IMPLEMENTING" /* IMPLEMENTING */);
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
if (snapshot.state === "READY" /* READY */) {
|
|
996
|
+
snapshot.state = transitionOrThrow(snapshot.state, "IMPLEMENTING" /* IMPLEMENTING */);
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
999
|
+
if (snapshot.state === "PLANNING" /* PLANNING */) {
|
|
1000
|
+
snapshot.state = transitionOrThrow(snapshot.state, "READY" /* READY */);
|
|
1001
|
+
snapshot.state = transitionOrThrow(snapshot.state, "IMPLEMENTING" /* IMPLEMENTING */);
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
if (snapshot.state === "BRAINSTORMING" /* BRAINSTORMING */) {
|
|
1005
|
+
snapshot.state = transitionOrThrow(snapshot.state, "PLANNING" /* PLANNING */);
|
|
1006
|
+
snapshot.state = transitionOrThrow(snapshot.state, "READY" /* READY */);
|
|
1007
|
+
snapshot.state = transitionOrThrow(snapshot.state, "IMPLEMENTING" /* IMPLEMENTING */);
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
if (snapshot.state === "DISCOVERY" /* DISCOVERY */) {
|
|
1011
|
+
snapshot.state = transitionOrThrow(snapshot.state, "BRAINSTORMING" /* BRAINSTORMING */);
|
|
1012
|
+
snapshot.state = transitionOrThrow(snapshot.state, "PLANNING" /* PLANNING */);
|
|
1013
|
+
snapshot.state = transitionOrThrow(snapshot.state, "READY" /* READY */);
|
|
1014
|
+
snapshot.state = transitionOrThrow(snapshot.state, "IMPLEMENTING" /* IMPLEMENTING */);
|
|
1015
|
+
return;
|
|
1016
|
+
}
|
|
1017
|
+
snapshot.state = transitionOrThrow(snapshot.state, "DISCOVERY" /* DISCOVERY */);
|
|
1018
|
+
snapshot.state = transitionOrThrow(snapshot.state, "BRAINSTORMING" /* BRAINSTORMING */);
|
|
1019
|
+
snapshot.state = transitionOrThrow(snapshot.state, "PLANNING" /* PLANNING */);
|
|
1020
|
+
snapshot.state = transitionOrThrow(snapshot.state, "READY" /* READY */);
|
|
1021
|
+
snapshot.state = transitionOrThrow(snapshot.state, "IMPLEMENTING" /* IMPLEMENTING */);
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
// src/commands/doctor.ts
|
|
1025
|
+
var import_node_fs6 = require("fs");
|
|
1026
|
+
var import_node_child_process2 = require("child_process");
|
|
1027
|
+
function runDoctor(options) {
|
|
1028
|
+
const store = new WorkflowStore(options.root);
|
|
1029
|
+
const checks = [];
|
|
1030
|
+
const agyCheck = (0, import_node_child_process2.spawnSync)("sh", ["-lc", "command -v agy"], {
|
|
1031
|
+
cwd: options.root,
|
|
1032
|
+
encoding: "utf8"
|
|
1033
|
+
});
|
|
1034
|
+
checks.push({
|
|
1035
|
+
name: "agy command",
|
|
1036
|
+
ok: agyCheck.status === 0,
|
|
1037
|
+
detail: agyCheck.stdout.trim() || agyCheck.stderr.trim()
|
|
1038
|
+
});
|
|
1039
|
+
checks.push({
|
|
1040
|
+
name: ".agent-workflow directory",
|
|
1041
|
+
ok: (0, import_node_fs6.existsSync)(store.workflowDir)
|
|
1042
|
+
});
|
|
1043
|
+
checks.push({
|
|
1044
|
+
name: "STATE.md",
|
|
1045
|
+
ok: (0, import_node_fs6.existsSync)(store.statePath)
|
|
1046
|
+
});
|
|
1047
|
+
checks.push({
|
|
1048
|
+
name: "config.json",
|
|
1049
|
+
ok: (0, import_node_fs6.existsSync)(store.configPath)
|
|
1050
|
+
});
|
|
1051
|
+
checks.push({
|
|
1052
|
+
name: "AGENTS.md",
|
|
1053
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/AGENTS.md`)
|
|
1054
|
+
});
|
|
1055
|
+
checks.push({
|
|
1056
|
+
name: ".codex/agents/codex.md",
|
|
1057
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/agents/codex.md`)
|
|
1058
|
+
});
|
|
1059
|
+
checks.push({
|
|
1060
|
+
name: ".codex/agents/brainstormer.md",
|
|
1061
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/agents/brainstormer.md`)
|
|
1062
|
+
});
|
|
1063
|
+
checks.push({
|
|
1064
|
+
name: ".codex/agents/planner.md",
|
|
1065
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/agents/planner.md`)
|
|
1066
|
+
});
|
|
1067
|
+
checks.push({
|
|
1068
|
+
name: ".codex/agents/researcher.md",
|
|
1069
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/agents/researcher.md`)
|
|
1070
|
+
});
|
|
1071
|
+
checks.push({
|
|
1072
|
+
name: ".codex/agents/business-analyst.md",
|
|
1073
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/agents/business-analyst.md`)
|
|
1074
|
+
});
|
|
1075
|
+
checks.push({
|
|
1076
|
+
name: ".codex/agents/web-engineer.md",
|
|
1077
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/agents/web-engineer.md`)
|
|
1078
|
+
});
|
|
1079
|
+
checks.push({
|
|
1080
|
+
name: ".codex/agents/mobile-engineer.md",
|
|
1081
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/agents/mobile-engineer.md`)
|
|
1082
|
+
});
|
|
1083
|
+
checks.push({
|
|
1084
|
+
name: ".codex/agents/game-engineer.md",
|
|
1085
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/agents/game-engineer.md`)
|
|
1086
|
+
});
|
|
1087
|
+
checks.push({
|
|
1088
|
+
name: ".codex/skills/codex-workflow.md",
|
|
1089
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/skills/codex-workflow.md`)
|
|
1090
|
+
});
|
|
1091
|
+
checks.push({
|
|
1092
|
+
name: ".codex/skills/brainstorming.md",
|
|
1093
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/skills/brainstorming.md`)
|
|
1094
|
+
});
|
|
1095
|
+
checks.push({
|
|
1096
|
+
name: ".codex/skills/planning.md",
|
|
1097
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/skills/planning.md`)
|
|
1098
|
+
});
|
|
1099
|
+
checks.push({
|
|
1100
|
+
name: ".codex/skills/research.md",
|
|
1101
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/skills/research.md`)
|
|
1102
|
+
});
|
|
1103
|
+
checks.push({
|
|
1104
|
+
name: ".codex/skills/requirements-analysis.md",
|
|
1105
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/skills/requirements-analysis.md`)
|
|
1106
|
+
});
|
|
1107
|
+
checks.push({
|
|
1108
|
+
name: ".codex/skills/web-engineering.md",
|
|
1109
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/skills/web-engineering.md`)
|
|
1110
|
+
});
|
|
1111
|
+
checks.push({
|
|
1112
|
+
name: ".codex/skills/mobile-engineering.md",
|
|
1113
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/skills/mobile-engineering.md`)
|
|
1114
|
+
});
|
|
1115
|
+
checks.push({
|
|
1116
|
+
name: ".codex/skills/game-engineering.md",
|
|
1117
|
+
ok: (0, import_node_fs6.existsSync)(`${options.root}/.codex/skills/game-engineering.md`)
|
|
1118
|
+
});
|
|
1119
|
+
for (const check of checks) {
|
|
1120
|
+
console.log(`${check.ok ? "PASS" : "FAIL"} - ${check.name}`);
|
|
1121
|
+
if (check.detail) {
|
|
1122
|
+
console.log(` ${check.detail}`);
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
const hasFailure = checks.some((check) => !check.ok);
|
|
1126
|
+
if (hasFailure) {
|
|
1127
|
+
process.exitCode = 1;
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
// src/commands/init.ts
|
|
1132
|
+
var import_node_fs7 = require("fs");
|
|
1133
|
+
var import_node_path5 = require("path");
|
|
1134
|
+
var defaultConfig = {
|
|
1135
|
+
agyCommand: "agy",
|
|
1136
|
+
agyArgs: [],
|
|
1137
|
+
maxRepairAttempts: 3
|
|
1138
|
+
};
|
|
1139
|
+
var defaultAgents = `# Codex Runtime Contract
|
|
1140
|
+
|
|
1141
|
+
Codex role: Technical Lead, Architect, Planner, Orchestrator, Reviewer, Verifier.
|
|
1142
|
+
|
|
1143
|
+
Execution order:
|
|
1144
|
+
Understand -> Inspect -> Clarify -> Brainstorm -> Plan -> Delegate -> Review -> Repair -> Verify -> Complete.
|
|
1145
|
+
|
|
1146
|
+
Rules:
|
|
1147
|
+
1. Search before asking.
|
|
1148
|
+
2. If missing context affects architecture/behavior/security/compatibility, stop and ask.
|
|
1149
|
+
3. Do not invent requirements.
|
|
1150
|
+
4. Do not delegate before task spec is complete.
|
|
1151
|
+
5. PASS only after verification and independent review.
|
|
1152
|
+
`;
|
|
1153
|
+
var defaultWorkerRules = `# Antigravity Worker Contract
|
|
1154
|
+
|
|
1155
|
+
You are the implementation worker.
|
|
1156
|
+
|
|
1157
|
+
1. SPEC is the contract.
|
|
1158
|
+
2. REPAIR request is the correction contract.
|
|
1159
|
+
3. Inspect relevant code before editing.
|
|
1160
|
+
4. Implement minimal correct scope.
|
|
1161
|
+
5. Add or update tests.
|
|
1162
|
+
6. Run verification commands.
|
|
1163
|
+
7. Report using Implementation Result contract.
|
|
1164
|
+
8. Return BLOCKED if missing decision/context prevents safe completion.
|
|
1165
|
+
`;
|
|
1166
|
+
var defaultCodexAgent = `# Codex Agent Template
|
|
1167
|
+
|
|
1168
|
+
Role: Technical Lead / Planner / Reviewer
|
|
1169
|
+
|
|
1170
|
+
Use this agent for:
|
|
1171
|
+
- clarifying requirements
|
|
1172
|
+
- decomposing work into phases
|
|
1173
|
+
- reviewing implementation output
|
|
1174
|
+
- deciding PASS / FAIL / BLOCKED
|
|
1175
|
+
|
|
1176
|
+
Rules:
|
|
1177
|
+
1. Keep decisions in markdown artifacts.
|
|
1178
|
+
2. Do not delegate before the spec is complete.
|
|
1179
|
+
3. Prefer the smallest safe next action.
|
|
1180
|
+
`;
|
|
1181
|
+
var brainstormAgent = `# Brainstormer Agent
|
|
1182
|
+
|
|
1183
|
+
Role: Discovery and problem framing.
|
|
1184
|
+
|
|
1185
|
+
Use this agent for:
|
|
1186
|
+
- turning a rough request into a clear problem statement
|
|
1187
|
+
- identifying constraints, assumptions, and unknowns
|
|
1188
|
+
- comparing solution options before planning
|
|
1189
|
+
- preparing the input for planning
|
|
1190
|
+
|
|
1191
|
+
Operating rules:
|
|
1192
|
+
1. Stay in discovery; do not implement.
|
|
1193
|
+
2. Capture only evidence-backed assumptions.
|
|
1194
|
+
3. Prefer short, explicit notes.
|
|
1195
|
+
4. End with concrete questions or a recommendation.
|
|
1196
|
+
|
|
1197
|
+
Output format:
|
|
1198
|
+
- Goal
|
|
1199
|
+
- Context
|
|
1200
|
+
- Constraints
|
|
1201
|
+
- Options
|
|
1202
|
+
- Risks
|
|
1203
|
+
- Open questions
|
|
1204
|
+
- Recommended next step
|
|
1205
|
+
`;
|
|
1206
|
+
var plannerAgent = `# Planner Agent
|
|
1207
|
+
|
|
1208
|
+
Role: Convert a validated brainstorm into an execution plan.
|
|
1209
|
+
|
|
1210
|
+
Use this agent for:
|
|
1211
|
+
- breaking work into phases and tasks
|
|
1212
|
+
- defining acceptance criteria
|
|
1213
|
+
- identifying dependencies and sequencing
|
|
1214
|
+
- preparing the handoff to execution
|
|
1215
|
+
|
|
1216
|
+
Operating rules:
|
|
1217
|
+
1. Use the brainstorm as the source of truth.
|
|
1218
|
+
2. Split work into small, ordered steps.
|
|
1219
|
+
3. Keep the plan testable and recoverable.
|
|
1220
|
+
4. Call out blockers explicitly.
|
|
1221
|
+
|
|
1222
|
+
Output format:
|
|
1223
|
+
- Objective
|
|
1224
|
+
- Scope
|
|
1225
|
+
- Phases
|
|
1226
|
+
- Tasks
|
|
1227
|
+
- Acceptance criteria
|
|
1228
|
+
- Verification
|
|
1229
|
+
- Blockers
|
|
1230
|
+
`;
|
|
1231
|
+
var defaultCodexSkill = `# Codex Skill Template
|
|
1232
|
+
|
|
1233
|
+
Use this skill when the task must be executed through the Codex flow in this kit.
|
|
1234
|
+
|
|
1235
|
+
Workflow:
|
|
1236
|
+
1. Brainstorm
|
|
1237
|
+
2. Plan
|
|
1238
|
+
3. Execute
|
|
1239
|
+
4. Delegate
|
|
1240
|
+
5. Review
|
|
1241
|
+
|
|
1242
|
+
Output artifacts:
|
|
1243
|
+
- BRAINSTORM.md
|
|
1244
|
+
- PLAN.md
|
|
1245
|
+
- EXECUTE.md
|
|
1246
|
+
- RESULT.md
|
|
1247
|
+
- REVIEW.md
|
|
1248
|
+
`;
|
|
1249
|
+
var brainstormingSkill = `# Brainstorming Skill
|
|
1250
|
+
|
|
1251
|
+
Use this skill when you need to transform a vague request into a decision-ready problem statement.
|
|
1252
|
+
|
|
1253
|
+
Workflow:
|
|
1254
|
+
1. Read the spec or request.
|
|
1255
|
+
2. Identify goals, constraints, unknowns, and risks.
|
|
1256
|
+
3. Compare at least two viable approaches.
|
|
1257
|
+
4. Recommend the safest next step.
|
|
1258
|
+
|
|
1259
|
+
Outputs:
|
|
1260
|
+
- BRAINSTORM.md
|
|
1261
|
+
- Decision notes
|
|
1262
|
+
- Open questions
|
|
1263
|
+
|
|
1264
|
+
Do not implement code in this phase.
|
|
1265
|
+
`;
|
|
1266
|
+
var planningSkill = `# Planning Skill
|
|
1267
|
+
|
|
1268
|
+
Use this skill when the request is ready to be turned into an execution plan.
|
|
1269
|
+
|
|
1270
|
+
Workflow:
|
|
1271
|
+
1. Consume the brainstorm output.
|
|
1272
|
+
2. Break the work into phases.
|
|
1273
|
+
3. Add acceptance criteria and verification steps.
|
|
1274
|
+
4. Prepare a clear execution handoff.
|
|
1275
|
+
|
|
1276
|
+
Outputs:
|
|
1277
|
+
- PLAN.md
|
|
1278
|
+
- Task breakdown
|
|
1279
|
+
- Verification checklist
|
|
1280
|
+
- Handoff notes
|
|
1281
|
+
|
|
1282
|
+
Do not delegate implementation until the plan is complete.
|
|
1283
|
+
`;
|
|
1284
|
+
var researcherAgent = `# Researcher Agent
|
|
1285
|
+
|
|
1286
|
+
Role: Deep Technical Research, Spikes, Architecture Benchmarks & Feasibility.
|
|
1287
|
+
|
|
1288
|
+
Use this agent for:
|
|
1289
|
+
- investigating unknown technical domains, new libraries, or unfamiliar APIs
|
|
1290
|
+
- conducting technical spikes and feasibility studies before architectural commitment
|
|
1291
|
+
- comparing competing frameworks, protocols, and third-party services
|
|
1292
|
+
- identifying hidden constraints, license obligations, deprecations, and performance bottlenecks
|
|
1293
|
+
- analyzing state-of-the-art implementations and industry best practices
|
|
1294
|
+
|
|
1295
|
+
Operating rules:
|
|
1296
|
+
1. Search code and documentation before speculating.
|
|
1297
|
+
2. Provide concrete evidence, benchmarks, or citations for claims.
|
|
1298
|
+
3. Compare at least 2 viable approaches with explicit trade-offs (pros/cons/risks).
|
|
1299
|
+
4. Never assume third-party API contracts without verifying current versions.
|
|
1300
|
+
5. Conclude with a definitive, actionable recommendation and a risk mitigation strategy.
|
|
1301
|
+
|
|
1302
|
+
Output format:
|
|
1303
|
+
- Research Objective & Scope
|
|
1304
|
+
- Background & Current State
|
|
1305
|
+
- Evaluated Options (Trade-off Matrix)
|
|
1306
|
+
- Spike / Proof of Concept Findings
|
|
1307
|
+
- Risks & Breaking Changes
|
|
1308
|
+
- Recommended Architecture / Path Forward
|
|
1309
|
+
`;
|
|
1310
|
+
var businessAnalystAgent = `# Business Analyst (BA) Agent
|
|
1311
|
+
|
|
1312
|
+
Role: Requirements Elicitation, User Story Breakdown, Domain Modeling & Acceptance Criteria Engineering.
|
|
1313
|
+
|
|
1314
|
+
Use this agent for:
|
|
1315
|
+
- turning unstructured business requirements or user requests into precise functional specifications
|
|
1316
|
+
- identifying distinct user personas, user journeys, and role-based permissions
|
|
1317
|
+
- uncovering non-obvious edge cases, error scenarios, and business boundary rules
|
|
1318
|
+
- authoring testable acceptance criteria using Gherkin (Given / When / Then) syntax
|
|
1319
|
+
- mapping domain entities, data dictionaries, and state transition lifecycles
|
|
1320
|
+
|
|
1321
|
+
Operating rules:
|
|
1322
|
+
1. Do not invent requirements; clarify ambiguities with explicit questions or assumptions.
|
|
1323
|
+
2. Separate business logic and user intent from technical implementation details.
|
|
1324
|
+
3. Every functional requirement must have at least one testable acceptance criterion.
|
|
1325
|
+
4. Always specify happy path, alternative paths, and negative/failure paths.
|
|
1326
|
+
5. Highlight all dependencies on external systems, legal/compliance rules, and business limits.
|
|
1327
|
+
|
|
1328
|
+
Output format:
|
|
1329
|
+
- Feature Summary & Business Value
|
|
1330
|
+
- User Personas & Permissions
|
|
1331
|
+
- User Stories & Workflows
|
|
1332
|
+
- Functional & Non-Functional Requirements
|
|
1333
|
+
- Edge Cases & Negative Scenarios
|
|
1334
|
+
- Acceptance Criteria (Given/When/Then)
|
|
1335
|
+
- Open Questions & Assumptions
|
|
1336
|
+
`;
|
|
1337
|
+
var webEngineerAgent = `# Web Engineer Agent
|
|
1338
|
+
|
|
1339
|
+
Role: Modern Web Architecture & Engineering Specialist (Frontend, Backend, APIs, Performance).
|
|
1340
|
+
|
|
1341
|
+
Use this agent for:
|
|
1342
|
+
- designing responsive frontend architectures (React, Next.js, Vue, Svelte, Vanilla HTML/CSS/JS)
|
|
1343
|
+
- building resilient backend services and APIs (Node.js/TypeScript, Go, Python, REST, GraphQL, WebSocket)
|
|
1344
|
+
- defining state management, data caching, optimistic UI updates, and server components
|
|
1345
|
+
- enforcing modern web performance (Core Web Vitals: LCP, INP, CLS) and responsive design
|
|
1346
|
+
- securing web applications against XSS, CSRF, SSRF, CORS misconfigurations, and injection attacks
|
|
1347
|
+
- establishing SEO, accessibility (WCAG 2.1 AA, ARIA roles), and progressive enhancement standards
|
|
1348
|
+
|
|
1349
|
+
Operating rules:
|
|
1350
|
+
1. Adhere to repository coding patterns and modern framework idioms (prefer web standards and composable patterns).
|
|
1351
|
+
2. Never hardcode sensitive tokens or environment secrets into client-side bundles.
|
|
1352
|
+
3. Design UI components for responsiveness across mobile, tablet, and desktop breakpoints.
|
|
1353
|
+
4. Keep network waterfalls minimal: optimize bundle size, leverage code splitting and caching headers.
|
|
1354
|
+
5. All interactive UI elements must have unique test identifiers and valid keyboard focus management.
|
|
1355
|
+
|
|
1356
|
+
Output format:
|
|
1357
|
+
- Web Architecture & Tech Stack Details
|
|
1358
|
+
- Component Hierarchy & State Flow
|
|
1359
|
+
- API Contracts & Data Schemas
|
|
1360
|
+
- Routing & Navigation Structure
|
|
1361
|
+
- Performance & Security Constraints
|
|
1362
|
+
- Verification & Test Matrix (Unit, Integration, E2E)
|
|
1363
|
+
`;
|
|
1364
|
+
var mobileEngineerAgent = `# Mobile Engineer Agent
|
|
1365
|
+
|
|
1366
|
+
Role: Mobile Application Architecture & Engineering Specialist (Cross-Platform & Native).
|
|
1367
|
+
|
|
1368
|
+
Use this agent for:
|
|
1369
|
+
- architecting cross-platform apps using Flutter/Dart or React Native/Expo
|
|
1370
|
+
- engineering native iOS applications (Swift, SwiftUI, UIKit, Combine/Async-Await)
|
|
1371
|
+
- engineering native Android applications (Kotlin, Jetpack Compose, Coroutines/Flow)
|
|
1372
|
+
- managing mobile lifecycle states (foreground, background, suspended, terminated)
|
|
1373
|
+
- designing offline-first local storage, SQLite/Room/CoreData/WatermelonDB/Hive, and background sync
|
|
1374
|
+
- handling device hardware integrations: Push notifications, Biometrics, Camera, Geolocation, Bluetooth
|
|
1375
|
+
- configuring native build pipelines, signing, permissions, deep linking, and App Store/Play Store readiness
|
|
1376
|
+
|
|
1377
|
+
Operating rules:
|
|
1378
|
+
1. Respect native operating system guidelines (Apple Human Interface Guidelines and Material Design 3).
|
|
1379
|
+
2. Handle network flakiness gracefully: implement retries, offline caching, and optimistic local state.
|
|
1380
|
+
3. Treat app permissions defensively: request at runtime with clear user rationale and fallback states.
|
|
1381
|
+
4. Avoid main-thread blocking; offload heavy computations and disk I/O to background workers/isolates.
|
|
1382
|
+
5. Account for device fragmentation: test various screen aspect ratios, safe areas, notches, and dark mode.
|
|
1383
|
+
|
|
1384
|
+
Output format:
|
|
1385
|
+
- Target Platform & Architecture (Native iOS/Android, React Native, or Flutter)
|
|
1386
|
+
- State Management & Navigation Hierarchy
|
|
1387
|
+
- Local Storage & Offline Sync Strategy
|
|
1388
|
+
- Native Capabilities & Permission Handling
|
|
1389
|
+
- Device Lifecycle & Memory Considerations
|
|
1390
|
+
- Build, Verification & Device Testing Strategy
|
|
1391
|
+
`;
|
|
1392
|
+
var gameEngineerAgent = `# Game Engineer Agent
|
|
1393
|
+
|
|
1394
|
+
Role: Game Systems Architecture, Gameplay Mechanics & Engine Specialist (Unity, Godot, Cocos Creator).
|
|
1395
|
+
|
|
1396
|
+
Use this agent for:
|
|
1397
|
+
- architecting game systems across major game engines:
|
|
1398
|
+
- Unity: C#, GameObject/Component lifecycle, ScriptableObjects, DOTS/Burst, Addressables
|
|
1399
|
+
- Godot: GDScript / C#, Node tree hierarchy, Scene inheritance, Signals, Resource system
|
|
1400
|
+
- Cocos Creator: TypeScript, Component lifecycle, Prefabs, Canvas/UI, WebGL/HTML5 packaging
|
|
1401
|
+
- developing core gameplay loops, mechanics, player controllers, and input action maps
|
|
1402
|
+
- designing Entity-Component-System (ECS) and data-driven state machines
|
|
1403
|
+
- configuring 2D/3D physics, collision layers, rigid bodies, raycasting, and triggers
|
|
1404
|
+
- managing asset pipelines: sprites, tilemaps, 3D meshes, particle effects, animations, and audio mixers
|
|
1405
|
+
- profiling and optimizing game performance: frame-rate stability (60/120 FPS), draw calls, texture atlases, garbage collection pauses
|
|
1406
|
+
|
|
1407
|
+
Operating rules:
|
|
1408
|
+
1. Keep gameplay logic decoupled from rendering and engine-specific editor scripts where feasible.
|
|
1409
|
+
2. Optimize memory allocations in the hot game loop (Update / _process) to prevent GC spikes.
|
|
1410
|
+
3. Physics updates must run in fixed timesteps (FixedUpdate / _physics_process).
|
|
1411
|
+
4. Manage scene and asset lifecycles strictly to eliminate memory leaks and dangling event listeners.
|
|
1412
|
+
5. Provide deterministic fallback logic and verification tests for core game rules and mathematical calculations.
|
|
1413
|
+
|
|
1414
|
+
Output format:
|
|
1415
|
+
- Game Engine, Version & Render Pipeline Selection
|
|
1416
|
+
- Core Game Loop & Gameplay Mechanics Architecture
|
|
1417
|
+
- Scene / Node Hierarchy & Component Relationships
|
|
1418
|
+
- Physics, Collision Matrix & Input Handling
|
|
1419
|
+
- Asset Management & Performance Budget (Draw calls, Memory, Target FPS)
|
|
1420
|
+
- Verification Checklist & Playtest Strategy
|
|
1421
|
+
`;
|
|
1422
|
+
var researchSkill = `# Technical Research Skill
|
|
1423
|
+
|
|
1424
|
+
Use this skill when tackling technical uncertainty, evaluating new libraries, prototyping spikes, or comparing architectural designs.
|
|
1425
|
+
|
|
1426
|
+
Workflow:
|
|
1427
|
+
1. Frame the Spike: Define the research question, target hypothesis, constraints, and success criteria.
|
|
1428
|
+
2. Explore Existing Solutions: Inspect repository codebase, official documentation, ecosystem libraries, and community benchmarks.
|
|
1429
|
+
3. Compare Alternatives: Benchmark at least 2 distinct approaches across complexity, maintenance, scalability, security, and developer experience.
|
|
1430
|
+
4. Prototype & Validate: Run minimal proof-of-concept tests or sandbox experiments to verify critical assumptions.
|
|
1431
|
+
5. Document & Recommend: Synthesize findings into clear architectural guidance, trade-offs, and an actionable implementation path.
|
|
1432
|
+
|
|
1433
|
+
Outputs:
|
|
1434
|
+
- Research findings artifact (RESEARCH.md or section in BRAINSTORM.md)
|
|
1435
|
+
- Technical comparison matrix
|
|
1436
|
+
- Decision record with trade-offs and rationale
|
|
1437
|
+
- Risk assessment and mitigation plan
|
|
1438
|
+
`;
|
|
1439
|
+
var requirementsAnalysisSkill = `# Requirements Analysis Skill
|
|
1440
|
+
|
|
1441
|
+
Use this skill when translating high-level business goals, user feedback, or feature requests into actionable, testable technical requirements.
|
|
1442
|
+
|
|
1443
|
+
Workflow:
|
|
1444
|
+
1. Clarify Business Intent: Elicit the core user problem, business metrics, and target audience.
|
|
1445
|
+
2. Deconstruct User Journeys: Map end-to-end flows covering happy path, alternative paths, and error scenarios.
|
|
1446
|
+
3. Formulate Acceptance Criteria: Write precise, testable criteria using Gherkin syntax (Given [context], When [action], Then [outcome]).
|
|
1447
|
+
4. Identify Non-Functional Requirements: Specify performance targets, security rules, compliance, and accessibility standards.
|
|
1448
|
+
5. Surface Unknowns: Flag open questions, unconfirmed business logic, and potential edge cases before planning.
|
|
1449
|
+
|
|
1450
|
+
Outputs:
|
|
1451
|
+
- Business requirements specification (REQUIREMENTS.md or section in SPEC.md)
|
|
1452
|
+
- User stories with Gherkin acceptance criteria
|
|
1453
|
+
- Domain entities & data dictionary definitions
|
|
1454
|
+
- Edge case checklist & business validation rules
|
|
1455
|
+
`;
|
|
1456
|
+
var webEngineeringSkill = `# Web Engineering Skill
|
|
1457
|
+
|
|
1458
|
+
Use this skill when designing, implementing, or optimizing fullstack web applications, frontends, APIs, and modern web architectures.
|
|
1459
|
+
|
|
1460
|
+
Workflow:
|
|
1461
|
+
1. Analyze Repository & Tech Stack: Inspect active frameworks (React, Next.js, Vue, Node.js, etc.), state stores, design systems, and package dependencies.
|
|
1462
|
+
2. Design Component & State Flow: Architect clean component boundaries, unidirectional data flow, server/client state segregation, and error boundaries.
|
|
1463
|
+
3. Specify API Contracts: Define type-safe request/response schemas (TypeScript, Zod, OpenAPI, GraphQL) and error handling codes.
|
|
1464
|
+
4. Enforce UX, Performance & Accessibility: Apply responsive layouts, Core Web Vitals optimizations (LCP, INP, CLS), keyboard navigation, and ARIA roles.
|
|
1465
|
+
5. Formulate Verification Matrix: Define unit tests (Vitest/Jest), component tests, and end-to-end integration scenarios (Playwright/Cypress).
|
|
1466
|
+
|
|
1467
|
+
Outputs:
|
|
1468
|
+
- Web implementation plan (PLAN.md with web-specific phase breakdown)
|
|
1469
|
+
- Component hierarchy and data flow diagrams
|
|
1470
|
+
- API schema specifications and endpoint contracts
|
|
1471
|
+
- Performance, security, and accessibility verification checklist
|
|
1472
|
+
`;
|
|
1473
|
+
var mobileEngineeringSkill = `# Mobile Engineering Skill
|
|
1474
|
+
|
|
1475
|
+
Use this skill when developing, refactoring, or optimizing native (iOS Swift, Android Kotlin) and cross-platform (Flutter, React Native) mobile applications.
|
|
1476
|
+
|
|
1477
|
+
Workflow:
|
|
1478
|
+
1. Target Platform & Framework Audit: Inspect whether the app is Flutter, React Native, Swift/SwiftUI, or Kotlin/Jetpack Compose, plus target SDK versions.
|
|
1479
|
+
2. Design Navigation & State Hierarchy: Define screen stacks, tabs, modals, deep linking schemes, and application-wide state management.
|
|
1480
|
+
3. Architect Storage & Offline Capability: Specify local caching, SQLite / Room / CoreData / WatermelonDB schemas, and background sync strategies.
|
|
1481
|
+
4. Integrate Native Device Capabilities: Structure permission flows, push notifications, hardware access, and platform bridges/plugins defensively.
|
|
1482
|
+
5. Formulate Verification & Emulation Matrix: Specify unit tests, widget/component tests, and platform-specific simulator/device build commands.
|
|
1483
|
+
|
|
1484
|
+
Outputs:
|
|
1485
|
+
- Mobile technical implementation plan
|
|
1486
|
+
- Screen navigation and state transition map
|
|
1487
|
+
- Local database schema and offline sync rules
|
|
1488
|
+
- Platform permission checklist and native configuration guidelines
|
|
1489
|
+
`;
|
|
1490
|
+
var gameEngineeringSkill = `# Game Engineering Skill
|
|
1491
|
+
|
|
1492
|
+
Use this skill when developing, refactoring, or optimizing games across Unity, Godot, or Cocos Creator engines.
|
|
1493
|
+
|
|
1494
|
+
Workflow:
|
|
1495
|
+
1. Engine & Architecture Assessment: Identify game engine (Unity C#, Godot GDScript/C#, Cocos Creator TypeScript), rendering pipeline, and target platforms (PC, Mobile, WebGL, Console).
|
|
1496
|
+
2. Gameplay Loops & Mechanics Design: Structure the primary game loop, player controllers, state machines, and event dispatchers.
|
|
1497
|
+
3. Scene, Node & Entity Architecture: Establish clean scene hierarchies, prefabs/nodes composition, and decouple gameplay logic from presentation.
|
|
1498
|
+
4. Physics, Collision & Input Integration: Configure collision layers/masks, rigid body properties, input action maps, and fixed-timestep calculations.
|
|
1499
|
+
5. Optimization & Performance Profiling: Audit hot loop allocations, draw call batching, texture atlases, object pooling, and target frame rate (60/120 FPS).
|
|
1500
|
+
|
|
1501
|
+
Outputs:
|
|
1502
|
+
- Game architecture & mechanics implementation plan
|
|
1503
|
+
- Scene hierarchy and component relationship specification
|
|
1504
|
+
- Physics collision matrix and input mapping configuration
|
|
1505
|
+
- Object pooling and memory optimization checklist
|
|
1506
|
+
- Verification plan with deterministic math/logic tests and playtest criteria
|
|
1507
|
+
`;
|
|
1508
|
+
function runInit(options) {
|
|
1509
|
+
const store = new WorkflowStore(options.root);
|
|
1510
|
+
store.ensureBaseStructure();
|
|
1511
|
+
const architecturePath = (0, import_node_path5.join)(store.workflowDir, "ARCHITECTURE.md");
|
|
1512
|
+
const projectPath = (0, import_node_path5.join)(store.workflowDir, "PROJECT.md");
|
|
1513
|
+
const decisionsPath = (0, import_node_path5.join)(store.workflowDir, "DECISIONS.md");
|
|
1514
|
+
const agentsPath = (0, import_node_path5.join)(options.root, "AGENTS.md");
|
|
1515
|
+
const codexDir = (0, import_node_path5.join)(options.root, ".codex");
|
|
1516
|
+
const codexAgentsDir = (0, import_node_path5.join)(codexDir, "agents");
|
|
1517
|
+
const codexSkillsDir = (0, import_node_path5.join)(codexDir, "skills");
|
|
1518
|
+
const workerDir = (0, import_node_path5.join)(options.root, ".antigravity");
|
|
1519
|
+
const workerPath = (0, import_node_path5.join)(workerDir, "WORKER_RULES.md");
|
|
1520
|
+
(0, import_node_fs7.mkdirSync)(codexDir, { recursive: true });
|
|
1521
|
+
(0, import_node_fs7.mkdirSync)(codexAgentsDir, { recursive: true });
|
|
1522
|
+
(0, import_node_fs7.mkdirSync)(codexSkillsDir, { recursive: true });
|
|
1523
|
+
if (!(0, import_node_fs7.existsSync)(workerDir)) {
|
|
1524
|
+
(0, import_node_fs7.mkdirSync)(workerDir, { recursive: true });
|
|
1525
|
+
(0, import_node_fs7.writeFileSync)((0, import_node_path5.join)(workerDir, ".gitkeep"), "", "utf8");
|
|
1526
|
+
}
|
|
1527
|
+
writeIfMissing(projectPath, "# Project\n\nDescribe project-level goals and boundaries.\n", options.force);
|
|
1528
|
+
writeIfMissing(
|
|
1529
|
+
architecturePath,
|
|
1530
|
+
"# Architecture\n\nDocument Codex brain, bridge, worker, state, and review loop architecture.\n",
|
|
1531
|
+
options.force
|
|
1532
|
+
);
|
|
1533
|
+
writeIfMissing(decisionsPath, "# Decisions\n\nLog only material architectural/product decisions.\n", options.force);
|
|
1534
|
+
writeIfMissing((0, import_node_path5.join)(codexAgentsDir, "brainstormer.md"), brainstormAgent, options.force);
|
|
1535
|
+
writeIfMissing((0, import_node_path5.join)(codexAgentsDir, "planner.md"), plannerAgent, options.force);
|
|
1536
|
+
writeIfMissing((0, import_node_path5.join)(codexAgentsDir, "codex.md"), defaultCodexAgent, options.force);
|
|
1537
|
+
writeIfMissing((0, import_node_path5.join)(codexAgentsDir, "researcher.md"), researcherAgent, options.force);
|
|
1538
|
+
writeIfMissing((0, import_node_path5.join)(codexAgentsDir, "business-analyst.md"), businessAnalystAgent, options.force);
|
|
1539
|
+
writeIfMissing((0, import_node_path5.join)(codexAgentsDir, "web-engineer.md"), webEngineerAgent, options.force);
|
|
1540
|
+
writeIfMissing((0, import_node_path5.join)(codexAgentsDir, "mobile-engineer.md"), mobileEngineerAgent, options.force);
|
|
1541
|
+
writeIfMissing((0, import_node_path5.join)(codexAgentsDir, "game-engineer.md"), gameEngineerAgent, options.force);
|
|
1542
|
+
writeIfMissing((0, import_node_path5.join)(codexSkillsDir, "brainstorming.md"), brainstormingSkill, options.force);
|
|
1543
|
+
writeIfMissing((0, import_node_path5.join)(codexSkillsDir, "planning.md"), planningSkill, options.force);
|
|
1544
|
+
writeIfMissing((0, import_node_path5.join)(codexSkillsDir, "codex-workflow.md"), defaultCodexSkill, options.force);
|
|
1545
|
+
writeIfMissing((0, import_node_path5.join)(codexSkillsDir, "research.md"), researchSkill, options.force);
|
|
1546
|
+
writeIfMissing((0, import_node_path5.join)(codexSkillsDir, "requirements-analysis.md"), requirementsAnalysisSkill, options.force);
|
|
1547
|
+
writeIfMissing((0, import_node_path5.join)(codexSkillsDir, "web-engineering.md"), webEngineeringSkill, options.force);
|
|
1548
|
+
writeIfMissing((0, import_node_path5.join)(codexSkillsDir, "mobile-engineering.md"), mobileEngineeringSkill, options.force);
|
|
1549
|
+
writeIfMissing((0, import_node_path5.join)(codexSkillsDir, "game-engineering.md"), gameEngineeringSkill, options.force);
|
|
1550
|
+
if (!(0, import_node_fs7.existsSync)(store.statePath) || options.force) {
|
|
1551
|
+
const state = defaultState();
|
|
1552
|
+
state.state = "IDLE" /* IDLE */;
|
|
1553
|
+
state.nextAction = "Start discovery for a feature request";
|
|
1554
|
+
store.writeState(state);
|
|
1555
|
+
}
|
|
1556
|
+
if (!(0, import_node_fs7.existsSync)(store.configPath) || options.force) {
|
|
1557
|
+
store.writeConfig(defaultConfig);
|
|
1558
|
+
}
|
|
1559
|
+
writeIfMissing(agentsPath, defaultAgents, options.force);
|
|
1560
|
+
writeIfMissing(workerPath, defaultWorkerRules, options.force);
|
|
1561
|
+
console.log("Initialized codex-antigravity kit");
|
|
1562
|
+
console.log(`Workflow dir: ${store.workflowDir}`);
|
|
1563
|
+
}
|
|
1564
|
+
function writeIfMissing(path, content, force) {
|
|
1565
|
+
if (!(0, import_node_fs7.existsSync)(path) || force) {
|
|
1566
|
+
(0, import_node_fs7.writeFileSync)(path, content, "utf8");
|
|
1567
|
+
return;
|
|
1568
|
+
}
|
|
1569
|
+
const current = (0, import_node_fs7.readFileSync)(path, "utf8");
|
|
1570
|
+
if (current.trim().length === 0) {
|
|
1571
|
+
(0, import_node_fs7.writeFileSync)(path, content, "utf8");
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
// src/commands/plan.ts
|
|
1576
|
+
var import_node_fs8 = require("fs");
|
|
1577
|
+
function runPlan(options) {
|
|
1578
|
+
const store = new WorkflowStore(options.root);
|
|
1579
|
+
store.ensureBaseStructure();
|
|
1580
|
+
let spec = "";
|
|
1581
|
+
if (options.spec && (0, import_node_fs8.existsSync)(options.spec)) {
|
|
1582
|
+
spec = (0, import_node_fs8.readFileSync)(options.spec, "utf8");
|
|
1583
|
+
store.writeTaskFile(options.task, "SPEC.md", spec);
|
|
1584
|
+
} else if (store.hasTaskFile(options.task, "SPEC.md")) {
|
|
1585
|
+
spec = store.readTaskFile(options.task, "SPEC.md");
|
|
1586
|
+
} else {
|
|
1587
|
+
spec = `# Task ${options.task}
|
|
1588
|
+
`;
|
|
1589
|
+
}
|
|
1590
|
+
const brainstormContent = store.hasTaskFile(options.task, "BRAINSTORM.md") ? store.readTaskFile(options.task, "BRAINSTORM.md") : "# Brainstorm\n\nRun brainstorm first.\n";
|
|
1591
|
+
const agentResolution = detectAgent({
|
|
1592
|
+
root: options.root,
|
|
1593
|
+
content: `${spec}
|
|
1594
|
+
${brainstormContent}`,
|
|
1595
|
+
explicitAgent: options.agent
|
|
1596
|
+
});
|
|
1597
|
+
console.log(`[Agent Router] Assigned: ${agentResolution.agent.name} (${agentResolution.agent.id})`);
|
|
1598
|
+
console.log(`[Agent Router] Reason: ${agentResolution.reason}`);
|
|
1599
|
+
const plan = buildPlanMarkdown(options.task, spec, brainstormContent, agentResolution);
|
|
1600
|
+
store.writeTaskFile(options.task, "PLAN.md", plan);
|
|
1601
|
+
const state = store.readState();
|
|
1602
|
+
state.state = "BRAINSTORMING" /* BRAINSTORMING */;
|
|
1603
|
+
state.state = "PLANNING" /* PLANNING */;
|
|
1604
|
+
state.currentTask = options.task;
|
|
1605
|
+
state.currentPhase = "planning";
|
|
1606
|
+
state.nextAction = `Run execute command to implement work described in PLAN.md for task ${options.task}`;
|
|
1607
|
+
state.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1608
|
+
store.writeState(state);
|
|
1609
|
+
console.log(plan);
|
|
1610
|
+
}
|
|
1611
|
+
function buildPlanMarkdown(task, spec, brainstorm, agentResolution) {
|
|
1612
|
+
return [
|
|
1613
|
+
"# Plan",
|
|
1614
|
+
"",
|
|
1615
|
+
`Task: ${task}`,
|
|
1616
|
+
`Assigned Agent: ${agentResolution.agent.name} (${agentResolution.agent.id})`,
|
|
1617
|
+
`Agent Selection: ${agentResolution.reason}`,
|
|
1618
|
+
"",
|
|
1619
|
+
"## Objective",
|
|
1620
|
+
"Convert brainstorm into actionable phases and tasks.",
|
|
1621
|
+
"",
|
|
1622
|
+
"## Context",
|
|
1623
|
+
brainstorm.trim(),
|
|
1624
|
+
"",
|
|
1625
|
+
"## Requirements",
|
|
1626
|
+
spec.trim(),
|
|
1627
|
+
"",
|
|
1628
|
+
"## Phases",
|
|
1629
|
+
"### Phase 1 \u2014 Scope and Contracts",
|
|
1630
|
+
"- Confirm task boundaries",
|
|
1631
|
+
"- Capture expected behavior",
|
|
1632
|
+
"",
|
|
1633
|
+
"### Phase 2 \u2014 Worker Execution",
|
|
1634
|
+
"- Send spec to Antigravity",
|
|
1635
|
+
"- Collect implementation result",
|
|
1636
|
+
"",
|
|
1637
|
+
"### Phase 3 \u2014 Review and Repair",
|
|
1638
|
+
"- Codex reviews diff and output",
|
|
1639
|
+
"- Produce repair request if needed",
|
|
1640
|
+
"",
|
|
1641
|
+
"## Acceptance Criteria",
|
|
1642
|
+
"- Brainstorm artifact exists",
|
|
1643
|
+
"- Plan artifact exists",
|
|
1644
|
+
"- Execute artifact can be generated",
|
|
1645
|
+
"- Workflow remains recoverable from disk",
|
|
1646
|
+
"",
|
|
1647
|
+
"## Verification",
|
|
1648
|
+
"- npm test",
|
|
1649
|
+
"- npm run build",
|
|
1650
|
+
"- npx codex-antigravity-kit doctor",
|
|
1651
|
+
""
|
|
1652
|
+
].join("\n");
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
// src/commands/review.ts
|
|
1656
|
+
var import_node_fs9 = require("fs");
|
|
1657
|
+
|
|
1658
|
+
// src/core/repair-loop.ts
|
|
1659
|
+
var RepairLoop = class {
|
|
1660
|
+
constructor(maxAttempts) {
|
|
1661
|
+
this.maxAttempts = maxAttempts;
|
|
1662
|
+
if (maxAttempts < 1) {
|
|
1663
|
+
throw new Error("maxAttempts must be >= 1");
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
maxAttempts;
|
|
1667
|
+
canRetry(currentAttempt) {
|
|
1668
|
+
return currentAttempt < this.maxAttempts;
|
|
1669
|
+
}
|
|
1670
|
+
nextAttempt(currentAttempt) {
|
|
1671
|
+
return currentAttempt + 1;
|
|
1672
|
+
}
|
|
1673
|
+
needsEscalation(currentAttempt) {
|
|
1674
|
+
return !this.canRetry(currentAttempt);
|
|
1675
|
+
}
|
|
1676
|
+
};
|
|
1677
|
+
|
|
1678
|
+
// src/commands/review.ts
|
|
1679
|
+
function runReview(options) {
|
|
1680
|
+
const store = new WorkflowStore(options.root);
|
|
1681
|
+
const state = store.readState();
|
|
1682
|
+
const config = store.readConfig();
|
|
1683
|
+
const loop = new RepairLoop(config.maxRepairAttempts);
|
|
1684
|
+
const reviewContent = options.reviewFile ? (0, import_node_fs9.readFileSync)(options.reviewFile, "utf8") : `# Review
|
|
1685
|
+
|
|
1686
|
+
Outcome: ${options.outcome}
|
|
1687
|
+
`;
|
|
1688
|
+
store.writeTaskFile(options.task, "REVIEW.md", reviewContent);
|
|
1689
|
+
state.currentTask = options.task;
|
|
1690
|
+
state.reviewAttempt += 1;
|
|
1691
|
+
if (options.outcome === "PASS") {
|
|
1692
|
+
state.state = "COMPLETED" /* COMPLETED */;
|
|
1693
|
+
state.nextAction = "Task completed. Return to IDLE when ready.";
|
|
1694
|
+
state.blockingIssues = [];
|
|
1695
|
+
} else if (options.outcome === "BLOCKED") {
|
|
1696
|
+
state.state = "ESCALATION_REQUIRED" /* ESCALATION_REQUIRED */;
|
|
1697
|
+
state.nextAction = "Escalate blocking issue to user";
|
|
1698
|
+
state.blockingIssues = ["Reviewer marked task as BLOCKED"];
|
|
1699
|
+
} else {
|
|
1700
|
+
state.repairAttempt += 1;
|
|
1701
|
+
if (loop.needsEscalation(state.repairAttempt)) {
|
|
1702
|
+
state.state = "ESCALATION_REQUIRED" /* ESCALATION_REQUIRED */;
|
|
1703
|
+
state.nextAction = "Repair attempts exceeded limit. Escalate to user.";
|
|
1704
|
+
state.blockingIssues = [
|
|
1705
|
+
`Max repair attempts exceeded (${config.maxRepairAttempts})`
|
|
1706
|
+
];
|
|
1707
|
+
} else {
|
|
1708
|
+
state.state = "REPAIR_REQUIRED" /* REPAIR_REQUIRED */;
|
|
1709
|
+
state.nextAction = "Prepare targeted repair request and delegate again";
|
|
1710
|
+
state.blockingIssues = [];
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
state.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1714
|
+
store.writeState(state);
|
|
1715
|
+
console.log(`Review outcome recorded: ${options.outcome}`);
|
|
1716
|
+
console.log(`State is now: ${state.state}`);
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
// src/commands/status.ts
|
|
1720
|
+
function runStatus(options) {
|
|
1721
|
+
const store = new WorkflowStore(options.root);
|
|
1722
|
+
const state = store.readState();
|
|
1723
|
+
console.log("Current workflow status");
|
|
1724
|
+
console.log(`State: ${state.state}`);
|
|
1725
|
+
console.log(`Current phase: ${state.currentPhase}`);
|
|
1726
|
+
console.log(`Current task: ${state.currentTask}`);
|
|
1727
|
+
console.log(`Review attempt: ${state.reviewAttempt}`);
|
|
1728
|
+
console.log(`Repair attempt: ${state.repairAttempt}`);
|
|
1729
|
+
console.log(`Next action: ${state.nextAction}`);
|
|
1730
|
+
console.log(`Updated at: ${state.updatedAt}`);
|
|
1731
|
+
if (state.blockingIssues.length > 0) {
|
|
1732
|
+
console.log("Blocking issues:");
|
|
1733
|
+
for (const issue of state.blockingIssues) {
|
|
1734
|
+
console.log(`- ${issue}`);
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
// src/cli.ts
|
|
1740
|
+
var program = new import_commander.Command();
|
|
1741
|
+
program.name("codex-antigravity-kit").description("Codex brain + Antigravity worker orchestration kit").version("0.1.0");
|
|
1742
|
+
program.command("init").option("--root <path>", "Project root", process.cwd()).option("--force", "Overwrite existing kit files", false).action((options) => {
|
|
1743
|
+
runInit({ root: (0, import_node_path6.resolve)(options.root), force: options.force });
|
|
1744
|
+
});
|
|
1745
|
+
program.command("doctor").option("--root <path>", "Project root", process.cwd()).action((options) => {
|
|
1746
|
+
runDoctor({ root: (0, import_node_path6.resolve)(options.root) });
|
|
1747
|
+
});
|
|
1748
|
+
program.command("status").option("--root <path>", "Project root", process.cwd()).action((options) => {
|
|
1749
|
+
runStatus({ root: (0, import_node_path6.resolve)(options.root) });
|
|
1750
|
+
});
|
|
1751
|
+
program.command("brainstorm").requiredOption("--task <id>", "Task ID").option("--spec <path>", "Path to task SPEC markdown file").option("--prompt <text>", "Task specification prompt text").option("--agent <name>", "Explicit agent override (web-engineer, mobile-engineer, game-engineer, researcher, business-analyst, codex)").option("--root <path>", "Project root", process.cwd()).action((options) => {
|
|
1752
|
+
runBrainstorm({
|
|
1753
|
+
root: (0, import_node_path6.resolve)(options.root),
|
|
1754
|
+
task: options.task,
|
|
1755
|
+
spec: options.spec ? (0, import_node_path6.resolve)(options.spec) : void 0,
|
|
1756
|
+
prompt: options.prompt,
|
|
1757
|
+
agent: options.agent
|
|
1758
|
+
});
|
|
1759
|
+
});
|
|
1760
|
+
program.command("plan").requiredOption("--task <id>", "Task ID").option("--spec <path>", "Path to task SPEC markdown file").option("--agent <name>", "Explicit agent override").option("--root <path>", "Project root", process.cwd()).action((options) => {
|
|
1761
|
+
runPlan({
|
|
1762
|
+
root: (0, import_node_path6.resolve)(options.root),
|
|
1763
|
+
task: options.task,
|
|
1764
|
+
spec: options.spec ? (0, import_node_path6.resolve)(options.spec) : void 0,
|
|
1765
|
+
agent: options.agent
|
|
1766
|
+
});
|
|
1767
|
+
});
|
|
1768
|
+
program.command("execute").requiredOption("--task <id>", "Task ID").option("--plan <path>", "Path to plan markdown file").option("--file <path>", "Path to markdown description file to execute").option("--spec <path>", "Path to task SPEC markdown file").option("--agent <name>", "Explicit agent override").option("--repair-request <path>", "Path to repair request markdown").option("--timeout-ms <number>", "Worker timeout in ms", "600000").option("--root <path>", "Project root", process.cwd()).action(
|
|
1769
|
+
async (options) => {
|
|
1770
|
+
await runExecute({
|
|
1771
|
+
root: (0, import_node_path6.resolve)(options.root),
|
|
1772
|
+
task: options.task,
|
|
1773
|
+
plan: options.plan ? (0, import_node_path6.resolve)(options.plan) : void 0,
|
|
1774
|
+
file: options.file ? (0, import_node_path6.resolve)(options.file) : void 0,
|
|
1775
|
+
spec: options.spec ? (0, import_node_path6.resolve)(options.spec) : void 0,
|
|
1776
|
+
agent: options.agent,
|
|
1777
|
+
repairRequest: options.repairRequest ? (0, import_node_path6.resolve)(options.repairRequest) : void 0,
|
|
1778
|
+
timeoutMs: Number(options.timeoutMs)
|
|
1779
|
+
});
|
|
1780
|
+
}
|
|
1781
|
+
);
|
|
1782
|
+
program.command("delegate").requiredOption("--task <id>", "Task ID").requiredOption("--spec <path>", "Path to task SPEC markdown file").option("--repair-request <path>", "Path to repair request markdown").option("--timeout-ms <number>", "Worker timeout in ms", "600000").option("--root <path>", "Project root", process.cwd()).action(
|
|
1783
|
+
async (options) => {
|
|
1784
|
+
await runDelegate({
|
|
1785
|
+
root: (0, import_node_path6.resolve)(options.root),
|
|
1786
|
+
task: options.task,
|
|
1787
|
+
spec: (0, import_node_path6.resolve)(options.spec),
|
|
1788
|
+
repairRequest: options.repairRequest ? (0, import_node_path6.resolve)(options.repairRequest) : void 0,
|
|
1789
|
+
timeoutMs: Number(options.timeoutMs)
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1792
|
+
);
|
|
1793
|
+
program.command("review").requiredOption("--task <id>", "Task ID").requiredOption("--outcome <value>", "PASS | FAIL | BLOCKED").option("--review-file <path>", "Path to review markdown").option("--root <path>", "Project root", process.cwd()).action((options) => {
|
|
1794
|
+
const outcome = options.outcome.toUpperCase();
|
|
1795
|
+
if (!["PASS", "FAIL", "BLOCKED"].includes(outcome)) {
|
|
1796
|
+
throw new Error("--outcome must be PASS, FAIL, or BLOCKED");
|
|
1797
|
+
}
|
|
1798
|
+
runReview({
|
|
1799
|
+
root: (0, import_node_path6.resolve)(options.root),
|
|
1800
|
+
task: options.task,
|
|
1801
|
+
outcome,
|
|
1802
|
+
reviewFile: options.reviewFile ? (0, import_node_path6.resolve)(options.reviewFile) : void 0
|
|
1803
|
+
});
|
|
1804
|
+
});
|
|
1805
|
+
program.parseAsync(process.argv).catch((error) => {
|
|
1806
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
1807
|
+
process.exitCode = 1;
|
|
1808
|
+
});
|