project-iris 0.0.12 → 0.0.14

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 (189) hide show
  1. package/README.md +214 -323
  2. package/bin/cli.js +21 -0
  3. package/flows/aidlc/README.md +372 -0
  4. package/flows/aidlc/agents/construction-agent.md +79 -0
  5. package/flows/aidlc/agents/inception-agent.md +97 -0
  6. package/flows/aidlc/agents/master-agent.md +61 -0
  7. package/flows/aidlc/agents/operations-agent.md +89 -0
  8. package/flows/aidlc/commands/construction-agent.md +63 -0
  9. package/flows/aidlc/commands/inception-agent.md +55 -0
  10. package/flows/aidlc/commands/master-agent.md +47 -0
  11. package/flows/aidlc/commands/operations-agent.md +77 -0
  12. package/flows/aidlc/context-config.yaml +67 -0
  13. package/flows/aidlc/memory-bank.yaml +104 -0
  14. package/flows/aidlc/quick-start.md +322 -0
  15. package/flows/aidlc/skills/construction/bolt-list.md +163 -0
  16. package/flows/aidlc/skills/construction/bolt-replan.md +345 -0
  17. package/flows/aidlc/skills/construction/bolt-start.md +442 -0
  18. package/flows/aidlc/skills/construction/bolt-status.md +185 -0
  19. package/flows/aidlc/skills/construction/navigator.md +196 -0
  20. package/flows/aidlc/skills/inception/bolt-plan.md +372 -0
  21. package/flows/aidlc/skills/inception/context.md +171 -0
  22. package/flows/aidlc/skills/inception/intent-create.md +211 -0
  23. package/flows/aidlc/skills/inception/intent-list.md +124 -0
  24. package/flows/aidlc/skills/inception/navigator.md +207 -0
  25. package/flows/aidlc/skills/inception/requirements.md +227 -0
  26. package/flows/aidlc/skills/inception/review.md +248 -0
  27. package/flows/aidlc/skills/inception/story-create.md +304 -0
  28. package/flows/aidlc/skills/inception/units.md +278 -0
  29. package/flows/aidlc/skills/master/analyze-context.md +239 -0
  30. package/flows/aidlc/skills/master/answer-question.md +141 -0
  31. package/flows/aidlc/skills/master/explain-flow.md +158 -0
  32. package/flows/aidlc/skills/master/project-init.md +281 -0
  33. package/flows/aidlc/skills/master/route-request.md +126 -0
  34. package/flows/aidlc/skills/operations/build.md +237 -0
  35. package/flows/aidlc/skills/operations/deploy.md +259 -0
  36. package/flows/aidlc/skills/operations/monitor.md +265 -0
  37. package/flows/aidlc/skills/operations/navigator.md +209 -0
  38. package/flows/aidlc/skills/operations/verify.md +224 -0
  39. package/{dist/iris_bundle/frameworks/iris-core → flows/aidlc}/templates/construction/bolt-types/ddd-construction-bolt.md +3 -3
  40. package/{dist → flows/aidlc}/templates/construction/bolt-types/spike-bolt.md +2 -2
  41. package/flows/aidlc/templates/construction/construction-log-template.md +129 -0
  42. package/flows/aidlc/templates/construction/standards/coding-standards.md +29 -0
  43. package/flows/aidlc/templates/construction/standards/system-architecture.md +22 -0
  44. package/flows/aidlc/templates/construction/standards/tech-stack.md +19 -0
  45. package/flows/aidlc/templates/inception/inception-log-template.md +134 -0
  46. package/flows/aidlc/templates/inception/project/README.md +55 -0
  47. package/flows/aidlc/templates/standards/catalog.yaml +345 -0
  48. package/flows/aidlc/templates/standards/coding-standards.guide.md +553 -0
  49. package/flows/aidlc/templates/standards/data-stack.guide.md +162 -0
  50. package/flows/aidlc/templates/standards/tech-stack.guide.md +280 -0
  51. package/lib/InstallerFactory.js +36 -0
  52. package/lib/analytics/env-detector.js +92 -0
  53. package/lib/analytics/index.js +22 -0
  54. package/lib/analytics/machine-id.js +33 -0
  55. package/lib/analytics/tracker.js +232 -0
  56. package/lib/cli-utils.js +342 -0
  57. package/lib/constants.js +32 -0
  58. package/lib/installer.js +402 -0
  59. package/lib/installers/AntigravityInstaller.js +22 -0
  60. package/lib/installers/ClaudeInstaller.js +85 -0
  61. package/lib/installers/ClineInstaller.js +21 -0
  62. package/lib/installers/CodexInstaller.js +21 -0
  63. package/lib/installers/CopilotInstaller.js +113 -0
  64. package/lib/installers/CursorInstaller.js +63 -0
  65. package/lib/installers/GeminiInstaller.js +75 -0
  66. package/lib/installers/KiroInstaller.js +22 -0
  67. package/lib/installers/OpenCodeInstaller.js +22 -0
  68. package/lib/installers/RooInstaller.js +22 -0
  69. package/lib/installers/ToolInstaller.js +73 -0
  70. package/lib/installers/WindsurfInstaller.js +22 -0
  71. package/lib/markdown-validator.ts +175 -0
  72. package/lib/yaml-validator.ts +99 -0
  73. package/package.json +105 -32
  74. package/scripts/artifact-validator.js +594 -0
  75. package/scripts/bolt-complete.js +606 -0
  76. package/scripts/status-integrity.js +598 -0
  77. package/dist/bridge/agent-runner.js +0 -190
  78. package/dist/bridge/connector-factory.js +0 -31
  79. package/dist/bridge/connectors/antigravity-connector.js +0 -18
  80. package/dist/bridge/connectors/cursor-connector.js +0 -31
  81. package/dist/bridge/connectors/in-process-connector.js +0 -29
  82. package/dist/bridge/connectors/vscode-connector.js +0 -31
  83. package/dist/bridge/connectors/windsurf-connector.js +0 -23
  84. package/dist/bridge/filesystem-connector.js +0 -110
  85. package/dist/bridge/helper.js +0 -203
  86. package/dist/bridge/types.js +0 -10
  87. package/dist/cli.js +0 -40
  88. package/dist/commands/ask.js +0 -259
  89. package/dist/commands/bridge.js +0 -88
  90. package/dist/commands/create.js +0 -25
  91. package/dist/commands/develop.js +0 -141
  92. package/dist/commands/doctor.js +0 -102
  93. package/dist/commands/flow.js +0 -301
  94. package/dist/commands/framework.js +0 -273
  95. package/dist/commands/generate.js +0 -59
  96. package/dist/commands/install.js +0 -100
  97. package/dist/commands/pack.js +0 -33
  98. package/dist/commands/phase.js +0 -38
  99. package/dist/commands/run.js +0 -199
  100. package/dist/commands/status.js +0 -114
  101. package/dist/commands/uninstall.js +0 -14
  102. package/dist/commands/use.js +0 -20
  103. package/dist/commands/validate.js +0 -102
  104. package/dist/framework/framework-loader.js +0 -97
  105. package/dist/framework/framework-paths.js +0 -48
  106. package/dist/framework/framework-types.js +0 -15
  107. package/dist/iris/artifact-checker.js +0 -78
  108. package/dist/iris/artifacts/config.js +0 -68
  109. package/dist/iris/artifacts/generator.js +0 -88
  110. package/dist/iris/artifacts/types.js +0 -1
  111. package/dist/iris/bundle.js +0 -44
  112. package/dist/iris/doctrine/collector.js +0 -124
  113. package/dist/iris/fixer.js +0 -149
  114. package/dist/iris/flows/manifest.js +0 -124
  115. package/dist/iris/framework-context.js +0 -49
  116. package/dist/iris/framework-manager.js +0 -215
  117. package/dist/iris/fs/atomic.js +0 -22
  118. package/dist/iris/guard.js +0 -38
  119. package/dist/iris/importers/index.js +0 -9
  120. package/dist/iris/importers/types.js +0 -8
  121. package/dist/iris/importers/writer.js +0 -139
  122. package/dist/iris/include.js +0 -49
  123. package/dist/iris/installer.js +0 -334
  124. package/dist/iris/interactive/env.js +0 -21
  125. package/dist/iris/interactive/intent-interview.js +0 -345
  126. package/dist/iris/interactive/intent-schema.js +0 -28
  127. package/dist/iris/interactive/interview-io.js +0 -22
  128. package/dist/iris/interview/config.js +0 -71
  129. package/dist/iris/interview/types.js +0 -16
  130. package/dist/iris/interview/utils.js +0 -38
  131. package/dist/iris/manifest.js +0 -54
  132. package/dist/iris/packer.js +0 -325
  133. package/dist/iris/parsers/unit-parser.js +0 -43
  134. package/dist/iris/paths.js +0 -18
  135. package/dist/iris/policy.js +0 -133
  136. package/dist/iris/proc.js +0 -56
  137. package/dist/iris/report.js +0 -53
  138. package/dist/iris/resolver.js +0 -66
  139. package/dist/iris/router.js +0 -114
  140. package/dist/iris/routes.js +0 -189
  141. package/dist/iris/run-state.js +0 -146
  142. package/dist/iris/state.js +0 -113
  143. package/dist/iris/templates.js +0 -70
  144. package/dist/iris/tmp.js +0 -24
  145. package/dist/iris/uninstaller.js +0 -181
  146. package/dist/iris/utils/interpolate.js +0 -42
  147. package/dist/iris/validator.js +0 -391
  148. package/dist/iris/workflow/config.js +0 -51
  149. package/dist/iris/workflow/engine.js +0 -129
  150. package/dist/iris/workflow/steps.js +0 -448
  151. package/dist/iris/workflow/types.js +0 -1
  152. package/dist/iris_bundle/frameworks/iris-core/framework.yaml +0 -9
  153. package/dist/iris_bundle/frameworks/iris-core/memory/memory-bank.yaml +0 -1
  154. package/dist/iris_bundle/frameworks/iris-core/policy.yaml +0 -7
  155. package/dist/iris_bundle/frameworks/iris-core/templates/config/memory-bank.yaml +0 -1
  156. package/dist/iris_bundle/frameworks/iris-core/templates/construction/bolt-types/spike-bolt.md +0 -240
  157. package/dist/lib.js +0 -96
  158. package/dist/templates/construction/bolt-template.md +0 -226
  159. package/dist/templates/construction/bolt-types/ddd-construction-bolt/adr-template.md +0 -49
  160. package/dist/templates/construction/bolt-types/ddd-construction-bolt/ddd-01-domain-model-template.md +0 -55
  161. package/dist/templates/construction/bolt-types/ddd-construction-bolt/ddd-02-technical-design-template.md +0 -67
  162. package/dist/templates/construction/bolt-types/ddd-construction-bolt/ddd-03-test-report-template.md +0 -62
  163. package/dist/templates/construction/bolt-types/ddd-construction-bolt.md +0 -528
  164. package/dist/templates/construction/bolt-types/simple-construction-bolt.md +0 -347
  165. package/dist/templates/inception/requirements-template.md +0 -144
  166. package/dist/templates/inception/stories-template.md +0 -38
  167. package/dist/templates/inception/story-template.md +0 -147
  168. package/dist/templates/inception/system-context-template.md +0 -29
  169. package/dist/templates/inception/unit-brief-template.md +0 -177
  170. package/dist/templates/inception/units-template.md +0 -52
  171. package/dist/utils/exit-codes.js +0 -7
  172. package/dist/utils/logo.js +0 -17
  173. package/dist/workflows/bolt-execution.js +0 -238
  174. package/dist/workflows/bolt-plan.js +0 -221
  175. package/dist/workflows/intent-inception.js +0 -285
  176. package/dist/workflows/memory-bank-generator.js +0 -180
  177. package/dist/workflows/reporting.js +0 -74
  178. /package/{dist/iris_bundle/frameworks/iris-core → flows/aidlc}/templates/construction/bolt-template.md +0 -0
  179. /package/{dist/iris_bundle/frameworks/iris-core → flows/aidlc}/templates/construction/bolt-types/ddd-construction-bolt/adr-template.md +0 -0
  180. /package/{dist/iris_bundle/frameworks/iris-core → flows/aidlc}/templates/construction/bolt-types/ddd-construction-bolt/ddd-01-domain-model-template.md +0 -0
  181. /package/{dist/iris_bundle/frameworks/iris-core → flows/aidlc}/templates/construction/bolt-types/ddd-construction-bolt/ddd-02-technical-design-template.md +0 -0
  182. /package/{dist/iris_bundle/frameworks/iris-core → flows/aidlc}/templates/construction/bolt-types/ddd-construction-bolt/ddd-03-test-report-template.md +0 -0
  183. /package/{dist/iris_bundle/frameworks/iris-core → flows/aidlc}/templates/construction/bolt-types/simple-construction-bolt.md +0 -0
  184. /package/{dist/iris_bundle/frameworks/iris-core → flows/aidlc}/templates/inception/requirements-template.md +0 -0
  185. /package/{dist/iris_bundle/frameworks/iris-core → flows/aidlc}/templates/inception/stories-template.md +0 -0
  186. /package/{dist/iris_bundle/frameworks/iris-core → flows/aidlc}/templates/inception/story-template.md +0 -0
  187. /package/{dist/iris_bundle/frameworks/iris-core → flows/aidlc}/templates/inception/system-context-template.md +0 -0
  188. /package/{dist/iris_bundle/frameworks/iris-core → flows/aidlc}/templates/inception/unit-brief-template.md +0 -0
  189. /package/{dist/iris_bundle/frameworks/iris-core → flows/aidlc}/templates/inception/units-template.md +0 -0
@@ -1,301 +0,0 @@
1
- import { Command } from "commander";
2
- import kleur from "kleur";
3
- import { repoRoot, ensureDir } from "../lib.js";
4
- import { loadState, saveState } from "../iris/state.js";
5
- import { listInstalledFlows, loadFlowManifest } from "../iris/flows/manifest.js";
6
- import { loadEffectivePolicy } from "../iris/policy.js";
7
- import { loadEffectiveRoutes } from "../iris/routes.js";
8
- import { validate } from "../iris/validator.js";
9
- import { printReport } from "../iris/report.js";
10
- import { EXIT_CODES } from "../utils/exit-codes.js";
11
- import { getBundledFlowsDir, listBundledFlows } from "../iris/bundle.js";
12
- import fs from "fs";
13
- import path from "path";
14
- import { getImporter } from "../iris/importers/index.js";
15
- import { ensureDoctrineOnlyFlowInstalled } from "../iris/importers/writer.js";
16
- import { makeTempDir, removeTempDir } from "../iris/tmp.js";
17
- import { ImporterError } from "../iris/importers/types.js";
18
- const importFlowCommand = new Command("import")
19
- .description("Import an external methodology as a doctrine-only flow (DEPRECATED)")
20
- .argument("<provider>", "Provider ID")
21
- .option("-f, --force", "Overwrite existing files", false)
22
- .option("-d, --dry-run", "Simulate import without writing files", false)
23
- .option("-v, --verbose", "Show detailed output", false)
24
- .action(async (providerId, options) => {
25
- const root = repoRoot();
26
- const importer = getImporter(providerId);
27
- if (!importer) {
28
- console.error(kleur.red(`No import providers available.`));
29
- console.log(kleur.yellow("IRIS ships only iris-core. External imports are not supported for now."));
30
- process.exit(1);
31
- }
32
- console.log(kleur.bold(`Importing '${importer.displayName}'...`));
33
- if (options.dryRun)
34
- console.log(kleur.yellow("[Dry Run Mode]"));
35
- console.warn(kleur.yellow("IRIS_WARNING IRIS_FLOW_IMPORT_DEPRECATED: use \"iris framework install <id>\" instead."));
36
- let tempDir = "";
37
- try {
38
- tempDir = makeTempDir(providerId);
39
- if (options.verbose)
40
- console.log(kleur.dim(`Temporary workspace: ${tempDir}`));
41
- // 1. Run Installer
42
- try {
43
- await importer.runInstaller({
44
- repoRoot: root,
45
- tempDir,
46
- provider: providerId,
47
- force: options.force,
48
- dryRun: options.dryRun,
49
- verbose: options.verbose
50
- });
51
- }
52
- catch (e) {
53
- if (e instanceof ImporterError && e.exitCode === 4) {
54
- // Policy/Not Supported error (e.g. Speckit)
55
- // Print friendly message and exit cleanly without stack trace
56
- console.error(kleur.yellow(e.message));
57
- process.exit(4);
58
- }
59
- throw e;
60
- }
61
- // 2. Detect Templates
62
- const { templateDirs } = await importer.detectDoctrineRoots({
63
- repoRoot: root,
64
- tempDir,
65
- provider: providerId,
66
- force: options.force,
67
- dryRun: options.dryRun,
68
- verbose: options.verbose
69
- });
70
- if (options.verbose) {
71
- console.log(kleur.dim(`Detected template roots: ${templateDirs.length > 0 ? templateDirs.join(", ") : "None"}`));
72
- }
73
- // 3. Install
74
- const result = ensureDoctrineOnlyFlowInstalled({
75
- repoRoot: root,
76
- flowId: providerId,
77
- displayName: importer.displayName,
78
- sourceTemplateDirs: templateDirs,
79
- force: options.force,
80
- dryRun: options.dryRun,
81
- verbose: options.verbose
82
- });
83
- if (result.installedDir && !options.dryRun) {
84
- // 4. Validate
85
- try {
86
- loadFlowManifest(root, providerId);
87
- }
88
- catch (e) {
89
- console.warn(kleur.yellow("\nWarning: Imported flow structure seems invalid:"));
90
- console.warn(kleur.red(e.message));
91
- }
92
- }
93
- // Summary
94
- console.log(kleur.green(`\n✓ Imported ${importer.displayName} as flow '${providerId}'`));
95
- if (options.dryRun) {
96
- console.log(kleur.dim(` [Dry Run] Would copy: ${result.copiedFiles}, Skip: ${result.skippedFiles}, Overwrite: ${result.overwrittenFiles}`));
97
- }
98
- else {
99
- console.log(kleur.dim(` Files: ${result.copiedFiles} created, ${result.skippedFiles} skipped, ${result.overwrittenFiles} overwritten.`));
100
- console.log(kleur.dim(` Templates: .iris/flows/${providerId}/doctrine/templates/${providerId}/...`));
101
- console.log(`\nTo activate, run: ${kleur.cyan(`iris flow use ${providerId}`)}`);
102
- console.log(kleur.gray(`This will make the '${importer.displayName}' templates available to doctrine.`));
103
- }
104
- }
105
- catch (e) {
106
- console.error(kleur.red(`\nImport failed: ${e.message}`));
107
- if (options.verbose && e.stack)
108
- console.error(kleur.dim(e.stack));
109
- // Rollback: If we created a directory but failed, remove it
110
- // We need to know the target dir. It's safe to assume .iris/flows/<providerId>
111
- const flowDir = path.join(root, ".iris/flows", providerId);
112
- if (!options.dryRun && fs.existsSync(flowDir)) {
113
- // Only rollback if we created it in this run?
114
- // It's hard to track perfectly without more state, but for safety in "import"
115
- // if it failed, leaving a partial flow is bad.
116
- // Limitation: If we were updating (--force) and failed, we might lose the original flow.
117
- // Risk acceptance: --force implies destructive.
118
- // For new installs, this is safe.
119
- try {
120
- // Check if it looks like a partial install? or just nuke it.
121
- console.log(kleur.yellow(`Rolling back partial installation at ${flowDir}...`));
122
- fs.rmSync(flowDir, { recursive: true, force: true });
123
- }
124
- catch (cleanupErr) {
125
- console.error(kleur.red(`Failed to rollback: ${cleanupErr}`));
126
- }
127
- }
128
- // Ensure we don't return 0
129
- process.exit(1);
130
- }
131
- finally {
132
- if (tempDir) {
133
- removeTempDir(tempDir);
134
- if (options.verbose)
135
- console.log(kleur.dim("Cleaned up temp workspace."));
136
- }
137
- }
138
- });
139
- const installCommand = new Command("install")
140
- .description("Install a flow from the bundle")
141
- .argument("<flowId>", "ID of the flow to install")
142
- .option("-f, --force", "Overwrite existing files", false)
143
- .action((flowId, options) => {
144
- const root = repoRoot();
145
- const bundledFlowsDir = getBundledFlowsDir();
146
- const sourceDir = path.join(bundledFlowsDir, flowId);
147
- // 1. Check Source
148
- if (!fs.existsSync(sourceDir)) {
149
- console.error(kleur.red(`Bundled flow '${flowId}' not found.`));
150
- const available = listBundledFlows();
151
- if (available.length > 0) {
152
- console.log(kleur.cyan("Available flows:"));
153
- available.forEach(id => console.log(` - ${id}`));
154
- }
155
- process.exit(1);
156
- }
157
- const targetDir = path.join(root, ".iris/flows", flowId);
158
- console.log(kleur.bold(`Installing flow '${flowId}' to .iris/flows/${flowId}...`));
159
- // 2. Install (Recursive Copy with stats)
160
- const stats = { installed: 0, skipped: 0, overwritten: 0 };
161
- function copyRec(src, dest) {
162
- ensureDir(dest);
163
- const entries = fs.readdirSync(src, { withFileTypes: true });
164
- for (const entry of entries) {
165
- const srcPath = path.join(src, entry.name);
166
- const destPath = path.join(dest, entry.name);
167
- if (entry.isDirectory()) {
168
- copyRec(srcPath, destPath);
169
- }
170
- else if (entry.isFile()) {
171
- if (fs.existsSync(destPath)) {
172
- if (options.force) {
173
- fs.copyFileSync(srcPath, destPath);
174
- stats.overwritten++;
175
- // console.log(kleur.gray(` Overwrote ${entry.name}`));
176
- }
177
- else {
178
- stats.skipped++;
179
- // console.log(kleur.gray(` Skipped ${entry.name} (exists)`));
180
- }
181
- }
182
- else {
183
- fs.copyFileSync(srcPath, destPath);
184
- stats.installed++;
185
- // console.log(kleur.green(` Created ${entry.name}`));
186
- }
187
- }
188
- }
189
- }
190
- try {
191
- copyRec(sourceDir, targetDir);
192
- }
193
- catch (e) {
194
- console.error(kleur.red(`Installation failed: ${e.message}`));
195
- process.exit(1);
196
- }
197
- // 3. Post-Install Validation
198
- try {
199
- loadFlowManifest(root, flowId);
200
- // Optional: Check existence of overlays explicitly if manifest says so?
201
- // loadFlowManifest checks structure.
202
- // We can trust it for now or do improved checks later.
203
- }
204
- catch (e) {
205
- console.error(kleur.yellow(`\nWarning: Installed flow '${flowId}' seems invalid:`));
206
- console.error(kleur.red(e.message));
207
- console.log("Installation completed but flow may not work.");
208
- process.exit(1);
209
- }
210
- console.log(kleur.green(`\n✓ Flow '${flowId}' installed successfully.`));
211
- console.log(kleur.dim(` Files: ${stats.installed} created, ${stats.overwritten} overwritten, ${stats.skipped} skipped.`));
212
- console.log(`\nTo activate, run: ${kleur.cyan(`iris flow use ${flowId}`)}`);
213
- });
214
- const listCommand = new Command("list")
215
- .description("List installed flows")
216
- .action(() => {
217
- const root = repoRoot();
218
- const state = loadState();
219
- const flows = listInstalledFlows(root);
220
- if (flows.length === 0) {
221
- console.log(kleur.gray("No flows installed."));
222
- return;
223
- }
224
- console.log(kleur.bold("\nInstalled Flows:"));
225
- for (const flow of flows) {
226
- const isActive = state.active.flow === flow.id;
227
- const status = isActive ? kleur.green("(active)") : "";
228
- const line = `${kleur.cyan(flow.id.padEnd(20))} ${flow.name} ${kleur.dim(flow.version)} ${status}`;
229
- console.log(line);
230
- }
231
- console.log("");
232
- });
233
- const useCommand = new Command("use")
234
- .description("Switch the active flow")
235
- .argument("<flowId>", "ID of the flow to switch to")
236
- .action(async (flowId) => {
237
- const root = repoRoot();
238
- const state = loadState();
239
- if (state.active.flow === flowId) {
240
- console.log(kleur.yellow(`Flow '${flowId}' is already active.`));
241
- return;
242
- }
243
- // 1. Safety Check (Dry Run)
244
- // Verify we can load policy and routes BEFORE switching
245
- try {
246
- console.log(kleur.dim(`Verifying flow '${flowId}' integrity...`));
247
- // Check manifest existence implicit in these loaders (via loadFlowManifest)
248
- // Resolve framework to ensure compatibility (best effort check)
249
- // We import resolveActiveFramework dynamically or add import?
250
- // Better to rely on null if we don't want to async resolve here?
251
- // Actually useCommand IS async action.
252
- // But we need to import resolveActiveFramework.
253
- // Let's pass null for framework for now to just check OVERLAY existence,
254
- // unless we want strict framework compatibility check.
255
- // Step 1 logic implies overlays are valid if files exist.
256
- // NOTE: Changing signature to (null, root, flowId) due to refactor
257
- loadEffectivePolicy(null, root, flowId);
258
- console.log(kleur.dim(" Policy overlay: OK"));
259
- loadEffectiveRoutes(null, root, flowId);
260
- console.log(kleur.dim(" Routes overlay: OK"));
261
- }
262
- catch (e) {
263
- console.error(kleur.red(`\nCannot switch to flow '${flowId}':`));
264
- if (e.name === "PolicyOverlayMissingError" || e.name === "RoutesOverlayMissingError") {
265
- console.error(kleur.red(` ${e.message}`));
266
- console.error(kleur.yellow(" This flow is broken (missing required overlay). Fix it or reinstall."));
267
- }
268
- else if (e.name === "FlowNotFoundError") {
269
- console.error(kleur.red(` Flow '${flowId}' is not installed.`));
270
- }
271
- else {
272
- console.error(kleur.red(` ${e.message}`));
273
- if (e.cause)
274
- console.error(kleur.gray(` Cause: ${e.cause}`));
275
- }
276
- process.exit(EXIT_CODES.POLICY_ERROR);
277
- }
278
- // 2. Update State
279
- state.active.flow = flowId;
280
- saveState(state);
281
- console.log(kleur.green(`Switched to flow: ${flowId}`));
282
- // 3. Run Validation (Info only)
283
- console.log(kleur.dim("Validating new requirements..."));
284
- const result = await validate({
285
- apply: false,
286
- strict: false,
287
- writeBack: false // Don't verify/update validation timestamp just for this check? Or yes?
288
- // "validates manifest exists and sets state... then runs validate (non-fix) to show new requirements"
289
- // Usually we want to show the report.
290
- });
291
- printReport(result, false);
292
- if (!result.valid) {
293
- console.log(kleur.yellow("\nNote: You may need to satisfy new requirements. Run 'iris fix' or 'iris validate'."));
294
- }
295
- });
296
- export const flowCommand = new Command("flow")
297
- .description("Manage active flows")
298
- .addCommand(listCommand)
299
- .addCommand(installCommand)
300
- .addCommand(importFlowCommand)
301
- .addCommand(useCommand);
@@ -1,273 +0,0 @@
1
- import { Command } from "commander";
2
- import kleur from "kleur";
3
- import { loadState, getActiveFramework, setActiveFramework } from "../iris/state.js";
4
- import { loadFramework } from "../framework/framework-loader.js";
5
- import { repoRoot } from "../lib.js";
6
- import { listInstalledFrameworks, listBundledFrameworks, installFrameworkFromPath, installBundledFramework, removeFramework, validateFrameworkParams } from "../iris/framework-manager.js";
7
- export const frameworkCommand = new Command("framework")
8
- .description("Manage IRIS frameworks");
9
- frameworkCommand
10
- .command("current")
11
- .description("Show the currently active framework")
12
- .option("--json", "Output as JSON")
13
- .action(async (options) => {
14
- const state = loadState();
15
- const active = getActiveFramework(state);
16
- const root = repoRoot();
17
- let resolution = null;
18
- let error = null;
19
- try {
20
- resolution = await loadFramework(active.current, { repoRoot: root });
21
- }
22
- catch (e) {
23
- error = e;
24
- }
25
- if (options.json) {
26
- console.log(JSON.stringify({
27
- schemaVersion: 1,
28
- active: {
29
- id: active.current,
30
- version: active.version
31
- },
32
- resolved: !!resolution,
33
- rootDir: resolution?.rootDir || null,
34
- source: resolution ? {
35
- kind: resolution.source.kind,
36
- path: resolution.source.path,
37
- ...(resolution.source.id ? { id: resolution.source.id } : {})
38
- } : null,
39
- error: error ? {
40
- code: error.code || 'UNKNOWN',
41
- path: error.path || null,
42
- hint: error.hint || null
43
- } : null
44
- }, null, 2));
45
- return;
46
- }
47
- // Human output
48
- console.log("");
49
- if (resolution) {
50
- console.log(kleur.bold(`Active Framework: ${kleur.green(active.current)}`));
51
- if (active.version) {
52
- console.log(`Version Pin: ${kleur.cyan(active.version)}`);
53
- }
54
- console.log(kleur.gray(`Location: ${resolution.rootDir}`));
55
- if (resolution.manifest.version) {
56
- console.log(`Manifest Version: ${resolution.manifest.version}`);
57
- }
58
- }
59
- else {
60
- console.log(kleur.bold(`Active Framework: ${kleur.yellow(active.current)} (Not Found)`));
61
- if (active.version) {
62
- console.log(`Version Pin: ${kleur.cyan(active.version)}`);
63
- }
64
- console.log(kleur.red(`Error: ${error?.message || "Could not resolve framework"}`));
65
- if (error?.hint) {
66
- console.log(kleur.gray(`Hint: ${error.hint}`));
67
- }
68
- }
69
- });
70
- frameworkCommand
71
- .command("use")
72
- .description("Switch the active framework")
73
- .argument("<id>", "Framework ID (can include @version)")
74
- .option("--strict", "Fail if framework cannot be resolved")
75
- .action(async (idStr, options) => {
76
- // Parse ID and Version
77
- const lastAt = idStr.lastIndexOf('@');
78
- let id = idStr;
79
- let version = null;
80
- if (lastAt > 0) {
81
- id = idStr.substring(0, lastAt);
82
- version = idStr.substring(lastAt + 1);
83
- }
84
- const root = repoRoot();
85
- const state = loadState();
86
- // Check if resolvable
87
- try {
88
- await loadFramework(id, { repoRoot: root });
89
- }
90
- catch (error) {
91
- if (options.strict) {
92
- console.error(kleur.red(`Error: Framework '${id}' not found.`));
93
- console.error(kleur.gray(error.message));
94
- process.exit(1);
95
- }
96
- else {
97
- console.warn(kleur.yellow(`Warning: Framework '${id}' could not be resolved. Setting anyway.`));
98
- }
99
- }
100
- setActiveFramework(state, id, version);
101
- console.log(kleur.green(`✓ Set active framework to: ${kleur.bold(id)}`));
102
- if (version) {
103
- console.log(kleur.cyan(` Pinned version: ${version}`));
104
- }
105
- });
106
- frameworkCommand
107
- .command("list")
108
- .description("List installed and available frameworks")
109
- .action(async () => {
110
- const root = repoRoot();
111
- const installed = await listInstalledFrameworks(root);
112
- const bundled = await listBundledFrameworks();
113
- // Merge strategy: map by ID
114
- const map = new Map();
115
- for (const i of installed) {
116
- if (!map.has(i.id))
117
- map.set(i.id, {});
118
- map.get(i.id).installed = i;
119
- }
120
- for (const b of bundled) {
121
- if (!map.has(b.id))
122
- map.set(b.id, {});
123
- map.get(b.id).bundled = b;
124
- }
125
- console.log(kleur.bold("\nFrameworks:\n"));
126
- // Output format
127
- // ID Version Status
128
- const sortedIds = Array.from(map.keys()).sort();
129
- for (const id of sortedIds) {
130
- const entry = map.get(id);
131
- const inst = entry.installed;
132
- const bund = entry.bundled;
133
- let status = "";
134
- let version = "";
135
- let meta = "";
136
- if (inst) {
137
- version = inst.version || "???";
138
- if (inst.active)
139
- status = kleur.green("Active");
140
- else if (inst.valid)
141
- status = "Installed";
142
- else
143
- status = kleur.red("Broken");
144
- if (bund)
145
- meta = kleur.gray("(Bundled available)");
146
- }
147
- else if (bund) {
148
- version = bund.version || "bundled";
149
- status = kleur.dim("Bundled");
150
- meta = kleur.gray("(Use 'iris framework install' to install)");
151
- }
152
- console.log(` ${kleur.bold(id.padEnd(20))} ${version.padEnd(10)} ${status.padEnd(15)} ${meta}`);
153
- if (inst?.error) {
154
- console.log(kleur.red(` Error: ${inst.error.message}`));
155
- }
156
- }
157
- console.log("");
158
- });
159
- frameworkCommand
160
- .command("add")
161
- .description("Install a framework from a local directory")
162
- .argument("<path>", "Path to framework folder")
163
- .option("-f, --force", "Overwrite existing framework if present")
164
- .action(async (srcPath, options) => {
165
- const root = repoRoot();
166
- try {
167
- const result = await installFrameworkFromPath(root, srcPath, { force: options.force });
168
- console.log(kleur.green(`✓ Added framework '${result.id}' (v${result.version})`));
169
- console.log(kleur.gray(` Installed to: ${result.path}`));
170
- }
171
- catch (error) {
172
- console.error(kleur.red(`Error: ${error.message}`));
173
- if (error.hint)
174
- console.error(kleur.gray(`Hint: ${error.hint}`));
175
- process.exit(1);
176
- }
177
- });
178
- frameworkCommand
179
- .command("install")
180
- .description("Install a bundled framework")
181
- .argument("<id>", "Framework ID")
182
- .option("-f, --force", "Overwrite existing framework if present")
183
- .action(async (id, options) => {
184
- const root = repoRoot();
185
- try {
186
- const result = await installBundledFramework(root, id, { force: options.force });
187
- console.log(kleur.green(`✓ Installed framework '${result.id}' (v${result.version})`));
188
- }
189
- catch (error) {
190
- console.error(kleur.red(`Error: ${error.message}`));
191
- process.exit(1);
192
- }
193
- });
194
- frameworkCommand
195
- .command("remove")
196
- .description("Remove an installed framework")
197
- .argument("<id>", "Framework ID")
198
- .action((id) => {
199
- const root = repoRoot();
200
- try {
201
- removeFramework(root, id);
202
- console.log(kleur.green(`✓ Removed framework '${id}'`));
203
- }
204
- catch (error) {
205
- console.error(kleur.red(`Error: ${error.message}`));
206
- if (error.hint)
207
- console.error(kleur.gray(`Hint: ${error.hint}`));
208
- process.exit(1);
209
- }
210
- });
211
- frameworkCommand
212
- .command("validate")
213
- .description("Validate a framework")
214
- .argument("<input>", "Framework ID or Path")
215
- .option("--json", "Output as JSON")
216
- .action(async (input, options) => {
217
- const root = repoRoot();
218
- let result = null;
219
- let error = null;
220
- try {
221
- result = await validateFrameworkParams(input, root);
222
- }
223
- catch (e) {
224
- error = e;
225
- }
226
- if (options.json) {
227
- console.log(JSON.stringify({
228
- schemaVersion: 1,
229
- ok: !error,
230
- id: result?.manifest?.id || null,
231
- rootDir: result?.rootDir || null,
232
- files: result?.files ? {
233
- policy: !!result.files.policy,
234
- routes: !!result.files.routes,
235
- interview: !!result.files.interview,
236
- pack: !!result.files.pack,
237
- templates: !!result.files.templates
238
- } : null,
239
- warnings: [], // Todo: collecting warnings?
240
- error: error ? {
241
- code: error.code || 'UNKNOWN',
242
- message: error.message,
243
- path: error.path
244
- } : null
245
- }, null, 2));
246
- return;
247
- }
248
- if (error) {
249
- console.error(kleur.red(`Validation Failed:`));
250
- console.error(kleur.red(` ${error.message}`));
251
- if (error.path)
252
- console.error(` Path: ${error.path}`);
253
- if (error.hint)
254
- console.error(kleur.gray(` Hint: ${error.hint}`));
255
- process.exit(1);
256
- }
257
- else {
258
- console.log(kleur.green(`✓ Framework '${result.manifest.id}' is valid.`));
259
- console.log(kleur.gray(` Location: ${result.rootDir}`));
260
- console.log(` Version: ${result.manifest.version}`);
261
- // List found files?
262
- const files = [];
263
- if (result.files.policy)
264
- files.push("Policy");
265
- if (result.files.routes)
266
- files.push("Routes");
267
- if (result.files.interview)
268
- files.push("Interview");
269
- if (result.files.templates)
270
- files.push("Templates");
271
- console.log(` Components: ${files.join(", ")}`);
272
- }
273
- });
@@ -1,59 +0,0 @@
1
- import { Command } from "commander";
2
- import path from "path";
3
- import fs from "fs";
4
- import kleur from "kleur";
5
- import { resolveActiveFramework } from "../iris/framework-context.js";
6
- import { loadEffectiveArtifactsConfig } from "../iris/artifacts/config.js";
7
- import { generateArtifacts } from "../iris/artifacts/generator.js";
8
- export const generateCommand = new Command("generate")
9
- .alias("gen")
10
- .description("Synthesize artifacts from an intent draft")
11
- .option("-i, --in <path>", "Input draft file (default: .iris/inbox/intent-draft.latest.json)")
12
- .option("-o, --out <path>", "Output artifacts file")
13
- .option("--json", "Output JSON to stdout")
14
- .action(async (opts) => {
15
- try {
16
- // 1. Resolve Framework
17
- const root = process.cwd();
18
- const projectRoot = root; // Assume CWD is root for now
19
- const { resolution } = await resolveActiveFramework(projectRoot);
20
- // resolveActiveFramework returns { resolution, activeFlowId? }
21
- const artifactsConfig = loadEffectiveArtifactsConfig(resolution);
22
- // 2. Load Draft
23
- let draftPath = opts.in;
24
- if (!draftPath) {
25
- draftPath = path.join(projectRoot, ".iris", "inbox", "intent-draft.latest.json");
26
- }
27
- else {
28
- draftPath = path.resolve(process.cwd(), draftPath); // Resolve relative to CWD
29
- }
30
- if (!fs.existsSync(draftPath)) {
31
- console.error(kleur.red(`Error: Draft file not found at ${draftPath}`));
32
- process.exit(1);
33
- }
34
- const draftContent = fs.readFileSync(draftPath, "utf8");
35
- const draft = JSON.parse(draftContent);
36
- // 3. Generate
37
- const output = generateArtifacts(draft, artifactsConfig, resolution);
38
- // 4. Output
39
- const jsonStr = JSON.stringify(output, null, 2);
40
- if (opts.out) {
41
- const outPath = path.resolve(process.cwd(), opts.out);
42
- fs.mkdirSync(path.dirname(outPath), { recursive: true });
43
- fs.writeFileSync(outPath, jsonStr);
44
- if (!opts.json) {
45
- console.log(kleur.green(`Artifacts generated at ${outPath}`));
46
- }
47
- }
48
- else if (!opts.json) {
49
- console.log(jsonStr);
50
- }
51
- if (opts.json) {
52
- console.log(jsonStr);
53
- }
54
- }
55
- catch (error) {
56
- console.error(kleur.red(`Generation Failed: ${error.message}`));
57
- process.exit(1);
58
- }
59
- });