project-iris 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/README.md +384 -0
  2. package/dist/bridge/connector-factory.js +27 -0
  3. package/dist/bridge/connectors/antigravity-connector.js +18 -0
  4. package/dist/bridge/connectors/cursor-connector.js +31 -0
  5. package/dist/bridge/connectors/vscode-connector.js +31 -0
  6. package/dist/bridge/connectors/windsurf-connector.js +23 -0
  7. package/dist/bridge/filesystem-connector.js +100 -0
  8. package/dist/bridge/types.js +10 -0
  9. package/dist/cli.js +30 -0
  10. package/dist/commands/ask.js +232 -0
  11. package/dist/commands/bridge.js +259 -0
  12. package/dist/commands/develop.js +108 -0
  13. package/dist/commands/doctor.js +102 -0
  14. package/dist/commands/install.js +57 -0
  15. package/dist/commands/pack.js +27 -0
  16. package/dist/commands/phase.js +38 -0
  17. package/dist/commands/run.js +17 -0
  18. package/dist/commands/status.js +105 -0
  19. package/dist/commands/uninstall.js +12 -0
  20. package/dist/commands/validate.js +87 -0
  21. package/dist/iris/artifact-checker.js +78 -0
  22. package/dist/iris/fixer.js +143 -0
  23. package/dist/iris/guard.js +38 -0
  24. package/dist/iris/include.js +49 -0
  25. package/dist/iris/installer.js +269 -0
  26. package/dist/iris/manifest.js +54 -0
  27. package/dist/iris/packer.js +303 -0
  28. package/dist/iris/policy.js +28 -0
  29. package/dist/iris/report.js +53 -0
  30. package/dist/iris/resolver.js +63 -0
  31. package/dist/iris/router.js +114 -0
  32. package/dist/iris/routes.js +20 -0
  33. package/dist/iris/run-state.js +143 -0
  34. package/dist/iris/state.js +85 -0
  35. package/dist/iris/uninstaller.js +166 -0
  36. package/dist/iris/validator.js +329 -0
  37. package/dist/lib.js +96 -0
  38. package/dist/utils/exit-codes.js +7 -0
  39. package/dist/workflows/bolt-execution.js +238 -0
  40. package/dist/workflows/bolt-plan.js +192 -0
  41. package/dist/workflows/intent-inception.js +188 -0
  42. package/package.json +41 -0
  43. package/src/iris_bundle/.iris/aidlc/README.md +16 -0
  44. package/src/iris_bundle/.iris/aidlc/agents/iris-construction-agent.md +35 -0
  45. package/src/iris_bundle/.iris/aidlc/agents/iris-inception-agent.md +30 -0
  46. package/src/iris_bundle/.iris/aidlc/agents/iris-master-agent.md +35 -0
  47. package/src/iris_bundle/.iris/aidlc/agents/iris-operations-agent.md +29 -0
  48. package/src/iris_bundle/.iris/aidlc/commands/iris-construction-agent.md +18 -0
  49. package/src/iris_bundle/.iris/aidlc/commands/iris-inception-agent.md +18 -0
  50. package/src/iris_bundle/.iris/aidlc/commands/iris-master-agent.md +18 -0
  51. package/src/iris_bundle/.iris/aidlc/commands/iris-operations-agent.md +18 -0
  52. package/src/iris_bundle/.iris/aidlc/context/context-map.md +25 -0
  53. package/src/iris_bundle/.iris/aidlc/context/exclusion-rules.md +13 -0
  54. package/src/iris_bundle/.iris/aidlc/context/load-order.md +25 -0
  55. package/src/iris_bundle/.iris/aidlc/memory/intent-rules.md +9 -0
  56. package/src/iris_bundle/.iris/aidlc/memory/log-rules.md +5 -0
  57. package/src/iris_bundle/.iris/aidlc/memory/memory-bank.yaml +39 -0
  58. package/src/iris_bundle/.iris/aidlc/memory/unit-rules.md +9 -0
  59. package/src/iris_bundle/.iris/aidlc/quick-start.md +24 -0
  60. package/src/iris_bundle/.iris/aidlc/skills/execution/implementation.md +14 -0
  61. package/src/iris_bundle/.iris/aidlc/skills/execution/refactoring.md +13 -0
  62. package/src/iris_bundle/.iris/aidlc/skills/execution/scaffold-generation.md +15 -0
  63. package/src/iris_bundle/.iris/aidlc/skills/governance/escalation.md +13 -0
  64. package/src/iris_bundle/.iris/aidlc/skills/governance/quality-gates.md +14 -0
  65. package/src/iris_bundle/.iris/aidlc/skills/governance/stop-conditions.md +11 -0
  66. package/src/iris_bundle/.iris/aidlc/skills/reasoning/decomposition.md +23 -0
  67. package/src/iris_bundle/.iris/aidlc/skills/reasoning/risk-analysis.md +14 -0
  68. package/src/iris_bundle/.iris/aidlc/skills/reasoning/verification.md +21 -0
  69. package/src/iris_bundle/.iris/aidlc/standards/artifacts-registry.md +38 -0
  70. package/src/iris_bundle/.iris/aidlc/standards/decision-logging.md +16 -0
  71. package/src/iris_bundle/.iris/aidlc/standards/doctrine-structure.md +31 -0
  72. package/src/iris_bundle/.iris/aidlc/standards/documentation-rules.md +15 -0
  73. package/src/iris_bundle/.iris/aidlc/standards/file-structure.md +21 -0
  74. package/src/iris_bundle/.iris/aidlc/standards/naming-conventions.md +18 -0
  75. package/src/iris_bundle/.iris/aidlc/standards/phases-and-gates.md +25 -0
  76. package/src/iris_bundle/.iris/aidlc/standards/routes-and-routing.md +35 -0
  77. package/src/iris_bundle/.iris/aidlc/standards/tool-wrappers.md +32 -0
  78. package/src/iris_bundle/.iris/aidlc/templates/bolt.md +23 -0
  79. package/src/iris_bundle/.iris/aidlc/templates/doctrine-doc-template.md +33 -0
  80. package/src/iris_bundle/.iris/aidlc/templates/intent.md +23 -0
  81. package/src/iris_bundle/.iris/aidlc/templates/log.md +24 -0
  82. package/src/iris_bundle/.iris/aidlc/templates/review.md +21 -0
  83. package/src/iris_bundle/.iris/aidlc/templates/unit.md +31 -0
  84. package/src/iris_bundle/.iris/aidlc/validation/failure-modes.md +16 -0
  85. package/src/iris_bundle/.iris/aidlc/validation/phase-preconditions.md +21 -0
  86. package/src/iris_bundle/.iris/aidlc/validation/quality-checklist.md +20 -0
  87. package/src/iris_bundle/.iris/policy.yaml +27 -0
  88. package/src/iris_bundle/.iris/routes.yaml +98 -0
  89. package/src/iris_bundle/.iris/state.yaml +7 -0
  90. package/src/iris_bundle/.iris/tools/antigravity/.antigravity/knowledge/IRIS.md +6 -0
  91. package/src/iris_bundle/.iris/tools/antigravity/.antigravity/workflows/iris-construction-agent.md +25 -0
  92. package/src/iris_bundle/.iris/tools/antigravity/.antigravity/workflows/iris-inception-agent.md +25 -0
  93. package/src/iris_bundle/.iris/tools/antigravity/.antigravity/workflows/iris-master-agent.md +25 -0
  94. package/src/iris_bundle/.iris/tools/antigravity/.antigravity/workflows/iris-operations-agent.md +25 -0
  95. package/src/iris_bundle/.iris/tools/claude/.claude/claude.md +9 -0
  96. package/src/iris_bundle/.iris/tools/claude/.claude/commands/compare-specs.md +203 -0
  97. package/src/iris_bundle/.iris/tools/claude/.claude/commands/iris-construction-agent.md +25 -0
  98. package/src/iris_bundle/.iris/tools/claude/.claude/commands/iris-inception-agent.md +25 -0
  99. package/src/iris_bundle/.iris/tools/claude/.claude/commands/iris-master-agent.md +25 -0
  100. package/src/iris_bundle/.iris/tools/claude/.claude/commands/iris-operations-agent.md +25 -0
  101. package/src/iris_bundle/.iris/tools/codex/AGENTS.md +15 -0
  102. package/src/iris_bundle/.iris/tools/cursor/.cursor/commands/iris-construction-agent.md +25 -0
  103. package/src/iris_bundle/.iris/tools/cursor/.cursor/commands/iris-inception-agent.md +25 -0
  104. package/src/iris_bundle/.iris/tools/cursor/.cursor/commands/iris-master-agent.md +25 -0
  105. package/src/iris_bundle/.iris/tools/cursor/.cursor/commands/iris-operations-agent.md +25 -0
  106. package/src/iris_bundle/.iris/tools/gemini/.gemini/commands/iris-construction-agent.toml +29 -0
  107. package/src/iris_bundle/.iris/tools/gemini/.gemini/commands/iris-inception-agent.toml +29 -0
  108. package/src/iris_bundle/.iris/tools/gemini/.gemini/commands/iris-master-agent.toml +29 -0
  109. package/src/iris_bundle/.iris/tools/gemini/.gemini/commands/iris-operations-agent.toml +29 -0
@@ -0,0 +1,232 @@
1
+ import { Command } from "commander";
2
+ import inquirer from "inquirer";
3
+ import kleur from "kleur";
4
+ import path from "path";
5
+ import fs from "fs";
6
+ import { repoRoot, writeFile, ensureDir } from "../lib.js";
7
+ import { getIrisDebugInfo } from "../iris/resolver.js";
8
+ import { loadRoutes } from "../iris/routes.js";
9
+ import { routeIntent } from "../iris/router.js";
10
+ import { generatePack } from "../iris/packer.js";
11
+ import { checkArtifact } from "../iris/artifact-checker.js";
12
+ import { loadPolicy } from "../iris/policy.js";
13
+ import { loadState } from "../iris/state.js";
14
+ import { EXIT_CODES } from "../utils/exit-codes.js";
15
+ export const askCommand = new Command("ask")
16
+ .description("Route intent to an agent and generate context pack")
17
+ .argument("[intent...]", "Natural language request intent")
18
+ .option("--agent <agent>", "Override target agent")
19
+ .option("--phase <phase>", "Override target phase")
20
+ .option("--out <path>", "Explicit output path for pack")
21
+ .option("--stdout", "Print pack to stdout", false)
22
+ .option("--json", "Output structured JSON result", false)
23
+ .option("--dry-run", "Simulate routing without writing files", false)
24
+ .option("--debug", "Show IRIS authority and artifact resolution info", false)
25
+ .action(async (intentParts, opts) => {
26
+ const root = repoRoot();
27
+ if (opts.debug) {
28
+ const debug = getIrisDebugInfo(root);
29
+ console.log(kleur.bold("IRIS Authority Debug"));
30
+ console.log(`- Repo Root: ${debug.repoRoot}`);
31
+ console.log(`- IRIS Root: ${debug.irisRoot}`);
32
+ console.log(`- Source: ${kleur.magenta(debug.source.toUpperCase())}`);
33
+ console.log(`- Bundled Path:${debug.bundledPath}`);
34
+ console.log("");
35
+ // Show artifact validation details
36
+ const policy = loadPolicy();
37
+ const state = loadState();
38
+ const phase = state.phase.current;
39
+ const requirements = policy.phases[phase]?.requires || [];
40
+ if (requirements.length > 0) {
41
+ console.log(kleur.bold("Required Artifacts Debug"));
42
+ for (const req of requirements) {
43
+ const check = checkArtifact(root, req.path, req.type);
44
+ console.log(`\n- Artifact: ${req.type}`);
45
+ console.log(` Raw: ${JSON.stringify(req.path)}`);
46
+ console.log(` Normalized: ${check.normalized}`);
47
+ console.log(` Absolute: ${check.absolutePath}`);
48
+ console.log(` Inferred: ${check.inferredKind}`);
49
+ console.log(` Exists: ${check.exists ? kleur.green("YES") : kleur.red("NO")}`);
50
+ if (check.exists) {
51
+ console.log(` Type: ${check.isDirectory ? "directory" : check.isFile ? "file" : "unknown"}`);
52
+ }
53
+ if (check.hasControlChars) {
54
+ console.log(` ${kleur.yellow("⚠ WARNING: Raw path contains control characters (\\r, \\n, etc.)")}`);
55
+ }
56
+ }
57
+ console.log("");
58
+ }
59
+ }
60
+ // 1. Get Intent
61
+ let intent = intentParts.join(" ");
62
+ if (!intent) {
63
+ if (process.stdin.isTTY) {
64
+ const { input } = await inquirer.prompt([
65
+ { type: "input", name: "input", message: "What do you want to do?" }
66
+ ]);
67
+ intent = input;
68
+ }
69
+ else {
70
+ intent = fs.readFileSync(0, "utf-8").trim();
71
+ }
72
+ }
73
+ if (!intent) {
74
+ console.error(kleur.red("No intent provided."));
75
+ process.exit(EXIT_CODES.INVALID);
76
+ }
77
+ // 2. Load Routes
78
+ const routesConfig = loadRoutes();
79
+ if (!routesConfig) {
80
+ console.error(kleur.red("Routes not found. Run `navi install` or create .iris/routes.yaml"));
81
+ process.exit(EXIT_CODES.POLICY_ERROR);
82
+ }
83
+ // 3. Route
84
+ const routing = routeIntent(intent, routesConfig);
85
+ const routeId = routing.route === "default" ? "default" : routing.route.route_id;
86
+ // 4. Decide Context
87
+ let agent = opts.agent;
88
+ let phase = opts.phase;
89
+ let command = "";
90
+ if (routing.route === "default") {
91
+ if (!agent)
92
+ agent = routesConfig.default.agent;
93
+ if (!phase)
94
+ phase = routesConfig.default.phase;
95
+ command = routesConfig.default.command;
96
+ }
97
+ else {
98
+ const selectedRoute = routing.route;
99
+ // If agent missing in route, try to infer or fallback
100
+ if (!agent)
101
+ agent = selectedRoute.agent || inferAgentFromPhase(selectedRoute.phase);
102
+ if (!phase)
103
+ phase = selectedRoute.phase ? selectedRoute.phase.toLowerCase() : "";
104
+ command = selectedRoute.command;
105
+ }
106
+ // Fallback inference if agent is still missing (e.g. default route missing fields)
107
+ if (!agent && command) {
108
+ if (command.includes("inception"))
109
+ agent = "inception";
110
+ else if (command.includes("construction"))
111
+ agent = "construction";
112
+ else if (command.includes("operations"))
113
+ agent = "operations";
114
+ else if (command.includes("master"))
115
+ agent = "master";
116
+ }
117
+ // Override command logic if agent/phase changed via flags
118
+ if (opts.agent) {
119
+ switch (opts.agent) {
120
+ case "master":
121
+ command = "/iris-master-agent";
122
+ break;
123
+ case "inception":
124
+ command = "/iris-inception-agent";
125
+ break;
126
+ case "construction":
127
+ command = "/iris-construction-agent";
128
+ break;
129
+ case "operations":
130
+ command = "/iris-operations-agent";
131
+ break;
132
+ }
133
+ }
134
+ // 5. Pack
135
+ let packPath = "";
136
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
137
+ if (opts.out) {
138
+ packPath = opts.out;
139
+ }
140
+ else {
141
+ packPath = path.join(root, `.iris/inbox/context-pack.${agent}.${phase}.${timestamp}.md`);
142
+ }
143
+ if (!opts.dryRun) {
144
+ try {
145
+ await generatePack({
146
+ agent,
147
+ phase,
148
+ output: opts.stdout ? undefined : packPath,
149
+ stdout: opts.stdout,
150
+ strict: false
151
+ });
152
+ }
153
+ catch (e) {
154
+ console.error("Packing failed:", e);
155
+ process.exit(EXIT_CODES.INVALID);
156
+ }
157
+ }
158
+ // 6. Write Next Action
159
+ const nextPath = path.join(root, ".iris/inbox/next.md");
160
+ const nextHistoryPath = path.join(root, `.iris/inbox/next.${timestamp}.md`);
161
+ const nextContent = `# IRIS Next Action
162
+
163
+ ## Intent
164
+ ${intent}
165
+
166
+ ## Routing Decision
167
+ - Route: ${routeId}
168
+ - Agent: ${agent}
169
+ - Phase: ${phase}
170
+ - Command: ${command}
171
+ - Score: ${routing.score}
172
+ - Matched: ${routing.matches.join(", ")}
173
+ ${routing.excludedBy ? `- Excluded By: ${routing.excludedBy}` : ""}
174
+
175
+ ## Context Pack
176
+ - Path: ${opts.stdout ? "(stdout)" : path.relative(root, packPath)}
177
+ - Generated: ${new Date().toISOString()}
178
+
179
+ ## Do this now
180
+ 1) Open your IDE agent tool
181
+ 2) Run: \`${command}\`
182
+ 3) Provide the context pack at: \`${opts.stdout ? "(stdout)" : path.relative(root, packPath)}\`
183
+
184
+ ## Notes
185
+ - If validation fails, run: \`navi validate\`
186
+ `;
187
+ if (!opts.dryRun) {
188
+ ensureDir(path.dirname(nextPath));
189
+ writeFile(nextPath, nextContent);
190
+ writeFile(nextHistoryPath, nextContent);
191
+ }
192
+ // 7. Output
193
+ if (opts.json) {
194
+ console.log(JSON.stringify({
195
+ intent,
196
+ route: routeId,
197
+ agent,
198
+ phase,
199
+ command,
200
+ score: routing.score,
201
+ matches: routing.matches,
202
+ pack_path: opts.stdout ? null : packPath,
203
+ next_path: nextPath
204
+ }, null, 2));
205
+ }
206
+ else if (!opts.stdout) {
207
+ console.log("");
208
+ console.log(kleur.bold("Routing: ") + kleur.cyan(routeId) + kleur.dim(` (conf: ${routing.score})`));
209
+ console.log(kleur.bold("Command: ") + kleur.green(command));
210
+ if (opts.dryRun) {
211
+ console.log(kleur.yellow("[DRY RUN] No files written."));
212
+ console.log(`Would satisfy intent '${intent}' with agent ${agent}.`);
213
+ }
214
+ else {
215
+ console.log(kleur.bold("Context: ") + kleur.gray(path.relative(root, packPath)));
216
+ console.log(kleur.bold("Next: ") + kleur.gray(path.relative(root, nextPath)));
217
+ }
218
+ console.log("");
219
+ }
220
+ });
221
+ function inferAgentFromPhase(phase) {
222
+ if (!phase)
223
+ return "master";
224
+ const p = phase.toLowerCase();
225
+ if (p === "inception")
226
+ return "inception";
227
+ if (p === "construction")
228
+ return "construction";
229
+ if (p === "operations")
230
+ return "operations";
231
+ return "master";
232
+ }
@@ -0,0 +1,259 @@
1
+ import { Command } from "commander";
2
+ import kleur from "kleur";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import { execSync } from "child_process";
6
+ import { getSelectedIde } from "../iris/state.js";
7
+ import { createConnector } from "../bridge/connector-factory.js";
8
+ const BRIDGE_DIR = path.join(process.cwd(), ".iris/bridge");
9
+ const INBOX_DIR = path.join(BRIDGE_DIR, "inbox");
10
+ const OUTBOX_DIR = path.join(BRIDGE_DIR, "outbox");
11
+ const STATE_DIR = path.join(BRIDGE_DIR, "state");
12
+ export const bridgeCommand = new Command("bridge")
13
+ .description("Bridge helper commands for IDE integration");
14
+ // navi bridge run
15
+ bridgeCommand
16
+ .command("run")
17
+ .description("Start bridge helper (watches inbox, opens IDE, waits for results)")
18
+ .option("--poll-interval <ms>", "Polling interval in milliseconds", "2000")
19
+ .action(async (options) => {
20
+ console.log(kleur.bold("IRIS Bridge Helper"));
21
+ console.log(kleur.dim("Watching for workflow tasks...\n"));
22
+ const ideId = getSelectedIde();
23
+ if (!ideId) {
24
+ console.error(kleur.red("No IDE selected. Run 'navi install' first."));
25
+ process.exit(1);
26
+ }
27
+ console.log(kleur.gray(`IDE: ${ideId}`));
28
+ console.log(kleur.gray(`Inbox: ${INBOX_DIR}`));
29
+ console.log(kleur.gray(`Polling: every ${options.pollInterval}ms\n`));
30
+ // Ensure directories exist
31
+ for (const dir of [INBOX_DIR, OUTBOX_DIR, STATE_DIR]) {
32
+ if (!fs.existsSync(dir)) {
33
+ fs.mkdirSync(dir, { recursive: true });
34
+ }
35
+ }
36
+ const processedTasks = new Set();
37
+ // Main watch loop
38
+ while (true) {
39
+ try {
40
+ const files = fs.readdirSync(INBOX_DIR);
41
+ const taskFiles = files.filter(f => f.endsWith(".json"));
42
+ for (const file of taskFiles) {
43
+ const taskId = file.replace(".json", "");
44
+ // Skip if already processed
45
+ if (processedTasks.has(taskId)) {
46
+ continue;
47
+ }
48
+ console.log(kleur.cyan(`\n→ New task: ${taskId}`));
49
+ const taskPath = path.join(INBOX_DIR, file);
50
+ const task = JSON.parse(fs.readFileSync(taskPath, "utf8"));
51
+ // Generate human-readable prompt
52
+ const promptPath = path.join(STATE_DIR, `${taskId}.md`);
53
+ if (!fs.existsSync(promptPath)) {
54
+ const prompt = generatePrompt(task);
55
+ fs.writeFileSync(promptPath, prompt, "utf8");
56
+ console.log(kleur.dim(` Prompt: ${promptPath}`));
57
+ }
58
+ // Try to open in IDE
59
+ const opened = await tryOpenInIDE(ideId, promptPath);
60
+ if (opened) {
61
+ console.log(kleur.green(` ✓ Opened in ${ideId}`));
62
+ }
63
+ else {
64
+ console.log(kleur.yellow(` ⚠ Could not auto-open. Please open manually:`));
65
+ console.log(kleur.dim(` ${promptPath}`));
66
+ }
67
+ console.log(kleur.dim(` Waiting for result in: ${OUTBOX_DIR}/${taskId}.json`));
68
+ processedTasks.add(taskId);
69
+ }
70
+ // Clean up completed tasks
71
+ const outboxFiles = fs.readdirSync(OUTBOX_DIR);
72
+ outboxFiles.forEach(file => {
73
+ const taskId = file.replace(".json", "");
74
+ if (processedTasks.has(taskId)) {
75
+ console.log(kleur.green(`✓ Task completed: ${taskId}`));
76
+ processedTasks.delete(taskId);
77
+ }
78
+ });
79
+ }
80
+ catch (error) {
81
+ console.error(kleur.red(`Error: ${error.message}`));
82
+ }
83
+ // Wait before next poll
84
+ await new Promise(resolve => setTimeout(resolve, parseInt(options.pollInterval)));
85
+ }
86
+ });
87
+ // navi bridge status
88
+ bridgeCommand
89
+ .command("status")
90
+ .description("Show bridge status and IDE information")
91
+ .action(() => {
92
+ console.log("");
93
+ console.log(kleur.bold("IRIS Bridge Status"));
94
+ console.log("===================\n");
95
+ // IDE selection
96
+ const ideId = getSelectedIde();
97
+ if (ideId) {
98
+ console.log(kleur.bold("Selected IDE:"));
99
+ console.log(` ${kleur.cyan(ideId)}\n`);
100
+ }
101
+ else {
102
+ console.log(kleur.yellow("⚠ No IDE selected"));
103
+ console.log(kleur.dim(" Run: navi install\n"));
104
+ }
105
+ // Connector availability
106
+ if (ideId) {
107
+ const connector = createConnector(ideId);
108
+ console.log(kleur.bold("Connector:"));
109
+ console.log(` Type: ${connector.displayName}`);
110
+ console.log(` ID: ${connector.id}\n`);
111
+ }
112
+ // Bridge directories
113
+ console.log(kleur.bold("Bridge Directories:"));
114
+ const dirs = [
115
+ { name: "Inbox", path: INBOX_DIR },
116
+ { name: "Outbox", path: OUTBOX_DIR },
117
+ { name: "State", path: STATE_DIR }
118
+ ];
119
+ dirs.forEach(({ name, path: dirPath }) => {
120
+ const exists = fs.existsSync(dirPath);
121
+ const status = exists ? kleur.green("✓") : kleur.red("✗");
122
+ console.log(` ${status} ${name}: ${dirPath}`);
123
+ if (exists) {
124
+ const files = fs.readdirSync(dirPath);
125
+ if (files.length > 0) {
126
+ console.log(kleur.dim(` ${files.length} file(s)`));
127
+ }
128
+ }
129
+ });
130
+ console.log("");
131
+ // Pending tasks
132
+ if (fs.existsSync(INBOX_DIR)) {
133
+ const tasks = fs.readdirSync(INBOX_DIR).filter(f => f.endsWith(".json"));
134
+ if (tasks.length > 0) {
135
+ console.log(kleur.bold("Pending Tasks:"));
136
+ tasks.forEach(task => {
137
+ console.log(kleur.yellow(` - ${task.replace(".json", "")}`));
138
+ });
139
+ console.log("");
140
+ }
141
+ }
142
+ // Helper running check
143
+ console.log(kleur.bold("Bridge Helper:"));
144
+ console.log(kleur.dim(" To start: navi bridge run"));
145
+ console.log("");
146
+ });
147
+ /**
148
+ * Generate human-readable prompt from task packet
149
+ */
150
+ function generatePrompt(task) {
151
+ return `# IRIS Workflow Task
152
+
153
+ **Task ID:** ${task.taskId}
154
+ **Stage:** ${task.stage}
155
+ **Agent:** ${task.agent}
156
+
157
+ ## Intent
158
+
159
+ ${task.intent}
160
+
161
+ ## Instructions
162
+
163
+ ${task.instructions}
164
+
165
+ ## Input Files
166
+
167
+ ${task.inputs && task.inputs.length > 0
168
+ ? task.inputs.map((p) => `- [\`${path.basename(p)}\`](file://${path.resolve(p)})`).join("\n")
169
+ : "*No input files*"}
170
+
171
+ ## Expected Outputs
172
+
173
+ ${task.expectedOutputs && task.expectedOutputs.length > 0
174
+ ? task.expectedOutputs.map((p) => `- \`${p}\``).join("\n")
175
+ : "*No specific outputs required*"}
176
+
177
+ ${task.gates ? `\n## Gates\n\n${task.gates.join("\n")}\n` : ""}
178
+
179
+ ---
180
+
181
+ **When complete, create a result file at:**
182
+ \`.iris/bridge/outbox/${task.taskId}.json\`
183
+
184
+ **Result format:**
185
+ \`\`\`json
186
+ {
187
+ "taskId": "${task.taskId}",
188
+ "status": "ok" | "needs_user" | "error",
189
+ "message": "Description of what was done or questions/errors",
190
+ "filesChanged": ["path/to/file1.md", "path/to/file2.md"],
191
+ "logs": ["Optional log messages"]
192
+ }
193
+ \`\`\`
194
+
195
+ **Example result:**
196
+ \`\`\`json
197
+ {
198
+ "taskId": "${task.taskId}",
199
+ "status": "ok",
200
+ "message": "Created requirements.md with 5 sections",
201
+ "filesChanged": ["memory-bank/intents/dashboard/requirements.md"],
202
+ "logs": ["Analyzed intent", "Generated requirements"]
203
+ }
204
+ \`\`\`
205
+ `;
206
+ }
207
+ /**
208
+ * Try to open file in IDE
209
+ */
210
+ async function tryOpenInIDE(ideId, filePath) {
211
+ try {
212
+ switch (ideId.toLowerCase()) {
213
+ case "cursor":
214
+ execSync(`cursor "${filePath}"`, { stdio: "ignore" });
215
+ return true;
216
+ case "vscode":
217
+ case "code":
218
+ execSync(`code "${filePath}"`, { stdio: "ignore" });
219
+ return true;
220
+ case "antigravity":
221
+ // Antigravity might not have a CLI, try common editors
222
+ try {
223
+ execSync(`code "${filePath}"`, { stdio: "ignore" });
224
+ return true;
225
+ }
226
+ catch {
227
+ // Fall through to default
228
+ }
229
+ break;
230
+ case "windsurf":
231
+ try {
232
+ execSync(`windsurf "${filePath}"`, { stdio: "ignore" });
233
+ return true;
234
+ }
235
+ catch {
236
+ // Fall through
237
+ }
238
+ break;
239
+ }
240
+ // Fallback: try to open with system default
241
+ const platform = process.platform;
242
+ if (platform === "darwin") {
243
+ execSync(`open "${filePath}"`, { stdio: "ignore" });
244
+ return true;
245
+ }
246
+ else if (platform === "win32") {
247
+ execSync(`start "" "${filePath}"`, { stdio: "ignore" });
248
+ return true;
249
+ }
250
+ else if (platform === "linux") {
251
+ execSync(`xdg-open "${filePath}"`, { stdio: "ignore" });
252
+ return true;
253
+ }
254
+ return false;
255
+ }
256
+ catch (error) {
257
+ return false;
258
+ }
259
+ }
@@ -0,0 +1,108 @@
1
+ import { Command } from "commander";
2
+ import inquirer from "inquirer";
3
+ import kleur from "kleur";
4
+ import { getSelectedIde, setSelectedIde } from "../iris/state.js";
5
+ import { createRun, loadRun, saveRun, saveRunSummary } from "../iris/run-state.js";
6
+ import { createConnector } from "../bridge/connector-factory.js";
7
+ import { WorkflowStage } from "../bridge/types.js";
8
+ import { executeIntentInception } from "../workflows/intent-inception.js";
9
+ import { executeBoltPlan } from "../workflows/bolt-plan.js";
10
+ import { executeBoltExecution } from "../workflows/bolt-execution.js";
11
+ export const developCommand = new Command("develop")
12
+ .description("Run automated IRIS workflow (Intent → Bolt Plan → Execution)")
13
+ .argument("[intent...]", "Intent description")
14
+ .option("--resume <runId>", "Resume a previous run")
15
+ .option("--ide <ideId>", "Override IDE selection")
16
+ .option("--no-bridge", "Fallback mode (generate files, print paths)")
17
+ .option("--gate <mode>", "Gate approval mode: auto or manual", "manual")
18
+ .action(async (intentArgs, options) => {
19
+ // Handle resume
20
+ if (options.resume) {
21
+ console.log(kleur.cyan(`Resuming run: ${options.resume}`));
22
+ await resumeRun(options.resume, options);
23
+ return;
24
+ }
25
+ // Get intent
26
+ const intent = intentArgs.join(" ");
27
+ if (!intent) {
28
+ console.error(kleur.red("Error: Intent is required"));
29
+ console.log("Usage: navi develop \"Build a dashboard UI...\"");
30
+ process.exit(1);
31
+ }
32
+ // Get IDE selection
33
+ let ideId = options.ide || getSelectedIde();
34
+ if (!ideId) {
35
+ // Prompt for IDE selection
36
+ const { selectedIde } = await inquirer.prompt([
37
+ {
38
+ type: "input",
39
+ name: "selectedIde",
40
+ message: "Which IDE will you use? (e.g., cursor, vscode, antigravity)",
41
+ default: "antigravity"
42
+ }
43
+ ]);
44
+ ideId = selectedIde;
45
+ setSelectedIde(ideId);
46
+ }
47
+ console.log("");
48
+ console.log(kleur.bold("Starting IRIS Workflow"));
49
+ console.log(kleur.gray(`Intent: ${intent}`));
50
+ console.log(kleur.gray(`IDE: ${ideId}`));
51
+ console.log(kleur.gray(`Gate Mode: ${options.gate}`));
52
+ console.log("");
53
+ // Create run
54
+ const runState = createRun(intent, ideId, options.gate);
55
+ console.log(kleur.cyan(`Run ID: ${runState.runId}`));
56
+ console.log(kleur.dim(`Resume with: navi develop --resume ${runState.runId}`));
57
+ console.log("");
58
+ // Execute workflow
59
+ await executeWorkflow(runState, options);
60
+ });
61
+ async function resumeRun(runId, options) {
62
+ try {
63
+ const runState = loadRun(runId);
64
+ console.log(kleur.gray(`Intent: ${runState.intent}`));
65
+ console.log(kleur.gray(`Current Stage: ${runState.stage}`));
66
+ console.log("");
67
+ await executeWorkflow(runState, options);
68
+ }
69
+ catch (error) {
70
+ console.error(kleur.red(`Failed to resume run: ${error.message}`));
71
+ process.exit(1);
72
+ }
73
+ }
74
+ async function executeWorkflow(runState, options) {
75
+ const connector = createConnector(runState.ideId);
76
+ console.log(kleur.bold("Workflow Execution"));
77
+ console.log(kleur.gray(`Using ${connector.displayName} connector`));
78
+ console.log("");
79
+ // Check connector availability
80
+ const available = await connector.isAvailable();
81
+ if (!available) {
82
+ console.log(kleur.yellow("⚠ Connector not fully available, using fallback mode"));
83
+ }
84
+ // Ensure bridge is running
85
+ if (connector.ensureRunning) {
86
+ await connector.ensureRunning();
87
+ }
88
+ // Execute stages based on current stage
89
+ while (runState.stage !== WorkflowStage.DONE) {
90
+ console.log(kleur.bold().cyan(`\n=== Stage: ${runState.stage} ===\n`));
91
+ switch (runState.stage) {
92
+ case WorkflowStage.INTENT_INCEPTION:
93
+ await executeIntentInception(runState, connector, options);
94
+ break;
95
+ case WorkflowStage.BOLT_PLAN:
96
+ await executeBoltPlan(runState, connector, options);
97
+ break;
98
+ case WorkflowStage.BOLT_EXECUTION:
99
+ await executeBoltExecution(runState, connector, options);
100
+ break;
101
+ }
102
+ saveRun(runState);
103
+ saveRunSummary(runState.runId);
104
+ }
105
+ console.log("");
106
+ console.log(kleur.bold().green("✓ Workflow Complete!"));
107
+ console.log(kleur.gray(`Summary: .iris/runs/${runState.runId}.md`));
108
+ }