project-iris 0.0.7 → 0.0.11

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 (125) hide show
  1. package/README.md +294 -264
  2. package/dist/bridge/agent-runner.js +190 -0
  3. package/dist/bridge/connector-factory.js +4 -0
  4. package/dist/bridge/connectors/in-process-connector.js +29 -0
  5. package/dist/bridge/filesystem-connector.js +5 -0
  6. package/dist/cli.js +10 -2
  7. package/dist/commands/ask.js +150 -23
  8. package/dist/commands/bridge.js +8 -0
  9. package/dist/commands/flow.js +301 -0
  10. package/dist/commands/framework.js +273 -0
  11. package/dist/commands/generate.js +59 -0
  12. package/dist/commands/install.js +72 -29
  13. package/dist/commands/pack.js +7 -1
  14. package/dist/commands/run.js +195 -13
  15. package/dist/commands/status.js +9 -0
  16. package/dist/commands/uninstall.js +3 -1
  17. package/dist/commands/use.js +20 -0
  18. package/dist/commands/validate.js +80 -65
  19. package/dist/framework/framework-loader.js +97 -0
  20. package/dist/framework/framework-paths.js +48 -0
  21. package/dist/framework/framework-types.js +15 -0
  22. package/dist/iris/artifacts/config.js +68 -0
  23. package/dist/iris/artifacts/generator.js +88 -0
  24. package/dist/iris/artifacts/types.js +1 -0
  25. package/dist/iris/bundle.js +44 -0
  26. package/dist/iris/doctrine/collector.js +124 -0
  27. package/dist/iris/fixer.js +28 -22
  28. package/dist/iris/flows/manifest.js +124 -0
  29. package/dist/iris/framework-context.js +49 -0
  30. package/dist/iris/framework-manager.js +215 -0
  31. package/dist/iris/fs/atomic.js +22 -0
  32. package/dist/iris/importers/index.js +9 -0
  33. package/dist/iris/importers/types.js +8 -0
  34. package/dist/iris/importers/writer.js +139 -0
  35. package/dist/iris/installer.js +105 -40
  36. package/dist/iris/interactive/env.js +21 -0
  37. package/dist/iris/interactive/intent-interview.js +345 -0
  38. package/dist/iris/interactive/intent-schema.js +28 -0
  39. package/dist/iris/interactive/interview-io.js +22 -0
  40. package/dist/iris/interview/config.js +71 -0
  41. package/dist/iris/interview/types.js +16 -0
  42. package/dist/iris/interview/utils.js +38 -0
  43. package/dist/iris/packer.js +69 -47
  44. package/dist/iris/parsers/unit-parser.js +43 -0
  45. package/dist/iris/paths.js +18 -0
  46. package/dist/iris/policy.js +122 -17
  47. package/dist/iris/proc.js +56 -0
  48. package/dist/iris/resolver.js +3 -0
  49. package/dist/iris/routes.js +180 -11
  50. package/dist/iris/run-state.js +3 -0
  51. package/dist/iris/state.js +37 -9
  52. package/dist/iris/templates.js +70 -0
  53. package/dist/iris/tmp.js +24 -0
  54. package/dist/iris/uninstaller.js +24 -9
  55. package/dist/iris/utils/interpolate.js +42 -0
  56. package/dist/iris/validator.js +72 -10
  57. package/dist/iris/workflow/config.js +51 -0
  58. package/dist/iris/workflow/engine.js +129 -0
  59. package/dist/iris/workflow/steps.js +448 -0
  60. package/dist/iris/workflow/types.js +1 -0
  61. package/dist/utils/logo.js +17 -0
  62. package/dist/workflows/intent-inception.js +87 -65
  63. package/package.json +8 -6
  64. package/src/iris_bundle/.iris/aidlc/README.md +0 -16
  65. package/src/iris_bundle/.iris/aidlc/agents/iris-construction-agent.md +0 -35
  66. package/src/iris_bundle/.iris/aidlc/agents/iris-inception-agent.md +0 -30
  67. package/src/iris_bundle/.iris/aidlc/agents/iris-master-agent.md +0 -35
  68. package/src/iris_bundle/.iris/aidlc/agents/iris-operations-agent.md +0 -29
  69. package/src/iris_bundle/.iris/aidlc/commands/iris-construction-agent.md +0 -18
  70. package/src/iris_bundle/.iris/aidlc/commands/iris-inception-agent.md +0 -18
  71. package/src/iris_bundle/.iris/aidlc/commands/iris-master-agent.md +0 -18
  72. package/src/iris_bundle/.iris/aidlc/commands/iris-operations-agent.md +0 -18
  73. package/src/iris_bundle/.iris/aidlc/context/context-map.md +0 -25
  74. package/src/iris_bundle/.iris/aidlc/context/exclusion-rules.md +0 -13
  75. package/src/iris_bundle/.iris/aidlc/context/load-order.md +0 -25
  76. package/src/iris_bundle/.iris/aidlc/memory/intent-rules.md +0 -9
  77. package/src/iris_bundle/.iris/aidlc/memory/log-rules.md +0 -5
  78. package/src/iris_bundle/.iris/aidlc/memory/memory-bank.yaml +0 -39
  79. package/src/iris_bundle/.iris/aidlc/memory/unit-rules.md +0 -9
  80. package/src/iris_bundle/.iris/aidlc/quick-start.md +0 -24
  81. package/src/iris_bundle/.iris/aidlc/skills/execution/implementation.md +0 -14
  82. package/src/iris_bundle/.iris/aidlc/skills/execution/refactoring.md +0 -13
  83. package/src/iris_bundle/.iris/aidlc/skills/execution/scaffold-generation.md +0 -15
  84. package/src/iris_bundle/.iris/aidlc/skills/governance/escalation.md +0 -13
  85. package/src/iris_bundle/.iris/aidlc/skills/governance/quality-gates.md +0 -14
  86. package/src/iris_bundle/.iris/aidlc/skills/governance/stop-conditions.md +0 -11
  87. package/src/iris_bundle/.iris/aidlc/skills/reasoning/decomposition.md +0 -23
  88. package/src/iris_bundle/.iris/aidlc/skills/reasoning/risk-analysis.md +0 -14
  89. package/src/iris_bundle/.iris/aidlc/skills/reasoning/verification.md +0 -21
  90. package/src/iris_bundle/.iris/aidlc/standards/artifacts-registry.md +0 -38
  91. package/src/iris_bundle/.iris/aidlc/standards/decision-logging.md +0 -16
  92. package/src/iris_bundle/.iris/aidlc/standards/doctrine-structure.md +0 -31
  93. package/src/iris_bundle/.iris/aidlc/standards/documentation-rules.md +0 -15
  94. package/src/iris_bundle/.iris/aidlc/standards/file-structure.md +0 -21
  95. package/src/iris_bundle/.iris/aidlc/standards/naming-conventions.md +0 -18
  96. package/src/iris_bundle/.iris/aidlc/standards/phases-and-gates.md +0 -25
  97. package/src/iris_bundle/.iris/aidlc/standards/routes-and-routing.md +0 -35
  98. package/src/iris_bundle/.iris/aidlc/standards/tool-wrappers.md +0 -32
  99. package/src/iris_bundle/.iris/aidlc/templates/bolt.md +0 -23
  100. package/src/iris_bundle/.iris/aidlc/templates/doctrine-doc-template.md +0 -33
  101. package/src/iris_bundle/.iris/aidlc/templates/intent.md +0 -23
  102. package/src/iris_bundle/.iris/aidlc/templates/log.md +0 -24
  103. package/src/iris_bundle/.iris/aidlc/templates/review.md +0 -21
  104. package/src/iris_bundle/.iris/aidlc/templates/unit.md +0 -31
  105. package/src/iris_bundle/.iris/aidlc/validation/failure-modes.md +0 -16
  106. package/src/iris_bundle/.iris/aidlc/validation/phase-preconditions.md +0 -21
  107. package/src/iris_bundle/.iris/aidlc/validation/quality-checklist.md +0 -20
  108. package/src/iris_bundle/.iris/policy.yaml +0 -27
  109. package/src/iris_bundle/.iris/routes.yaml +0 -98
  110. package/src/iris_bundle/.iris/state.yaml +0 -7
  111. package/src/iris_bundle/.iris/tools/claude/.claude/claude.md +0 -9
  112. package/src/iris_bundle/.iris/tools/claude/.claude/commands/compare-specs.md +0 -203
  113. package/src/iris_bundle/.iris/tools/claude/.claude/commands/iris-construction-agent.md +0 -25
  114. package/src/iris_bundle/.iris/tools/claude/.claude/commands/iris-inception-agent.md +0 -25
  115. package/src/iris_bundle/.iris/tools/claude/.claude/commands/iris-master-agent.md +0 -25
  116. package/src/iris_bundle/.iris/tools/claude/.claude/commands/iris-operations-agent.md +0 -25
  117. package/src/iris_bundle/.iris/tools/codex/AGENTS.md +0 -15
  118. package/src/iris_bundle/.iris/tools/cursor/.cursor/commands/iris-construction-agent.md +0 -25
  119. package/src/iris_bundle/.iris/tools/cursor/.cursor/commands/iris-inception-agent.md +0 -25
  120. package/src/iris_bundle/.iris/tools/cursor/.cursor/commands/iris-master-agent.md +0 -25
  121. package/src/iris_bundle/.iris/tools/cursor/.cursor/commands/iris-operations-agent.md +0 -25
  122. package/src/iris_bundle/.iris/tools/gemini/.gemini/commands/iris-construction-agent.toml +0 -29
  123. package/src/iris_bundle/.iris/tools/gemini/.gemini/commands/iris-inception-agent.toml +0 -29
  124. package/src/iris_bundle/.iris/tools/gemini/.gemini/commands/iris-master-agent.toml +0 -29
  125. package/src/iris_bundle/.iris/tools/gemini/.gemini/commands/iris-operations-agent.toml +0 -29
@@ -0,0 +1,190 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import kleur from "kleur";
4
+ import { INBOX_DIR, OUTBOX_DIR } from "./helper.js";
5
+ export async function startAgentRunner(options = {}) {
6
+ const pollInterval = options.pollInterval || 2000;
7
+ const verbose = options.verbose !== false;
8
+ console.log(kleur.bold("🤖 IRIS Automated Agent Started"));
9
+ console.log(kleur.dim(` Watching: ${INBOX_DIR}`));
10
+ console.log(kleur.dim(` Answering to: ${OUTBOX_DIR}\n`));
11
+ // Ensure directories
12
+ fs.mkdirSync(INBOX_DIR, { recursive: true });
13
+ fs.mkdirSync(OUTBOX_DIR, { recursive: true });
14
+ const processed = new Set();
15
+ // Polling Loop
16
+ setInterval(async () => {
17
+ try {
18
+ const files = fs.readdirSync(INBOX_DIR).filter(f => f.endsWith(".json"));
19
+ for (const file of files) {
20
+ if (processed.has(file))
21
+ continue;
22
+ const filePath = path.join(INBOX_DIR, file);
23
+ try {
24
+ const content = fs.readFileSync(filePath, "utf8");
25
+ const task = JSON.parse(content);
26
+ processed.add(file);
27
+ const outPath = path.join(OUTBOX_DIR, file);
28
+ if (fs.existsSync(outPath)) {
29
+ processed.add(file);
30
+ continue;
31
+ }
32
+ if (verbose) {
33
+ console.log(kleur.cyan(`\n[Active] Processing task: ${task.taskId}`));
34
+ console.log(kleur.dim(` Stage: ${task.stage}`));
35
+ console.log(kleur.dim(` Intent: ${task.intent}`));
36
+ }
37
+ // Think...
38
+ await new Promise(r => setTimeout(r, 1000)); // Simulate latency
39
+ // Handle
40
+ const result = await handleTask(task);
41
+ // Respond
42
+ fs.writeFileSync(outPath, JSON.stringify(result, null, 2));
43
+ console.log(kleur.green(` ✓ Responded to ${task.taskId}`));
44
+ }
45
+ catch (err) {
46
+ console.error(kleur.red(` ✗ Failed to process ${file}: ${err.message}`));
47
+ }
48
+ }
49
+ }
50
+ catch (e) {
51
+ // Ignore read errors
52
+ }
53
+ }, pollInterval);
54
+ }
55
+ // Heuristic Intelligence
56
+ export async function handleTask(task) {
57
+ // 1. Intent Inception (Ping-Pong)
58
+ if (task.stage === "INTENT_INCEPTION" && task.metadata?.step === "clarify_turn") {
59
+ return handleClarification(task);
60
+ }
61
+ // 2. Artifact Generation
62
+ if (task.stage === "INTENT_INCEPTION" && task.metadata?.step === "generate_artifacts") {
63
+ return handleArtifactGeneration(task);
64
+ }
65
+ // 3. Bolt Plan
66
+ if (task.stage === "BOLT_PLAN" && task.metadata?.step === "generate_bolt_plan") {
67
+ return handleBoltPlan(task);
68
+ }
69
+ // Default fallback
70
+ return {
71
+ taskId: task.taskId,
72
+ status: "ok",
73
+ message: "DONE",
74
+ filesChanged: []
75
+ };
76
+ }
77
+ function handleClarification(task) {
78
+ const instructions = task.instructions || "";
79
+ const historyLines = instructions.split("\n").filter(l => l.trim().startsWith("Q:"));
80
+ const turnCount = historyLines.length;
81
+ let message = "DONE";
82
+ // Simple Script
83
+ if (turnCount === 0) {
84
+ message = "\"Who is the primary user for this application?\"";
85
+ }
86
+ else if (turnCount === 1) {
87
+ message = "\"What are the key technical constraints (Language, DB)?\"";
88
+ }
89
+ else if (turnCount === 2) {
90
+ message = "\"What are the success criteria for this project?\"";
91
+ }
92
+ else if (turnCount === 3) {
93
+ message = "\"What are the non-goals (what should we NOT build)?\"";
94
+ }
95
+ else {
96
+ message = "\"DONE\"";
97
+ }
98
+ return {
99
+ taskId: task.taskId,
100
+ status: "ok",
101
+ message,
102
+ filesChanged: []
103
+ };
104
+ }
105
+ function handleArtifactGeneration(task) {
106
+ const intentSlug = task.metadata?.intentSlug || "default";
107
+ const prompt = task.instructions || "";
108
+ // 1. Parse Inputs (Poor man's extraction from "User Answers" section of prompt)
109
+ let targetUser = "Unknown User";
110
+ let techStack = "Node.js (Default)";
111
+ let successCriteria = "- Standard success criteria";
112
+ let nonGoals = "- None specified";
113
+ // Extract Answers
114
+ const qaRegex = /Q: (.*?)\nA: (.*?)(?=\nQ:|\n$)/gs;
115
+ const matches = [...prompt.matchAll(qaRegex)];
116
+ matches.forEach(([, q, a]) => {
117
+ const qLower = q.toLowerCase();
118
+ if (qLower.includes("primary user"))
119
+ targetUser = a.trim();
120
+ else if (qLower.includes("technical constraints"))
121
+ techStack = a.trim();
122
+ else if (qLower.includes("success criteria"))
123
+ successCriteria = a.trim().split('.').map(s => s.trim()).filter(Boolean).map(s => `- ${s}`).join("\n");
124
+ else if (qLower.includes("non-goals"))
125
+ nonGoals = a.trim().split('.').map(s => s.trim()).filter(Boolean).map(s => `- ${s}`).join("\n");
126
+ });
127
+ // 2. Generate Requirements
128
+ const reqContent = `# Requirements: ${task.intent}
129
+
130
+ ## Goal
131
+ ${task.intent}
132
+
133
+ ## Target User
134
+ ${targetUser}
135
+
136
+ ## Success Criteria
137
+ ${successCriteria}
138
+
139
+ ## Non-Goals
140
+ ${nonGoals}
141
+
142
+ ## Functional Requirements (Inferred)
143
+ - User should be able to complete the core workflows described in criteria.
144
+ - System should be performant and reliable.
145
+ `;
146
+ // 3. Generate System Context
147
+ const sysContent = `# System Context
148
+
149
+ ## Tech Stack
150
+ ${techStack}
151
+
152
+ ## Architecture Decisions
153
+ - **Frontend / Backend Split**: as implied by tech stack.
154
+ - **Data Persistence**: ${techStack.includes("firebase") ? "Firebase" : "Local/File-based (Default)"}.
155
+
156
+ ## Constraints
157
+ - ${techStack}
158
+ `;
159
+ const root = process.cwd();
160
+ const reqPath = `memory-bank/intents/${intentSlug}/requirements.md`;
161
+ const sysPath = `memory-bank/intents/${intentSlug}/system-context.md`;
162
+ ensureFile(path.join(root, reqPath), reqContent);
163
+ ensureFile(path.join(root, sysPath), sysContent);
164
+ return {
165
+ taskId: task.taskId,
166
+ status: "ok",
167
+ message: "Artifacts generated.",
168
+ filesChanged: [reqPath, sysPath]
169
+ };
170
+ }
171
+ function handleBoltPlan(task) {
172
+ const root = process.cwd();
173
+ const planPath = "memory-bank/operations/bolts/plan.md";
174
+ const boltPath = "memory-bank/operations/bolts/b001-bootstrap.md";
175
+ const planContent = `# Bolt Plan\n\n- [ ] [B001] [Bootstrap Project](./b001-bootstrap.md)\n`;
176
+ const boltContent = `# Bolt: Bootstrap\n\n## Tasks\n- [ ] Init project\n\n## Acceptance\n- runs\n`;
177
+ ensureFile(path.join(root, planPath), planContent);
178
+ ensureFile(path.join(root, boltPath), boltContent);
179
+ return {
180
+ taskId: task.taskId,
181
+ status: "ok",
182
+ message: "Plan generated.",
183
+ filesChanged: [planPath, boltPath]
184
+ };
185
+ }
186
+ function ensureFile(p, content) {
187
+ const dir = path.dirname(p);
188
+ fs.mkdirSync(dir, { recursive: true });
189
+ fs.writeFileSync(p, content);
190
+ }
@@ -3,6 +3,7 @@ import { CursorConnector } from "./connectors/cursor-connector.js";
3
3
  import { VSCodeConnector } from "./connectors/vscode-connector.js";
4
4
  import { AntigravityConnector } from "./connectors/antigravity-connector.js";
5
5
  import { WindsurfConnector } from "./connectors/windsurf-connector.js";
6
+ import { InProcessBridgeConnector } from "./connectors/in-process-connector.js";
6
7
  /**
7
8
  * Create a bridge connector based on IDE id
8
9
  */
@@ -18,6 +19,9 @@ export function createConnector(ideId) {
18
19
  return new AntigravityConnector();
19
20
  case "windsurf":
20
21
  return new WindsurfConnector();
22
+ case "auto":
23
+ case "internal":
24
+ return new InProcessBridgeConnector();
21
25
  case "claude":
22
26
  case "codex":
23
27
  default:
@@ -0,0 +1,29 @@
1
+ import { handleTask } from "../agent-runner.js";
2
+ export class InProcessBridgeConnector {
3
+ id = "in-process";
4
+ displayName = "Internal Agent";
5
+ pendingTasks = new Map();
6
+ async isAvailable() {
7
+ return true;
8
+ }
9
+ async ensureRunning() {
10
+ // No-op
11
+ }
12
+ async sendTask(packet) {
13
+ this.pendingTasks.set(packet.taskId, packet);
14
+ return { taskId: packet.taskId };
15
+ }
16
+ async waitResult(taskId, opts) {
17
+ const packet = this.pendingTasks.get(taskId);
18
+ if (!packet) {
19
+ throw new Error(`Task ${taskId} not found in process memory`);
20
+ }
21
+ // Simulate async processing (think time)
22
+ await new Promise(resolve => setTimeout(resolve, 500));
23
+ // Execute logic directly
24
+ const result = await handleTask(packet);
25
+ // Cleanup
26
+ this.pendingTasks.delete(taskId);
27
+ return result;
28
+ }
29
+ }
@@ -2,6 +2,7 @@ import fs from "fs";
2
2
  import path from "path";
3
3
  import { processInboxTasks } from "./helper.js";
4
4
  import { getSelectedIde } from "../iris/state.js";
5
+ import kleur from "kleur";
5
6
  const BRIDGE_DIR = path.join(process.cwd(), ".iris/bridge");
6
7
  const INBOX_DIR = path.join(BRIDGE_DIR, "inbox");
7
8
  const OUTBOX_DIR = path.join(BRIDGE_DIR, "outbox");
@@ -40,6 +41,7 @@ export class FilesystemBridgeConnector {
40
41
  while (Date.now() - startTime < timeoutMs) {
41
42
  // Check for result logic...
42
43
  if (fs.existsSync(outboxPath)) {
44
+ console.log(kleur.dim(` [Debug] Found result at: ${outboxPath}`));
43
45
  const content = fs.readFileSync(outboxPath, "utf8");
44
46
  const result = JSON.parse(content);
45
47
  // Clean up
@@ -50,6 +52,9 @@ export class FilesystemBridgeConnector {
50
52
  }
51
53
  return result;
52
54
  }
55
+ else {
56
+ // console.log(kleur.dim(` [Debug] Waiting... Checked: ${outboxPath}`));
57
+ }
53
58
  // AUTO-BRIDGE: Act as the bridge while waiting
54
59
  const ideId = getSelectedIde();
55
60
  if (ideId) {
package/dist/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
3
  import { installCommand } from "./commands/install.js";
4
+ import { flowCommand } from "./commands/flow.js";
4
5
  import { uninstallCommand } from "./commands/uninstall.js";
5
6
  import { phaseCommand } from "./commands/phase.js";
6
7
  import { validateCommand } from "./commands/validate.js";
@@ -11,13 +12,19 @@ import { askCommand } from "./commands/ask.js";
11
12
  import { doctorCommand } from "./commands/doctor.js";
12
13
  import { developCommand } from "./commands/develop.js";
13
14
  import { bridgeCommand } from "./commands/bridge.js";
15
+ import { frameworkCommand } from "./commands/framework.js";
16
+ import { generateCommand } from "./commands/generate.js";
17
+ import { useCommand } from "./commands/use.js";
14
18
  const program = new Command();
15
19
  program
16
20
  .name("iris")
17
21
  .description("IRIS CLI - Intelligent Repository for Intent-driven Systems")
18
- .version("0.0.06")
22
+ .version("0.0.11")
19
23
  .addCommand(installCommand)
20
24
  .addCommand(uninstallCommand)
25
+ .addCommand(frameworkCommand)
26
+ .addCommand(generateCommand)
27
+ .addCommand(flowCommand)
21
28
  .addCommand(phaseCommand)
22
29
  .addCommand(validateCommand)
23
30
  .addCommand(statusCommand)
@@ -26,5 +33,6 @@ program
26
33
  .addCommand(askCommand)
27
34
  .addCommand(doctorCommand)
28
35
  .addCommand(developCommand)
29
- .addCommand(bridgeCommand);
36
+ .addCommand(bridgeCommand)
37
+ .addCommand(useCommand);
30
38
  program.parseAsync(process.argv);
@@ -1,20 +1,24 @@
1
1
  import { Command } from "commander";
2
2
  import inquirer from "inquirer";
3
3
  import kleur from "kleur";
4
+ import path from "path";
4
5
  import fs from "fs";
5
6
  import { repoRoot } from "../lib.js";
6
- import { getIrisDebugInfo } from "../iris/resolver.js";
7
- import { loadRoutes } from "../iris/routes.js";
7
+ import { resolveArtifactPath, getIrisDebugInfo } from "../iris/resolver.js";
8
+ import { loadEffectiveRoutes } from "../iris/routes.js";
8
9
  import { routeIntent } from "../iris/router.js";
9
10
  import { checkArtifact } from "../iris/artifact-checker.js";
10
11
  import { loadPolicy } from "../iris/policy.js";
11
12
  import { loadState } from "../iris/state.js";
12
13
  import { EXIT_CODES } from "../utils/exit-codes.js";
13
14
  import { createConnector } from "../bridge/connector-factory.js";
14
- import { getSelectedIde } from "../iris/state.js";
15
15
  import { executeIntentInception } from "../workflows/intent-inception.js";
16
16
  import { executeBoltPlan } from "../workflows/bolt-plan.js";
17
17
  import { createRun } from "../iris/run-state.js";
18
+ import { migrateLegacyDraft } from "../iris/interactive/intent-interview.js";
19
+ import { checkInteractiveMode } from "../iris/interactive/env.js";
20
+ import { resolveActiveFramework } from "../iris/framework-context.js";
21
+ import { loadEffectiveInterviewConfig } from "../iris/interview/config.js";
18
22
  export const askCommand = new Command("ask")
19
23
  .description("Route intent to an agent and generate context pack")
20
24
  .argument("[intent...]", "Natural language request intent")
@@ -25,8 +29,12 @@ export const askCommand = new Command("ask")
25
29
  .option("--json", "Output structured JSON result", false)
26
30
  .option("--dry-run", "Simulate routing without writing files", false)
27
31
  .option("--debug", "Show IRIS authority and artifact resolution info", false)
32
+ .option("--non-interactive", "Skip interactive interview", false)
33
+ .option("--force-interactive", "Force interactive mode even in CI/Pipe", false)
34
+ .option("--save-draft-only", "Run interview and save draft, but do not execute workflow", false)
28
35
  .action(async (intentParts, opts) => {
29
36
  const root = repoRoot();
37
+ const { resolution } = await resolveActiveFramework(root);
30
38
  if (opts.debug) {
31
39
  const debug = getIrisDebugInfo(root);
32
40
  console.log(kleur.bold("IRIS Authority Debug"));
@@ -36,7 +44,7 @@ export const askCommand = new Command("ask")
36
44
  console.log(`- Bundled Path:${debug.bundledPath}`);
37
45
  console.log("");
38
46
  // Show artifact validation details
39
- const policy = loadPolicy();
47
+ const policy = loadPolicy(root);
40
48
  const state = loadState();
41
49
  const phase = state.phase.current;
42
50
  const requirements = policy.phases[phase]?.requires || [];
@@ -60,39 +68,143 @@ export const askCommand = new Command("ask")
60
68
  console.log("");
61
69
  }
62
70
  }
71
+ // Migration Check
72
+ const migrated = migrateLegacyDraft(root);
73
+ if (migrated) {
74
+ console.log(kleur.dim("Migrated old intent-draft.json to intent-draft.latest.json"));
75
+ }
63
76
  // 1. Get Intent
64
77
  let intent = intentParts.join(" ");
65
- if (!intent) {
66
- if (process.stdin.isTTY) {
67
- const { input } = await inquirer.prompt([
68
- { type: "input", name: "input", message: "What do you want to do?" }
78
+ // Environment Check
79
+ const envCheck = checkInteractiveMode({
80
+ nonInteractive: opts.nonInteractive,
81
+ forceInteractive: opts.forceInteractive
82
+ });
83
+ if (envCheck.isInteractive) {
84
+ // 1.5 Load Interview Config
85
+ // Skipped Legacy Interview - proceeding directly to Ping-Pong Flow
86
+ // If no intent provided yet, ask for just the one-liner intent
87
+ if (!intent) {
88
+ const { initialIntent } = await inquirer.prompt([
89
+ {
90
+ type: "input",
91
+ name: "initialIntent",
92
+ message: "What are you trying to build?",
93
+ validate: (val) => val.trim().length > 0 || "Please provide a goal."
94
+ }
69
95
  ]);
70
- intent = input;
96
+ intent = initialIntent;
71
97
  }
72
- else {
73
- intent = fs.readFileSync(0, "utf-8").trim();
98
+ }
99
+ else {
100
+ // NON-INTERACTIVE MODE
101
+ if (!opts.nonInteractive && !opts.forceInteractive) {
102
+ // Warn if we fell back automatically (reason exists)
103
+ if (envCheck.reason) {
104
+ console.warn(kleur.yellow(`⚠ Interactive mode disabled: ${envCheck.reason}`));
105
+ console.warn(kleur.dim(" Use --force-interactive to override if safe."));
106
+ }
107
+ }
108
+ // Fallback input reading
109
+ if (!intent) {
110
+ if (process.stdin.isTTY) {
111
+ console.error(kleur.red("Error: Intent argument required in non-interactive mode."));
112
+ process.exit(EXIT_CODES.INVALID);
113
+ return;
114
+ }
115
+ else {
116
+ try {
117
+ intent = fs.readFileSync(0, "utf-8").trim();
118
+ }
119
+ catch (e) {
120
+ // Ignore read error
121
+ }
122
+ }
74
123
  }
75
124
  }
76
125
  if (!intent) {
77
126
  console.error(kleur.red("No intent provided."));
78
127
  process.exit(EXIT_CODES.INVALID);
128
+ return; // TS Guard
79
129
  }
80
130
  // 2. Load Routes
81
- const routesConfig = loadRoutes();
82
- if (!routesConfig) {
83
- console.error(kleur.red("Routes not found. Run `iris install` or create .iris/routes.yaml"));
131
+ let routesConfig;
132
+ try {
133
+ const state = loadState();
134
+ // Load Base or Effective
135
+ routesConfig = loadEffectiveRoutes(resolution, root, state.active.flow);
136
+ }
137
+ catch (e) {
138
+ if (e.name === "RoutesOverlayMissingError") {
139
+ console.error(kleur.red(`\n[Policy Error] ${e.message}`));
140
+ process.exit(EXIT_CODES.POLICY_ERROR);
141
+ }
142
+ if (e.name === "RoutesLoadError") {
143
+ console.error(kleur.red(`\n[Routes Error] ${e.message}`));
144
+ if (e.cause)
145
+ console.error(kleur.gray(e.cause));
146
+ process.exit(EXIT_CODES.POLICY_ERROR);
147
+ }
148
+ // Fallback for unexpected
149
+ console.error(kleur.red(`Failed to load routes: ${e.message}`));
84
150
  process.exit(EXIT_CODES.POLICY_ERROR);
85
151
  }
86
152
  // 3. Route
87
153
  const routing = routeIntent(intent, routesConfig);
88
154
  const routeId = routing.route === "default" ? "default" : routing.route.route_id;
155
+ const source = routing.route !== "default" ? routing.route._source : "default";
156
+ if (opts.debug) {
157
+ console.log(kleur.bold(`Matched route_id: ${routeId} ${source ? `(source: ${source})` : ""}`));
158
+ }
89
159
  // 4. Execution Workflow (Inception + Planning)
160
+ if (opts.dryRun) {
161
+ // DRY RUN: Simulate pack generation
162
+ // We know intent, route, agent.
163
+ // We can create a Plan object.
164
+ const plan = {
165
+ schemaVersion: 1,
166
+ intent: intent,
167
+ framework: resolution ? resolution.manifest.id : "legacy-fallback",
168
+ route: {
169
+ id: routeId,
170
+ target: routing.route === "default" ? "default" : routing.route.agent,
171
+ score: routing.route === "default" ? 0 : routing.route.score
172
+ },
173
+ routesSource: {
174
+ kind: routesConfig?._meta?.sourceKind || (resolution ? 'framework' : 'legacy'),
175
+ path: routesConfig?._meta?.sourcePath || (resolution ? resolution.files.routes : resolveArtifactPath(root, ".iris/routes.yaml"))
176
+ },
177
+ interviewSource: (() => {
178
+ // We need to load it here for dry run to show source
179
+ const interviewConfig = loadEffectiveInterviewConfig(resolution);
180
+ const isFramework = !!(resolution?.files.interview);
181
+ return {
182
+ kind: isFramework ? 'framework' : 'default',
183
+ path: isFramework ? resolution?.files.interview : null,
184
+ activeFrameworkId: resolution?.manifest.id || null
185
+ };
186
+ })(),
187
+ pack: {
188
+ planned: true,
189
+ }
190
+ };
191
+ if (opts.json) {
192
+ console.log(JSON.stringify(plan, null, 2));
193
+ }
194
+ else {
195
+ console.log(kleur.yellow("[Dry Run] Routing Result:"));
196
+ console.log(JSON.stringify(plan, null, 2));
197
+ }
198
+ process.exit(0);
199
+ return;
200
+ }
90
201
  console.log(kleur.bold("Starting IRIS Inception & Planning"));
91
202
  console.log(kleur.dim("This process will clarify your intent and generate an implementation plan.\n"));
92
203
  // 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.
204
+ // Default to 'auto' (In-Process Agent) for seamless UX, ignoring detected IDE unless explicitly bridged?
205
+ // For now, satisfy user request: "Check user intent first".
206
+ // We will use "auto" as the default connector.
207
+ const ideId = "auto";
96
208
  // Create new run
97
209
  const runState = createRun(intent, ideId, "manual");
98
210
  const connector = createConnector(ideId);
@@ -107,14 +219,29 @@ export const askCommand = new Command("ask")
107
219
  gate: "manual",
108
220
  noBridge: false
109
221
  });
110
- console.log("");
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}`));
114
- console.log("");
222
+ const result = {
223
+ runId: runState.runId,
224
+ status: "plan_created",
225
+ planPath: path.join(root, ".iris/runs", runState.runId, "implementation_plan.md")
226
+ };
227
+ if (opts.json) {
228
+ console.log(JSON.stringify(result, null, 2));
229
+ }
230
+ else {
231
+ console.log("");
232
+ console.log(kleur.bold(kleur.green("✓ Plan Created Successfully!")));
233
+ console.log("To start execution, run:");
234
+ console.log(kleur.cyan(` iris develop --resume ${runState.runId}`));
235
+ console.log("");
236
+ }
115
237
  }
116
238
  catch (error) {
117
- console.error(kleur.red(`\n✗ Planning Failed: ${error.message}`));
239
+ if (opts.json) {
240
+ console.log(JSON.stringify({ error: error.message }, null, 2));
241
+ }
242
+ else {
243
+ console.error(kleur.red(`\n✗ Planning Failed: ${error.message}`));
244
+ }
118
245
  process.exit(1);
119
246
  }
120
247
  });
@@ -18,6 +18,14 @@ bridgeCommand
18
18
  verbose: true
19
19
  });
20
20
  });
21
+ // iris bridge serve
22
+ bridgeCommand
23
+ .command("serve")
24
+ .description("Start automated agent (Simulates AI response)")
25
+ .action(async () => {
26
+ const { startAgentRunner } = await import("../bridge/agent-runner.js");
27
+ await startAgentRunner({ verbose: true });
28
+ });
21
29
  // iris bridge status
22
30
  bridgeCommand
23
31
  .command("status")