project-iris 0.0.6 ā 0.0.8
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/README.md +41 -31
- package/dist/bridge/filesystem-connector.js +9 -4
- package/dist/bridge/helper.js +203 -0
- package/dist/bridge/types.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/commands/ask.js +35 -135
- package/dist/commands/bridge.js +13 -192
- package/dist/commands/develop.js +82 -49
- package/dist/commands/doctor.js +13 -13
- package/dist/commands/install.js +4 -4
- package/dist/commands/pack.js +1 -1
- package/dist/commands/phase.js +1 -1
- package/dist/commands/status.js +1 -1
- package/dist/iris/guard.js +3 -3
- package/dist/iris/packer.js +1 -1
- package/dist/workflows/reporting.js +74 -0
- package/package.json +3 -2
- package/src/iris_bundle/.iris/tools/antigravity/.antigravity/knowledge/IRIS.md +0 -6
- package/src/iris_bundle/.iris/tools/antigravity/.antigravity/workflows/iris-construction-agent.md +0 -25
- package/src/iris_bundle/.iris/tools/antigravity/.antigravity/workflows/iris-inception-agent.md +0 -25
- package/src/iris_bundle/.iris/tools/antigravity/.antigravity/workflows/iris-master-agent.md +0 -25
- package/src/iris_bundle/.iris/tools/antigravity/.antigravity/workflows/iris-operations-agent.md +0 -25
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ mkdir my-project
|
|
|
14
14
|
cd my-project
|
|
15
15
|
|
|
16
16
|
# Install IRIS
|
|
17
|
-
npx iris@latest install
|
|
17
|
+
npx project-iris@latest install
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
The installer will:
|
|
@@ -28,19 +28,29 @@ The installer will:
|
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
30
|
# Check IRIS is working
|
|
31
|
-
npx iris --help
|
|
32
|
-
npx iris validate
|
|
31
|
+
npx project-iris --help
|
|
32
|
+
npx project-iris validate
|
|
33
33
|
|
|
34
34
|
# Start using IRIS
|
|
35
|
-
npx iris ask "scaffold a new login system"
|
|
35
|
+
npx project-iris ask "scaffold a new login system"
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
> [!IMPORTANT]
|
|
39
|
+
> **Package Name vs Command Name**
|
|
40
|
+
>
|
|
41
|
+
> The npm package is named `project-iris`, but when installed globally, the command is `iris`.
|
|
42
|
+
>
|
|
43
|
+
> - **With npx** (no global install): Use `npx project-iris <command>`
|
|
44
|
+
> - **After global install**: Use `iris <command>`
|
|
45
|
+
>
|
|
46
|
+
> This is why `npx iris` won't work - there's no package named `iris` on npm.
|
|
47
|
+
|
|
38
48
|
### For Existing Projects
|
|
39
49
|
|
|
40
50
|
If you already have a `package.json`, just run:
|
|
41
51
|
|
|
42
52
|
```bash
|
|
43
|
-
npx iris@latest install
|
|
53
|
+
npx project-iris@latest install
|
|
44
54
|
```
|
|
45
55
|
|
|
46
56
|
IRIS will integrate with your existing project without breaking anything.
|
|
@@ -52,12 +62,12 @@ IRIS will integrate with your existing project without breaking anything.
|
|
|
52
62
|
For convenience, you can install IRIS globally:
|
|
53
63
|
|
|
54
64
|
```bash
|
|
55
|
-
npm install -g iris@latest
|
|
65
|
+
npm install -g project-iris@latest
|
|
56
66
|
|
|
57
|
-
# Now use 'iris' directly
|
|
58
|
-
iris --version
|
|
59
|
-
iris install
|
|
60
|
-
iris ask "create a new feature"
|
|
67
|
+
# Now use 'project-iris' directly
|
|
68
|
+
project-iris --version
|
|
69
|
+
project-iris install
|
|
70
|
+
project-iris ask "create a new feature"
|
|
61
71
|
```
|
|
62
72
|
|
|
63
73
|
---
|
|
@@ -82,7 +92,7 @@ A standardized documentation structure enforced by Navi. The following minimal b
|
|
|
82
92
|
* **`memory-bank/standards/`**: Coding and documentation standards (`README.md` required).
|
|
83
93
|
* **`memory-bank/operations/`**: Runbooks and maintenance guides (`README.md` required).
|
|
84
94
|
|
|
85
|
-
|
|
95
|
+
IRIS ensures these files always exist. If missing, `project-iris validate` fails. Use `project-iris validate --fix` to restore them.
|
|
86
96
|
|
|
87
97
|
---
|
|
88
98
|
|
|
@@ -92,7 +102,7 @@ Navi ensures these files always exist. If missing, `navi validate` fails. Use `n
|
|
|
92
102
|
Don't guess which agent or prompt to use. Just ask IRIS.
|
|
93
103
|
|
|
94
104
|
```bash
|
|
95
|
-
iris ask "I need to fix the auth bug in login"
|
|
105
|
+
project-iris ask "I need to fix the auth bug in login"
|
|
96
106
|
```
|
|
97
107
|
* **Result**: IRIS analyzes `.iris/routes.yaml`, picks the right agent (e.g., `inception` vs `construction`), generates a context pack, and tells you exactly what command to run.
|
|
98
108
|
* **Artifact**: Creates `.iris/inbox/next.md` with instructions.
|
|
@@ -101,7 +111,7 @@ iris ask "I need to fix the auth bug in login"
|
|
|
101
111
|
If you just need the context for an agent manually:
|
|
102
112
|
|
|
103
113
|
```bash
|
|
104
|
-
iris pack --agent inception
|
|
114
|
+
project-iris pack --agent inception
|
|
105
115
|
```
|
|
106
116
|
* **Result**: Generates a single Markdown file containing all relevant project context, rules, and active tasks.
|
|
107
117
|
|
|
@@ -109,29 +119,29 @@ iris pack --agent inception
|
|
|
109
119
|
Ensure your project complies with the defined policies (e.g., "Designs must be approved before coding").
|
|
110
120
|
|
|
111
121
|
```bash
|
|
112
|
-
iris validate
|
|
122
|
+
project-iris validate
|
|
113
123
|
```
|
|
114
124
|
|
|
115
125
|
**Auto-Fix**: IRIS can repair missing directories and file structures automatically.
|
|
116
126
|
```bash
|
|
117
|
-
iris validate --fix
|
|
127
|
+
project-iris validate --fix
|
|
118
128
|
```
|
|
119
129
|
|
|
120
130
|
**Strict Mode (CI)**:
|
|
121
131
|
Use strict mode to fail (exit non-zero) on quality warnings (e.g. placeholders, empty files).
|
|
122
132
|
```bash
|
|
123
|
-
iris validate --strict
|
|
133
|
+
project-iris validate --strict
|
|
124
134
|
```
|
|
125
135
|
|
|
126
136
|
---
|
|
127
137
|
|
|
128
|
-
## š¤ Automated Workflows with `iris develop`
|
|
138
|
+
## š¤ Automated Workflows with `project-iris develop`
|
|
129
139
|
|
|
130
140
|
**NEW**: Automate the complete IRIS workflow from Intent ā Bolt Plan ā Execution with IDE agent integration.
|
|
131
141
|
|
|
132
142
|
### Overview
|
|
133
143
|
|
|
134
|
-
`iris develop` orchestrates the entire IRIS workflow automatically:
|
|
144
|
+
`project-iris develop` orchestrates the entire IRIS workflow automatically:
|
|
135
145
|
1. **Intent Inception** - Clarifies requirements through questions, generates intent artifacts
|
|
136
146
|
2. **Bolt Plan** - Creates implementation plan and individual bolt files
|
|
137
147
|
3. **Bolt Execution** - Executes each bolt (design ā implement ā test)
|
|
@@ -142,10 +152,10 @@ All stages interact with your IDE agent via a bridge protocol, with approval gat
|
|
|
142
152
|
|
|
143
153
|
```bash
|
|
144
154
|
# Terminal 1: Start bridge helper (recommended)
|
|
145
|
-
iris bridge run
|
|
155
|
+
project-iris bridge run
|
|
146
156
|
|
|
147
157
|
# Terminal 2: Run workflow
|
|
148
|
-
iris develop "Build a dashboard UI to track IRIS progress"
|
|
158
|
+
project-iris develop "Build a dashboard UI to track IRIS progress"
|
|
149
159
|
```
|
|
150
160
|
|
|
151
161
|
The workflow will:
|
|
@@ -160,27 +170,27 @@ The workflow will:
|
|
|
160
170
|
|
|
161
171
|
**Basic workflow:**
|
|
162
172
|
```bash
|
|
163
|
-
iris develop "Your intent description"
|
|
173
|
+
project-iris develop "Your intent description"
|
|
164
174
|
```
|
|
165
175
|
|
|
166
176
|
**Resume interrupted workflow:**
|
|
167
177
|
```bash
|
|
168
|
-
iris develop --resume <runId>
|
|
178
|
+
project-iris develop --resume <runId>
|
|
169
179
|
```
|
|
170
180
|
|
|
171
181
|
**Auto-approve gates (no prompts):**
|
|
172
182
|
```bash
|
|
173
|
-
iris develop --gate auto "Your intent"
|
|
183
|
+
project-iris develop --gate auto "Your intent"
|
|
174
184
|
```
|
|
175
185
|
|
|
176
186
|
**Override IDE selection:**
|
|
177
187
|
```bash
|
|
178
|
-
iris develop --ide cursor "Your intent"
|
|
188
|
+
project-iris develop --ide cursor "Your intent"
|
|
179
189
|
```
|
|
180
190
|
|
|
181
191
|
**No-bridge mode (manual result creation):**
|
|
182
192
|
```bash
|
|
183
|
-
iris develop --no-bridge "Your intent"
|
|
193
|
+
project-iris develop --no-bridge "Your intent"
|
|
184
194
|
```
|
|
185
195
|
|
|
186
196
|
### Bridge Helper
|
|
@@ -189,12 +199,12 @@ The bridge helper watches for workflow tasks and opens them in your IDE:
|
|
|
189
199
|
|
|
190
200
|
**Start the helper:**
|
|
191
201
|
```bash
|
|
192
|
-
iris bridge run
|
|
202
|
+
project-iris bridge run
|
|
193
203
|
```
|
|
194
204
|
|
|
195
205
|
**Check bridge status:**
|
|
196
206
|
```bash
|
|
197
|
-
iris bridge status
|
|
207
|
+
project-iris bridge status
|
|
198
208
|
```
|
|
199
209
|
|
|
200
210
|
The helper will:
|
|
@@ -281,12 +291,12 @@ cat .iris/runs/<runId>.md
|
|
|
281
291
|
|
|
282
292
|
**Bridge helper not finding tasks:**
|
|
283
293
|
- Check `.iris/bridge/inbox/` for task files
|
|
284
|
-
- Ensure bridge helper is running (`
|
|
294
|
+
- Ensure bridge helper is running (`iris bridge run`)
|
|
285
295
|
|
|
286
296
|
**IDE not opening automatically:**
|
|
287
297
|
- Verify IDE CLI is available (`which cursor`, `which code`)
|
|
288
298
|
- Use `--no-bridge` mode and open files manually
|
|
289
|
-
- Check `
|
|
299
|
+
- Check `iris bridge status` for connector info
|
|
290
300
|
|
|
291
301
|
**Workflow stuck waiting:**
|
|
292
302
|
- Create result file manually in `.iris/bridge/outbox/<taskId>.json`
|
|
@@ -308,7 +318,7 @@ cat .iris/runs/<runId>.md
|
|
|
308
318
|
* **`pack`**: focused context bundle generator.
|
|
309
319
|
* `--agent <name>`: Target specific agent context.
|
|
310
320
|
* `--auth`: Include sensitive rules (optional).
|
|
311
|
-
* **`run <workflow>`**: Execute a named workflow (e.g., `
|
|
321
|
+
* **`run <workflow>`**: Execute a named workflow (e.g., `iris run deploy`).
|
|
312
322
|
* **`develop [intent]`**: **NEW** - Automated workflow orchestration (Intent ā Bolt Plan ā Execution).
|
|
313
323
|
* `--resume <runId>`: Resume interrupted workflow.
|
|
314
324
|
* `--ide <ideId>`: Override IDE selection.
|
|
@@ -339,7 +349,7 @@ This section is for developers who want to contribute to IRIS itself (not for us
|
|
|
339
349
|
```bash
|
|
340
350
|
# Clone the repository
|
|
341
351
|
git clone <repo-url>
|
|
342
|
-
cd iris
|
|
352
|
+
cd project-iris
|
|
343
353
|
|
|
344
354
|
# Install dependencies
|
|
345
355
|
npm ci
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
+
import { processInboxTasks } from "./helper.js";
|
|
4
|
+
import { getSelectedIde } from "../iris/state.js";
|
|
3
5
|
const BRIDGE_DIR = path.join(process.cwd(), ".iris/bridge");
|
|
4
6
|
const INBOX_DIR = path.join(BRIDGE_DIR, "inbox");
|
|
5
7
|
const OUTBOX_DIR = path.join(BRIDGE_DIR, "outbox");
|
|
@@ -27,10 +29,6 @@ export class FilesystemBridgeConnector {
|
|
|
27
29
|
await this.ensureRunning();
|
|
28
30
|
const inboxPath = path.join(INBOX_DIR, `${packet.taskId}.json`);
|
|
29
31
|
fs.writeFileSync(inboxPath, JSON.stringify(packet, null, 2), "utf8");
|
|
30
|
-
// Also create a human-readable prompt file
|
|
31
|
-
const promptPath = path.join(STATE_DIR, `${packet.taskId}.md`);
|
|
32
|
-
const promptContent = this.generatePrompt(packet);
|
|
33
|
-
fs.writeFileSync(promptPath, promptContent, "utf8");
|
|
34
32
|
return { taskId: packet.taskId };
|
|
35
33
|
}
|
|
36
34
|
async waitResult(taskId, opts) {
|
|
@@ -38,7 +36,9 @@ export class FilesystemBridgeConnector {
|
|
|
38
36
|
const pollIntervalMs = opts?.pollIntervalMs || 1000; // 1 second
|
|
39
37
|
const outboxPath = path.join(OUTBOX_DIR, `${taskId}.json`);
|
|
40
38
|
const startTime = Date.now();
|
|
39
|
+
const processedTasks = new Set(); // Track state for this wait cycle
|
|
41
40
|
while (Date.now() - startTime < timeoutMs) {
|
|
41
|
+
// Check for result logic...
|
|
42
42
|
if (fs.existsSync(outboxPath)) {
|
|
43
43
|
const content = fs.readFileSync(outboxPath, "utf8");
|
|
44
44
|
const result = JSON.parse(content);
|
|
@@ -50,6 +50,11 @@ export class FilesystemBridgeConnector {
|
|
|
50
50
|
}
|
|
51
51
|
return result;
|
|
52
52
|
}
|
|
53
|
+
// AUTO-BRIDGE: Act as the bridge while waiting
|
|
54
|
+
const ideId = getSelectedIde();
|
|
55
|
+
if (ideId) {
|
|
56
|
+
await processInboxTasks(ideId, processedTasks, false);
|
|
57
|
+
}
|
|
53
58
|
// Wait before next poll
|
|
54
59
|
await new Promise(resolve => setTimeout(resolve, pollIntervalMs));
|
|
55
60
|
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import kleur from "kleur";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import { getSelectedIde } from "../iris/state.js";
|
|
6
|
+
const BRIDGE_DIR = path.join(process.cwd(), ".iris/bridge");
|
|
7
|
+
export const INBOX_DIR = path.join(BRIDGE_DIR, "inbox");
|
|
8
|
+
export const OUTBOX_DIR = path.join(BRIDGE_DIR, "outbox");
|
|
9
|
+
export const STATE_DIR = path.join(BRIDGE_DIR, "state");
|
|
10
|
+
/**
|
|
11
|
+
* Start the bridge helper loop
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Start the bridge helper loop
|
|
15
|
+
*/
|
|
16
|
+
export async function startBridgeHelper(options = {}) {
|
|
17
|
+
const { pollInterval = 2000, verbose = false, stopSignal } = options;
|
|
18
|
+
if (verbose) {
|
|
19
|
+
console.log(kleur.bold("IRIS Bridge Helper"));
|
|
20
|
+
console.log(kleur.dim("Watching for workflow tasks...\n"));
|
|
21
|
+
}
|
|
22
|
+
const ideId = getSelectedIde();
|
|
23
|
+
if (!ideId) {
|
|
24
|
+
if (verbose)
|
|
25
|
+
console.error(kleur.red("No IDE selected. Run 'iris install' first."));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (verbose) {
|
|
29
|
+
console.log(kleur.gray(`IDE: ${ideId}`));
|
|
30
|
+
console.log(kleur.gray(`Inbox: ${INBOX_DIR}`));
|
|
31
|
+
console.log(kleur.gray(`Polling: every ${pollInterval}ms\n`));
|
|
32
|
+
}
|
|
33
|
+
ensureBridgeDirs();
|
|
34
|
+
const processedTasks = new Set();
|
|
35
|
+
let running = true;
|
|
36
|
+
while (running) {
|
|
37
|
+
if (stopSignal && stopSignal()) {
|
|
38
|
+
running = false;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
await processInboxTasks(ideId, processedTasks, verbose);
|
|
42
|
+
if (options.runOnce) {
|
|
43
|
+
running = false;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
await new Promise(resolve => setTimeout(resolve, pollInterval));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Process all tasks in the inbox once
|
|
52
|
+
*/
|
|
53
|
+
export async function processInboxTasks(ideId, processedTasks, verbose = false) {
|
|
54
|
+
try {
|
|
55
|
+
// Ensure dirs exist (safe to call repeatedly)
|
|
56
|
+
if (!fs.existsSync(INBOX_DIR))
|
|
57
|
+
return;
|
|
58
|
+
const files = fs.readdirSync(INBOX_DIR);
|
|
59
|
+
const taskFiles = files.filter(f => f.endsWith(".json"));
|
|
60
|
+
for (const file of taskFiles) {
|
|
61
|
+
const taskId = file.replace(".json", "");
|
|
62
|
+
if (processedTasks.has(taskId))
|
|
63
|
+
continue;
|
|
64
|
+
// Allow check against outbox to skip already completed tasks
|
|
65
|
+
if (fs.existsSync(path.join(OUTBOX_DIR, `${taskId}.json`))) {
|
|
66
|
+
processedTasks.add(taskId);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (verbose)
|
|
70
|
+
console.log(kleur.cyan(`\nā New task: ${taskId}`));
|
|
71
|
+
const taskPath = path.join(INBOX_DIR, file);
|
|
72
|
+
let task;
|
|
73
|
+
try {
|
|
74
|
+
task = JSON.parse(fs.readFileSync(taskPath, "utf8"));
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
if (verbose)
|
|
78
|
+
console.error(`Failed to parse task ${taskId}`, e);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const promptPath = path.join(STATE_DIR, `${taskId}.md`);
|
|
82
|
+
if (!fs.existsSync(promptPath)) {
|
|
83
|
+
const prompt = generatePrompt(task);
|
|
84
|
+
fs.writeFileSync(promptPath, prompt, "utf8");
|
|
85
|
+
if (verbose)
|
|
86
|
+
console.log(kleur.dim(` Prompt: ${promptPath}`));
|
|
87
|
+
}
|
|
88
|
+
const opened = await tryOpenInIDE(ideId, promptPath);
|
|
89
|
+
if (verbose) {
|
|
90
|
+
if (opened)
|
|
91
|
+
console.log(kleur.green(` ā Opened in ${ideId}`));
|
|
92
|
+
else {
|
|
93
|
+
console.log(kleur.yellow(` ā Could not auto-open. Please open manually:`));
|
|
94
|
+
console.log(kleur.dim(` ${promptPath}`));
|
|
95
|
+
}
|
|
96
|
+
console.log(kleur.dim(` Waiting for result in: ${OUTBOX_DIR}/${taskId}.json`));
|
|
97
|
+
}
|
|
98
|
+
processedTasks.add(taskId);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
if (verbose)
|
|
103
|
+
console.error(kleur.red(`Error: ${error.message}`));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
export function ensureBridgeDirs() {
|
|
107
|
+
for (const dir of [INBOX_DIR, OUTBOX_DIR, STATE_DIR]) {
|
|
108
|
+
if (!fs.existsSync(dir)) {
|
|
109
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function generatePrompt(task) {
|
|
114
|
+
return `# IRIS Workflow Task
|
|
115
|
+
|
|
116
|
+
**Task ID:** ${task.taskId}
|
|
117
|
+
**Stage:** ${task.stage}
|
|
118
|
+
**Agent:** ${task.agent}
|
|
119
|
+
|
|
120
|
+
## Intent
|
|
121
|
+
|
|
122
|
+
${task.intent}
|
|
123
|
+
|
|
124
|
+
## Instructions
|
|
125
|
+
|
|
126
|
+
${task.instructions}
|
|
127
|
+
|
|
128
|
+
## Input Files
|
|
129
|
+
|
|
130
|
+
${task.inputs && task.inputs.length > 0
|
|
131
|
+
? task.inputs.map((p) => `- [\`${path.basename(p)}\`](file://${path.resolve(p)})`).join("\n")
|
|
132
|
+
: "*No input files*"}
|
|
133
|
+
|
|
134
|
+
## Expected Outputs
|
|
135
|
+
|
|
136
|
+
${task.expectedOutputs && task.expectedOutputs.length > 0
|
|
137
|
+
? task.expectedOutputs.map((p) => `- \`${p}\``).join("\n")
|
|
138
|
+
: "*No specific outputs required*"}
|
|
139
|
+
|
|
140
|
+
${task.gates ? `\n## Gates\n\n${task.gates.join("\n")}\n` : ""}
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
**When complete, create a result file at:**
|
|
145
|
+
\`.iris/bridge/outbox/${task.taskId}.json\`
|
|
146
|
+
|
|
147
|
+
**Result format:**
|
|
148
|
+
\`\`\`json
|
|
149
|
+
{
|
|
150
|
+
"taskId": "${task.taskId}",
|
|
151
|
+
"status": "ok" | "needs_user" | "error",
|
|
152
|
+
"message": "Description of what was done or questions/errors",
|
|
153
|
+
"filesChanged": ["path/to/file1.md", "path/to/file2.md"],
|
|
154
|
+
"logs": ["Optional log messages"]
|
|
155
|
+
}
|
|
156
|
+
\`\`\`
|
|
157
|
+
`;
|
|
158
|
+
}
|
|
159
|
+
async function tryOpenInIDE(ideId, filePath) {
|
|
160
|
+
try {
|
|
161
|
+
switch (ideId.toLowerCase()) {
|
|
162
|
+
case "cursor":
|
|
163
|
+
execSync(`cursor "${filePath}"`, { stdio: "ignore" });
|
|
164
|
+
return true;
|
|
165
|
+
case "vscode":
|
|
166
|
+
case "code":
|
|
167
|
+
execSync(`code "${filePath}"`, { stdio: "ignore" });
|
|
168
|
+
return true;
|
|
169
|
+
case "antigravity":
|
|
170
|
+
case "gemini":
|
|
171
|
+
try {
|
|
172
|
+
execSync(`code "${filePath}"`, { stdio: "ignore" });
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
catch { }
|
|
176
|
+
break;
|
|
177
|
+
case "windsurf":
|
|
178
|
+
try {
|
|
179
|
+
execSync(`windsurf "${filePath}"`, { stdio: "ignore" });
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
catch { }
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
const platform = process.platform;
|
|
186
|
+
if (platform === "darwin") {
|
|
187
|
+
execSync(`open "${filePath}"`, { stdio: "ignore" });
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
else if (platform === "win32") {
|
|
191
|
+
execSync(`start "" "${filePath}"`, { stdio: "ignore" });
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
else if (platform === "linux") {
|
|
195
|
+
execSync(`xdg-open "${filePath}"`, { stdio: "ignore" });
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
}
|
package/dist/bridge/types.js
CHANGED
package/dist/cli.js
CHANGED
|
@@ -15,7 +15,7 @@ const program = new Command();
|
|
|
15
15
|
program
|
|
16
16
|
.name("iris")
|
|
17
17
|
.description("IRIS CLI - Intelligent Repository for Intent-driven Systems")
|
|
18
|
-
.version("0.0.
|
|
18
|
+
.version("0.0.08")
|
|
19
19
|
.addCommand(installCommand)
|
|
20
20
|
.addCommand(uninstallCommand)
|
|
21
21
|
.addCommand(phaseCommand)
|
package/dist/commands/ask.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import inquirer from "inquirer";
|
|
3
3
|
import kleur from "kleur";
|
|
4
|
-
import path from "path";
|
|
5
4
|
import fs from "fs";
|
|
6
|
-
import { repoRoot
|
|
5
|
+
import { repoRoot } from "../lib.js";
|
|
7
6
|
import { getIrisDebugInfo } from "../iris/resolver.js";
|
|
8
7
|
import { loadRoutes } from "../iris/routes.js";
|
|
9
8
|
import { routeIntent } from "../iris/router.js";
|
|
10
|
-
import { generatePack } from "../iris/packer.js";
|
|
11
9
|
import { checkArtifact } from "../iris/artifact-checker.js";
|
|
12
10
|
import { loadPolicy } from "../iris/policy.js";
|
|
13
11
|
import { loadState } from "../iris/state.js";
|
|
14
12
|
import { EXIT_CODES } from "../utils/exit-codes.js";
|
|
13
|
+
import { createConnector } from "../bridge/connector-factory.js";
|
|
14
|
+
import { getSelectedIde } from "../iris/state.js";
|
|
15
|
+
import { executeIntentInception } from "../workflows/intent-inception.js";
|
|
16
|
+
import { executeBoltPlan } from "../workflows/bolt-plan.js";
|
|
17
|
+
import { createRun } from "../iris/run-state.js";
|
|
15
18
|
export const askCommand = new Command("ask")
|
|
16
19
|
.description("Route intent to an agent and generate context pack")
|
|
17
20
|
.argument("[intent...]", "Natural language request intent")
|
|
@@ -77,146 +80,43 @@ export const askCommand = new Command("ask")
|
|
|
77
80
|
// 2. Load Routes
|
|
78
81
|
const routesConfig = loadRoutes();
|
|
79
82
|
if (!routesConfig) {
|
|
80
|
-
console.error(kleur.red("Routes not found. Run `
|
|
83
|
+
console.error(kleur.red("Routes not found. Run `iris install` or create .iris/routes.yaml"));
|
|
81
84
|
process.exit(EXIT_CODES.POLICY_ERROR);
|
|
82
85
|
}
|
|
83
86
|
// 3. Route
|
|
84
87
|
const routing = routeIntent(intent, routesConfig);
|
|
85
88
|
const routeId = routing.route === "default" ? "default" : routing.route.route_id;
|
|
86
|
-
// 4.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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) {
|
|
89
|
+
// 4. Execution Workflow (Inception + Planning)
|
|
90
|
+
console.log(kleur.bold("Starting IRIS Inception & Planning"));
|
|
91
|
+
console.log(kleur.dim("This process will clarify your intent and generate an implementation plan.\n"));
|
|
92
|
+
// Initialize Bridge/IDE
|
|
93
|
+
const ideId = getSelectedIde() || "antigravity"; // Default or prompt?
|
|
94
|
+
// If not selected, we might want to prompt, but for now fallback to antigravity or error?
|
|
95
|
+
// The bridge helper handles "run 'iris install'" error.
|
|
96
|
+
// Create new run
|
|
97
|
+
const runState = createRun(intent, ideId, "manual");
|
|
98
|
+
const connector = createConnector(ideId);
|
|
99
|
+
try {
|
|
100
|
+
// Phase 1: Inception (Clarify + Artifacts)
|
|
101
|
+
await executeIntentInception(runState, connector, {
|
|
102
|
+
gate: "manual",
|
|
103
|
+
noBridge: false
|
|
104
|
+
});
|
|
105
|
+
// Phase 2: Bolt Plan (Stories -> Bolts)
|
|
106
|
+
await executeBoltPlan(runState, connector, {
|
|
107
|
+
gate: "manual",
|
|
108
|
+
noBridge: false
|
|
109
|
+
});
|
|
207
110
|
console.log("");
|
|
208
|
-
console.log(kleur.bold(
|
|
209
|
-
console.log(
|
|
210
|
-
|
|
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
|
-
}
|
|
111
|
+
console.log(kleur.bold(kleur.green("ā Plan Created Successfully!")));
|
|
112
|
+
console.log("To start execution, run:");
|
|
113
|
+
console.log(kleur.cyan(` iris develop --resume ${runState.runId}`));
|
|
218
114
|
console.log("");
|
|
219
115
|
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error(kleur.red(`\nā Planning Failed: ${error.message}`));
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
220
120
|
});
|
|
221
121
|
function inferAgentFromPhase(phase) {
|
|
222
122
|
if (!phase)
|