project-iris 0.0.8 → 0.0.12

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 (160) 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 +12 -2
  7. package/dist/commands/ask.js +150 -23
  8. package/dist/commands/bridge.js +8 -0
  9. package/dist/commands/create.js +25 -0
  10. package/dist/commands/flow.js +301 -0
  11. package/dist/commands/framework.js +273 -0
  12. package/dist/commands/generate.js +59 -0
  13. package/dist/commands/install.js +72 -29
  14. package/dist/commands/pack.js +7 -1
  15. package/dist/commands/run.js +195 -13
  16. package/dist/commands/status.js +9 -0
  17. package/dist/commands/uninstall.js +3 -1
  18. package/dist/commands/use.js +20 -0
  19. package/dist/commands/validate.js +80 -65
  20. package/dist/framework/framework-loader.js +97 -0
  21. package/dist/framework/framework-paths.js +48 -0
  22. package/dist/framework/framework-types.js +15 -0
  23. package/dist/iris/artifacts/config.js +68 -0
  24. package/dist/iris/artifacts/generator.js +88 -0
  25. package/dist/iris/artifacts/types.js +1 -0
  26. package/dist/iris/bundle.js +44 -0
  27. package/dist/iris/doctrine/collector.js +124 -0
  28. package/dist/iris/fixer.js +28 -22
  29. package/dist/iris/flows/manifest.js +124 -0
  30. package/dist/iris/framework-context.js +49 -0
  31. package/dist/iris/framework-manager.js +215 -0
  32. package/dist/iris/fs/atomic.js +22 -0
  33. package/dist/iris/importers/index.js +9 -0
  34. package/dist/iris/importers/types.js +8 -0
  35. package/dist/iris/importers/writer.js +139 -0
  36. package/dist/iris/installer.js +105 -40
  37. package/dist/iris/interactive/env.js +21 -0
  38. package/dist/iris/interactive/intent-interview.js +345 -0
  39. package/dist/iris/interactive/intent-schema.js +28 -0
  40. package/dist/iris/interactive/interview-io.js +22 -0
  41. package/dist/iris/interview/config.js +71 -0
  42. package/dist/iris/interview/types.js +16 -0
  43. package/dist/iris/interview/utils.js +38 -0
  44. package/dist/iris/packer.js +69 -47
  45. package/dist/iris/parsers/unit-parser.js +43 -0
  46. package/dist/iris/paths.js +18 -0
  47. package/dist/iris/policy.js +122 -17
  48. package/dist/iris/proc.js +56 -0
  49. package/dist/iris/resolver.js +3 -0
  50. package/dist/iris/routes.js +180 -11
  51. package/dist/iris/run-state.js +3 -0
  52. package/dist/iris/state.js +37 -9
  53. package/dist/iris/templates.js +70 -0
  54. package/dist/iris/tmp.js +24 -0
  55. package/dist/iris/uninstaller.js +24 -9
  56. package/dist/iris/utils/interpolate.js +42 -0
  57. package/dist/iris/validator.js +72 -10
  58. package/dist/iris/workflow/config.js +51 -0
  59. package/dist/iris/workflow/engine.js +129 -0
  60. package/dist/iris/workflow/steps.js +448 -0
  61. package/dist/iris/workflow/types.js +1 -0
  62. package/dist/iris_bundle/frameworks/iris-core/framework.yaml +9 -0
  63. package/dist/iris_bundle/frameworks/iris-core/memory/memory-bank.yaml +1 -0
  64. package/dist/iris_bundle/frameworks/iris-core/policy.yaml +7 -0
  65. package/dist/iris_bundle/frameworks/iris-core/templates/config/memory-bank.yaml +1 -0
  66. package/dist/iris_bundle/frameworks/iris-core/templates/construction/bolt-template.md +226 -0
  67. package/dist/iris_bundle/frameworks/iris-core/templates/construction/bolt-types/ddd-construction-bolt/adr-template.md +49 -0
  68. package/dist/iris_bundle/frameworks/iris-core/templates/construction/bolt-types/ddd-construction-bolt/ddd-01-domain-model-template.md +55 -0
  69. package/dist/iris_bundle/frameworks/iris-core/templates/construction/bolt-types/ddd-construction-bolt/ddd-02-technical-design-template.md +67 -0
  70. package/dist/iris_bundle/frameworks/iris-core/templates/construction/bolt-types/ddd-construction-bolt/ddd-03-test-report-template.md +62 -0
  71. package/dist/iris_bundle/frameworks/iris-core/templates/construction/bolt-types/ddd-construction-bolt.md +528 -0
  72. package/dist/iris_bundle/frameworks/iris-core/templates/construction/bolt-types/simple-construction-bolt.md +347 -0
  73. package/dist/iris_bundle/frameworks/iris-core/templates/construction/bolt-types/spike-bolt.md +240 -0
  74. package/dist/iris_bundle/frameworks/iris-core/templates/inception/requirements-template.md +144 -0
  75. package/dist/iris_bundle/frameworks/iris-core/templates/inception/stories-template.md +38 -0
  76. package/dist/iris_bundle/frameworks/iris-core/templates/inception/story-template.md +147 -0
  77. package/dist/iris_bundle/frameworks/iris-core/templates/inception/system-context-template.md +29 -0
  78. package/dist/iris_bundle/frameworks/iris-core/templates/inception/unit-brief-template.md +177 -0
  79. package/dist/iris_bundle/frameworks/iris-core/templates/inception/units-template.md +52 -0
  80. package/dist/templates/construction/bolt-template.md +226 -0
  81. package/dist/templates/construction/bolt-types/ddd-construction-bolt/adr-template.md +49 -0
  82. package/dist/templates/construction/bolt-types/ddd-construction-bolt/ddd-01-domain-model-template.md +55 -0
  83. package/dist/templates/construction/bolt-types/ddd-construction-bolt/ddd-02-technical-design-template.md +67 -0
  84. package/dist/templates/construction/bolt-types/ddd-construction-bolt/ddd-03-test-report-template.md +62 -0
  85. package/dist/templates/construction/bolt-types/ddd-construction-bolt.md +528 -0
  86. package/dist/templates/construction/bolt-types/simple-construction-bolt.md +347 -0
  87. package/dist/templates/construction/bolt-types/spike-bolt.md +240 -0
  88. package/dist/templates/inception/requirements-template.md +144 -0
  89. package/dist/templates/inception/stories-template.md +38 -0
  90. package/dist/templates/inception/story-template.md +147 -0
  91. package/dist/templates/inception/system-context-template.md +29 -0
  92. package/dist/templates/inception/unit-brief-template.md +177 -0
  93. package/dist/templates/inception/units-template.md +52 -0
  94. package/dist/utils/logo.js +17 -0
  95. package/dist/workflows/bolt-plan.js +57 -28
  96. package/dist/workflows/intent-inception.js +169 -72
  97. package/dist/workflows/memory-bank-generator.js +180 -0
  98. package/package.json +10 -7
  99. package/src/iris_bundle/.iris/aidlc/README.md +0 -16
  100. package/src/iris_bundle/.iris/aidlc/agents/iris-construction-agent.md +0 -35
  101. package/src/iris_bundle/.iris/aidlc/agents/iris-inception-agent.md +0 -30
  102. package/src/iris_bundle/.iris/aidlc/agents/iris-master-agent.md +0 -35
  103. package/src/iris_bundle/.iris/aidlc/agents/iris-operations-agent.md +0 -29
  104. package/src/iris_bundle/.iris/aidlc/commands/iris-construction-agent.md +0 -18
  105. package/src/iris_bundle/.iris/aidlc/commands/iris-inception-agent.md +0 -18
  106. package/src/iris_bundle/.iris/aidlc/commands/iris-master-agent.md +0 -18
  107. package/src/iris_bundle/.iris/aidlc/commands/iris-operations-agent.md +0 -18
  108. package/src/iris_bundle/.iris/aidlc/context/context-map.md +0 -25
  109. package/src/iris_bundle/.iris/aidlc/context/exclusion-rules.md +0 -13
  110. package/src/iris_bundle/.iris/aidlc/context/load-order.md +0 -25
  111. package/src/iris_bundle/.iris/aidlc/memory/intent-rules.md +0 -9
  112. package/src/iris_bundle/.iris/aidlc/memory/log-rules.md +0 -5
  113. package/src/iris_bundle/.iris/aidlc/memory/memory-bank.yaml +0 -39
  114. package/src/iris_bundle/.iris/aidlc/memory/unit-rules.md +0 -9
  115. package/src/iris_bundle/.iris/aidlc/quick-start.md +0 -24
  116. package/src/iris_bundle/.iris/aidlc/skills/execution/implementation.md +0 -14
  117. package/src/iris_bundle/.iris/aidlc/skills/execution/refactoring.md +0 -13
  118. package/src/iris_bundle/.iris/aidlc/skills/execution/scaffold-generation.md +0 -15
  119. package/src/iris_bundle/.iris/aidlc/skills/governance/escalation.md +0 -13
  120. package/src/iris_bundle/.iris/aidlc/skills/governance/quality-gates.md +0 -14
  121. package/src/iris_bundle/.iris/aidlc/skills/governance/stop-conditions.md +0 -11
  122. package/src/iris_bundle/.iris/aidlc/skills/reasoning/decomposition.md +0 -23
  123. package/src/iris_bundle/.iris/aidlc/skills/reasoning/risk-analysis.md +0 -14
  124. package/src/iris_bundle/.iris/aidlc/skills/reasoning/verification.md +0 -21
  125. package/src/iris_bundle/.iris/aidlc/standards/artifacts-registry.md +0 -38
  126. package/src/iris_bundle/.iris/aidlc/standards/decision-logging.md +0 -16
  127. package/src/iris_bundle/.iris/aidlc/standards/doctrine-structure.md +0 -31
  128. package/src/iris_bundle/.iris/aidlc/standards/documentation-rules.md +0 -15
  129. package/src/iris_bundle/.iris/aidlc/standards/file-structure.md +0 -21
  130. package/src/iris_bundle/.iris/aidlc/standards/naming-conventions.md +0 -18
  131. package/src/iris_bundle/.iris/aidlc/standards/phases-and-gates.md +0 -25
  132. package/src/iris_bundle/.iris/aidlc/standards/routes-and-routing.md +0 -35
  133. package/src/iris_bundle/.iris/aidlc/standards/tool-wrappers.md +0 -32
  134. package/src/iris_bundle/.iris/aidlc/templates/bolt.md +0 -23
  135. package/src/iris_bundle/.iris/aidlc/templates/doctrine-doc-template.md +0 -33
  136. package/src/iris_bundle/.iris/aidlc/templates/intent.md +0 -23
  137. package/src/iris_bundle/.iris/aidlc/templates/log.md +0 -24
  138. package/src/iris_bundle/.iris/aidlc/templates/review.md +0 -21
  139. package/src/iris_bundle/.iris/aidlc/templates/unit.md +0 -31
  140. package/src/iris_bundle/.iris/aidlc/validation/failure-modes.md +0 -16
  141. package/src/iris_bundle/.iris/aidlc/validation/phase-preconditions.md +0 -21
  142. package/src/iris_bundle/.iris/aidlc/validation/quality-checklist.md +0 -20
  143. package/src/iris_bundle/.iris/policy.yaml +0 -27
  144. package/src/iris_bundle/.iris/routes.yaml +0 -98
  145. package/src/iris_bundle/.iris/state.yaml +0 -7
  146. package/src/iris_bundle/.iris/tools/claude/.claude/claude.md +0 -9
  147. package/src/iris_bundle/.iris/tools/claude/.claude/commands/compare-specs.md +0 -203
  148. package/src/iris_bundle/.iris/tools/claude/.claude/commands/iris-construction-agent.md +0 -25
  149. package/src/iris_bundle/.iris/tools/claude/.claude/commands/iris-inception-agent.md +0 -25
  150. package/src/iris_bundle/.iris/tools/claude/.claude/commands/iris-master-agent.md +0 -25
  151. package/src/iris_bundle/.iris/tools/claude/.claude/commands/iris-operations-agent.md +0 -25
  152. package/src/iris_bundle/.iris/tools/codex/AGENTS.md +0 -15
  153. package/src/iris_bundle/.iris/tools/cursor/.cursor/commands/iris-construction-agent.md +0 -25
  154. package/src/iris_bundle/.iris/tools/cursor/.cursor/commands/iris-inception-agent.md +0 -25
  155. package/src/iris_bundle/.iris/tools/cursor/.cursor/commands/iris-master-agent.md +0 -25
  156. package/src/iris_bundle/.iris/tools/cursor/.cursor/commands/iris-operations-agent.md +0 -25
  157. package/src/iris_bundle/.iris/tools/gemini/.gemini/commands/iris-construction-agent.toml +0 -29
  158. package/src/iris_bundle/.iris/tools/gemini/.gemini/commands/iris-inception-agent.toml +0 -29
  159. package/src/iris_bundle/.iris/tools/gemini/.gemini/commands/iris-master-agent.toml +0 -29
  160. package/src/iris_bundle/.iris/tools/gemini/.gemini/commands/iris-operations-agent.toml +0 -29
@@ -4,42 +4,80 @@ import kleur from "kleur";
4
4
  import { repoRoot } from "../lib.js";
5
5
  import { detectTools, installIris, TOOLS } from "../iris/installer.js";
6
6
  import { setSelectedIde } from "../iris/state.js";
7
+ import { displayLogo } from "../utils/logo.js";
7
8
  export const installCommand = new Command("install")
8
9
  .description("Install IRIS doctrine under .iris and install tool commands into this repo (interactive).")
9
- .action(async () => {
10
+ .option("-y, --yes", "Skip prompts and use default/detected values")
11
+ .option("-f, --force", "Overwrite existing files")
12
+ .option("--tools <items>", "Comma-separated list of tools to install (e.g. cursor,vscode)")
13
+ .action(async (options) => {
14
+ // Display OSiris logo banner
15
+ displayLogo("0.0.11");
10
16
  const root = repoRoot();
11
- // Step A: Detect
17
+ // Step 1: Detect agentic coding tools
18
+ console.log(kleur.bold(`(1/4) Detecting agentic coding tools...`));
12
19
  const defaults = detectTools(root);
13
- // Use detected tools as defaults, or empty array if none detected
14
- const defaultSelection = defaults;
15
- // Step B: Prompt
16
- const { tools } = await inquirer.prompt([
17
- {
18
- type: "checkbox",
19
- name: "tools",
20
- message: "Select the tool(s) you will use with IRIS in this repository:",
21
- choices: TOOLS.map(t => ({
22
- name: t.charAt(0).toUpperCase() + t.slice(1), // Capitalize
23
- value: t,
24
- checked: defaultSelection.includes(t)
25
- })),
26
- validate: (arr) => (arr.length ? true : "Select at least one tool."),
27
- },
28
- ]);
20
+ if (defaults.length > 0) {
21
+ console.log(kleur.gray(` Found: ${defaults.join(", ")}`));
22
+ }
23
+ else {
24
+ console.log(kleur.gray(" No agentic coding tools detected"));
25
+ }
29
26
  console.log("");
30
- console.log(kleur.bold("Installing IRIS..."));
31
- // Step C-G: Core Installer
32
- await installIris(root, tools);
27
+ // Step 2: Select target tools
28
+ let selectedTools = [];
29
+ if (options.yes || options.tools) {
30
+ if (options.tools) {
31
+ selectedTools = options.tools.split(",").map((t) => t.trim().toLowerCase());
32
+ // Validate? (optional but good)
33
+ }
34
+ else {
35
+ selectedTools = defaults.length > 0 ? defaults : ["cursor"]; // Fallback default
36
+ }
37
+ console.log(kleur.bold(`(2/4) Select target tools`));
38
+ console.log(kleur.gray(` [Space] = toggle [Enter] confirm [a] toggle all`));
39
+ console.log(kleur.green(` [x] = selected [ ] = not selected`));
40
+ console.log("");
41
+ selectedTools.forEach(t => {
42
+ console.log(kleur.green(` ◉ ${t.charAt(0).toUpperCase() + t.slice(1)}`));
43
+ });
44
+ console.log("");
45
+ }
46
+ else {
47
+ // Step B: Prompt
48
+ console.log(kleur.bold(`(2/4) Select target tools`));
49
+ const { tools } = await inquirer.prompt([
50
+ {
51
+ type: "checkbox",
52
+ name: "tools",
53
+ message: "Choose tools:",
54
+ prefix: "?",
55
+ choices: TOOLS.map(t => ({
56
+ name: t.charAt(0).toUpperCase() + t.slice(1), // Capitalize
57
+ value: t,
58
+ checked: defaults.includes(t)
59
+ })),
60
+ validate: (arr) => (arr.length ? true : "Select at least one tool."),
61
+ },
62
+ ]);
63
+ selectedTools = tools;
64
+ console.log("");
65
+ }
66
+ console.log(kleur.bold("(3/4) Installing iris-core framework..."));
67
+ // Step 3: Core Installer - Install framework and tools
68
+ await installIris(root, selectedTools, options);
69
+ console.log("");
70
+ console.log(kleur.bold("(4/4) Finalizing setup..."));
33
71
  // Persist IDE selection for iris develop
34
- // Use first tool as default IDE, or prompt if multiple
35
- let selectedIde = tools[0];
36
- if (tools.length > 1) {
72
+ let selectedIde = selectedTools[0];
73
+ if (!options.yes && selectedTools.length > 1) {
74
+ // Only prompt if interactive
37
75
  const { ide } = await inquirer.prompt([
38
76
  {
39
77
  type: "list",
40
78
  name: "ide",
41
79
  message: "Which IDE will you primarily use with 'iris develop'?",
42
- choices: tools.map(t => ({
80
+ choices: selectedTools.map(t => ({
43
81
  name: t.charAt(0).toUpperCase() + t.slice(1),
44
82
  value: t
45
83
  }))
@@ -47,11 +85,16 @@ export const installCommand = new Command("install")
47
85
  ]);
48
86
  selectedIde = ide;
49
87
  }
88
+ // If non-interactive and multiple tools, first one is default IDE.
50
89
  setSelectedIde(selectedIde);
51
90
  console.log("");
52
- console.log(kleur.bold().green("IRIS install complete."));
53
- console.log(kleur.gray("Doctrine: .iris/aidlc"));
54
- console.log(kleur.gray("Policy: .iris/policy.yaml"));
55
- console.log(kleur.gray(`Tools: ${tools.join(", ")}`));
91
+ console.log(kleur.bold().green("IRIS install complete."));
92
+ console.log("");
93
+ console.log(kleur.gray("Installation Summary"));
94
+ console.log(kleur.gray("───────────────────────"));
95
+ console.log(kleur.gray(`Doctrine: .iris/aidlc`));
96
+ console.log(kleur.gray(`Policy: .iris/policy.yaml`));
97
+ console.log(kleur.gray(`Tools: ${selectedTools.join(", ")}`));
56
98
  console.log(kleur.gray(`Primary IDE: ${selectedIde}`));
99
+ console.log("");
57
100
  });
@@ -1,5 +1,6 @@
1
1
  import { Command } from "commander";
2
2
  import { generatePack } from "../iris/packer.js";
3
+ import { resolveActiveFramework } from "../iris/framework-context.js";
3
4
  function collect(value, previous) {
4
5
  return previous.concat([value]);
5
6
  }
@@ -9,19 +10,24 @@ export const packCommand = new Command("pack")
9
10
  .option("--phase <phase>", "Target phase (overrides state.phase.current)")
10
11
  .option("--out <path>", "Output file path (default: .iris/inbox/context-<phase>-<agent>.md)")
11
12
  .option("--stdout", "Print bundle to stdout instead of writing file", false)
13
+ .option("--json", "Output result as JSON", false)
12
14
  .option("--strict", "Fail on validation warnings", false)
13
15
  .option("--max-bytes <n>", "Maximum size in bytes", (val) => parseInt(val, 10), 1_500_000)
14
16
  .option("--include <glob>", "Glob pattern to include files (repeatable)", collect, [])
15
17
  .option("--exclude <glob>", "Glob pattern to exclude files (repeatable)", collect, [])
16
18
  .action(async (opts) => {
19
+ // Wiring up framework resolution as per Step 4 plan (no functional change to packer yet)
20
+ const { resolution } = await resolveActiveFramework();
17
21
  await generatePack({
18
22
  agent: opts.agent,
19
23
  phase: opts.phase,
20
24
  output: opts.out,
21
25
  stdout: opts.stdout,
26
+ json: opts.json,
22
27
  strict: opts.strict,
23
28
  maxBytes: opts.maxBytes,
24
29
  includes: opts.include,
25
- excludes: opts.exclude
30
+ excludes: opts.exclude,
31
+ frameworkResolution: resolution
26
32
  });
27
33
  });
@@ -1,17 +1,199 @@
1
1
  import { Command } from "commander";
2
2
  import kleur from "kleur";
3
- import { requireValidRepoOrExit } from "../iris/guard.js";
4
- import { EXIT_CODES } from "../utils/exit-codes.js";
3
+ import path from "path";
4
+ import fs from "fs";
5
+ import { repoRoot } from "../lib.js";
6
+ import { loadState, getActiveFramework, saveState } from "../iris/state.js";
7
+ import { WorkflowEngine } from "../iris/workflow/engine.js";
8
+ import { loadEffectiveWorkflowConfig } from "../iris/workflow/config.js";
9
+ import { EXEC_REGISTRY } from "../iris/workflow/steps.js";
10
+ import { loadFramework } from "../framework/framework-loader.js";
5
11
  export const runCommand = new Command("run")
6
- .description("Execute a named workflow or agent (Placeholder)")
7
- .argument("<name>", "Name of the workflow/agent to run")
8
- .option("--strict", "Enforce strict validation (warnings become errors)", false)
9
- .action(async (name, options) => {
10
- // GUARDRAIL
11
- await requireValidRepoOrExit({ strict: options.strict });
12
- // If we are here, repo is valid (or warnings ignored)
13
- console.log("");
14
- console.log(kleur.green(`✅ Guards passed. Would run: ${name}`));
15
- console.log("");
16
- process.exit(EXIT_CODES.SUCCESS);
12
+ .description("Execute the IRIS workflow loop")
13
+ .option("--new", "Start a new run (even if one exists)", false)
14
+ .option("--resume [runId]", "Resume a specific run ID")
15
+ .option("--seed <path>", "Seed run with an existing intent draft")
16
+ .option("--step <id>", "Execute only a specific step")
17
+ .option("--force", "Force re-execution of done steps", false)
18
+ .option("--json", "Output machine-readable status", false)
19
+ .option("--no-interactive", "Disable interactive prompts (Block if input needed)")
20
+ .action(async (options) => {
21
+ const root = repoRoot();
22
+ try {
23
+ // 1. Resolve Run Context
24
+ let engine;
25
+ let runId = options.resume === true ? undefined : options.resume; // --resume might be boolean true if no arg? No, [runId] means optional arg.
26
+ // If --resume passed without arg, commander sets it to true? Commander syntax [runId] sets it to true if flag present but no arg?
27
+ // Wait, argument [runId] means optional.
28
+ // If I run `iris run --resume`, `options.resume` is `true`? Or `runId`?
29
+ // Need to handle `true`.
30
+ if (typeof options.resume === 'boolean') {
31
+ runId = undefined; // Implies "resume latest" explicitly requested
32
+ }
33
+ const latestId = WorkflowEngine.getLatestRunId(root);
34
+ if (options.new || (!runId && !latestId)) {
35
+ // START NEW RUN
36
+ // Resolve Active Framework for configuration
37
+ const state = loadState();
38
+ const active = getActiveFramework(state);
39
+ // Load framework config
40
+ let framework = null;
41
+ try {
42
+ if (active.current) {
43
+ framework = await loadFramework(active.current, { repoRoot: root });
44
+ }
45
+ }
46
+ catch (e) {
47
+ // Ignore framework load error? Default workflow will use default.
48
+ // But we should probably warn.
49
+ if (options.json) {
50
+ // We are creating a run, hard to report json error before engine exists?
51
+ }
52
+ else {
53
+ console.warn(kleur.yellow(`Warning: Could not load framework '${active.current}'. Using default workflow.`));
54
+ }
55
+ }
56
+ const workflowConfig = loadEffectiveWorkflowConfig(framework);
57
+ engine = WorkflowEngine.create(root, active.current, active.version || null, workflowConfig);
58
+ if (!options.json) {
59
+ console.log(kleur.bold(`Started new run: ${kleur.cyan(engine.getRunId())}`));
60
+ console.log(kleur.dim(`Framework: ${active.current}`));
61
+ }
62
+ }
63
+ else {
64
+ // RESUME
65
+ runId = runId || latestId;
66
+ if (!runId) {
67
+ // Should be unreachable due to !latestId check above
68
+ throw new Error("No run to resume.");
69
+ }
70
+ try {
71
+ engine = WorkflowEngine.load(root, runId);
72
+ if (!options.json) {
73
+ console.log(kleur.bold(`Resuming run: ${kleur.cyan(runId)}`));
74
+ }
75
+ engine.appendEvent("RUN_RESUMED");
76
+ // Assuming workflow config is baked into state, so no need to reload framework
77
+ }
78
+ catch (e) {
79
+ console.error(kleur.red(`Failed to load run '${runId}': ${e.message}`));
80
+ process.exit(1);
81
+ }
82
+ }
83
+ // 2. Execution Loop
84
+ const engineState = engine.getState();
85
+ // Sync intentId to global state
86
+ const state = loadState();
87
+ state.active.intent_id = engineState.intentId;
88
+ // Also sync other active fields if needed
89
+ saveState(state);
90
+ const steps = engineState.workflow.steps;
91
+ // Filter steps?
92
+ const targetSteps = options.step
93
+ ? steps.filter(s => s.id === options.step)
94
+ : steps;
95
+ if (targetSteps.length === 0) {
96
+ console.error(kleur.red(`Step '${options.step}' not found in workflow.`));
97
+ process.exit(1);
98
+ }
99
+ let blocked = false;
100
+ let failed = false;
101
+ for (const stepConfig of targetSteps) {
102
+ if (stepConfig.enabled === false)
103
+ continue;
104
+ const status = engine.getStepStatus(stepConfig.id);
105
+ const isDone = status?.status === 'done';
106
+ fs.appendFileSync(path.join(root, 'debug.log'), `[DEBUG] Step ${stepConfig.id} status=${status?.status} isDone=${isDone}\n`);
107
+ if (isDone && !options.force) {
108
+ if (!options.json)
109
+ console.log(kleur.dim(`✓ Step '${stepConfig.id}' already done.`));
110
+ continue;
111
+ }
112
+ // Execute
113
+ if (!options.json)
114
+ console.log(kleur.bold(`\nRunning step: ${stepConfig.id}...`));
115
+ engine.appendEvent("STEP_STARTED", { stepId: stepConfig.id });
116
+ const executor = EXEC_REGISTRY[stepConfig.kind];
117
+ if (!executor) {
118
+ const msg = `Unknown step kind '${stepConfig.kind}'`;
119
+ console.error(kleur.red(msg));
120
+ engine.updateStepstatus(stepConfig.id, { status: "failed", error: msg });
121
+ engine.appendEvent("STEP_FAILED", { stepId: stepConfig.id, error: msg });
122
+ failed = true;
123
+ break;
124
+ }
125
+ const result = await executor.execute(engineState, stepConfig, root, engine.getRunDir(), {
126
+ interactive: options.interactive ?? true,
127
+ seed: options.seed,
128
+ force: options.force,
129
+ quiet: options.json // Suppress stdout when --json is enabled
130
+ });
131
+ fs.appendFileSync(path.join(root, 'debug.log'), `[DEBUG] Step ${stepConfig.id} result result=${JSON.stringify(result)}\n`);
132
+ // Update Status
133
+ engine.updateStepstatus(stepConfig.id, {
134
+ status: result.status,
135
+ reason: result.reason,
136
+ error: result.error,
137
+ outputs: result.outputs
138
+ });
139
+ if (result.status === "failed") {
140
+ if (!options.json)
141
+ console.error(kleur.red(`✗ Step '${stepConfig.id}' failed: ${result.error}`));
142
+ engine.appendEvent("STEP_FAILED", { stepId: stepConfig.id, error: result.error });
143
+ failed = true;
144
+ break;
145
+ }
146
+ else if (result.status === "blocked") {
147
+ if (!options.json) {
148
+ console.warn(kleur.yellow(`⚠ Step '${stepConfig.id}' blocked: ${result.reason}`));
149
+ console.warn(kleur.dim(` To fix: ${result.error}`));
150
+ }
151
+ engine.appendEvent("STEP_BLOCKED", { stepId: stepConfig.id, msg: result.reason, error: result.error });
152
+ blocked = true;
153
+ break;
154
+ }
155
+ else {
156
+ if (!options.json)
157
+ console.log(kleur.green(`✓ Step '${stepConfig.id}' done.`));
158
+ engine.appendEvent("STEP_DONE", { stepId: stepConfig.id, outputs: result.outputs });
159
+ }
160
+ }
161
+ // Finish
162
+ if (failed) {
163
+ engine.appendEvent("RUN_FINISHED", { error: "Run failed" });
164
+ if (options.json) {
165
+ console.log(JSON.stringify(engine.getState(), null, 2));
166
+ // console.error("DEBUG: Run failed. Exiting 1.");
167
+ }
168
+ process.exit(1);
169
+ }
170
+ else if (blocked) {
171
+ // Blocked is special exit code 2
172
+ engine.appendEvent("STEP_BLOCKED", { stepId: "run", msg: "Run blocked" }); // Ensure event log?
173
+ if (options.json) {
174
+ console.log(JSON.stringify(engine.getState(), null, 2));
175
+ // console.error("DEBUG: Run blocked. Exiting 2.");
176
+ }
177
+ process.exit(2);
178
+ }
179
+ else {
180
+ if (!options.step) {
181
+ // Only mark run finished if we ran the full loop?
182
+ // Or if cursor reached end?
183
+ // For now, if no failure/block, we assume success.
184
+ engine.appendEvent("RUN_FINISHED");
185
+ }
186
+ }
187
+ if (options.json) {
188
+ // Reload state to get latest updates
189
+ console.log(JSON.stringify(engine.getState(), null, 2));
190
+ }
191
+ }
192
+ catch (e) {
193
+ console.error(kleur.red(`Run error: ${e.message}`));
194
+ if (options.json) {
195
+ console.log(JSON.stringify({ error: e.message }));
196
+ }
197
+ process.exit(1);
198
+ }
17
199
  });
@@ -51,6 +51,9 @@ export const statusCommand = new Command("status")
51
51
  requested: result ? result.phase.requested : state.phase.requested
52
52
  },
53
53
  last_validation: result ? state.last_validation : null,
54
+ active: {
55
+ flow: state.active.flow
56
+ },
54
57
  summary: result ? {
55
58
  result: result.valid ? "valid" : "invalid",
56
59
  errors_count: result.errors.length,
@@ -71,6 +74,12 @@ export const statusCommand = new Command("status")
71
74
  if (result.phase.requested) {
72
75
  console.log(`- Requested:${kleur.yellow(result.phase.requested)}`);
73
76
  }
77
+ if (state.active && state.active.flow) {
78
+ console.log(`- Active Flow: ${kleur.blue(state.active.flow)}`);
79
+ }
80
+ else {
81
+ console.log(`- Active Flow: (none)`);
82
+ }
74
83
  // Show validation result
75
84
  const validity = result.valid
76
85
  ? kleur.green("VALID")
@@ -3,10 +3,12 @@ import { uninstallIris } from "../iris/uninstaller.js";
3
3
  export const uninstallCommand = new Command("uninstall")
4
4
  .description("Remove .iris and tool command files installed by IRIS (manifest-driven).")
5
5
  .option("--keep-memory", "Keep memory-bank folder if present", false)
6
+ .option("--yes", "Run non-interactively (defaults to safe preservation)", false)
6
7
  .option("--force", "Skip confirmations where possible", false)
7
8
  .action(async (opts) => {
8
9
  await uninstallIris({
9
10
  keepMemory: opts.keepMemory,
10
- force: opts.force
11
+ force: opts.force,
12
+ yes: opts.yes
11
13
  });
12
14
  });
@@ -0,0 +1,20 @@
1
+ import { Command } from "commander";
2
+ import kleur from "kleur";
3
+ import { setSelectedIde } from "../iris/state.js";
4
+ import { TOOLS } from "../iris/installer.js";
5
+ export const useCommand = new Command("use")
6
+ .description("Set the active IDE/Tool for IRIS")
7
+ .argument("<ide>", "IDE ID (cursor, vscode, auto, etc.)")
8
+ .action((ide) => {
9
+ const normalized = ide.toLowerCase();
10
+ // Validation (Soft)
11
+ if (!TOOLS.includes(normalized)) {
12
+ console.log(kleur.yellow(`Warning: '${ide}' is not in the standard tools list.`));
13
+ console.log(kleur.dim(`Available: ${TOOLS.join(", ")}`));
14
+ }
15
+ setSelectedIde(normalized);
16
+ console.log(kleur.green(`✓ Active IDE set to: ${normalized}`));
17
+ if (normalized === "auto") {
18
+ console.log(kleur.cyan(" In-Process Agent enabled (background mode)."));
19
+ }
20
+ });
@@ -4,84 +4,99 @@ import { validate } from "../iris/validator.js";
4
4
  import { printReport } from "../iris/report.js";
5
5
  import { collectFixPlan, applyFixPlan } from "../iris/fixer.js";
6
6
  import { EXIT_CODES } from "../utils/exit-codes.js";
7
+ import { resolveActiveFramework } from "../iris/framework-context.js";
7
8
  export const validateCommand = new Command("validate")
8
- .description("Validate the current repository state against the IRIS policy.")
9
- .option("--apply", "Automatically apply requested phase changes if valid.")
10
- .option("--phase <phase>", "Override the target phase to validate against.")
11
- .option("--strict", "Fail on warnings as well as errors.")
12
- .option("--json", "Output results as JSON.")
13
- .option("--fix", "Attempt to fix missing artifacts automatically.")
14
- .option("--fix-dry-run", "Show what would be fixed without making changes.")
15
- .option("--yes", "Automatically confirm overwrites (if any).")
9
+ // ...
16
10
  .action(async (options) => {
17
- // 1. First Validation Pass
18
- if (!options.fix && !options.fixDryRun) {
19
- const result = await validate({
11
+ const { resolution } = await resolveActiveFramework();
12
+ try {
13
+ // 1. First Validation Pass
14
+ if (!options.fix && !options.fixDryRun) {
15
+ const result = await validate({
16
+ apply: options.apply || false,
17
+ phase: options.phase,
18
+ strict: options.strict || false,
19
+ frameworkResolution: resolution,
20
+ });
21
+ printReport(result, options.json, undefined, options.strict);
22
+ let exitCode = EXIT_CODES.SUCCESS;
23
+ if (!result.valid) {
24
+ exitCode = EXIT_CODES.INVALID;
25
+ }
26
+ else if (options.strict && result.warnings) {
27
+ exitCode = EXIT_CODES.VALID_WITH_WARNINGS;
28
+ }
29
+ process.exit(exitCode);
30
+ }
31
+ // 2. Fix Mode
32
+ // Pass 1: Discovery
33
+ const result1 = await validate({
34
+ apply: false,
35
+ phase: options.phase,
36
+ strict: options.strict || false,
37
+ writeBack: false,
38
+ frameworkResolution: resolution,
39
+ });
40
+ if (result1.valid && !result1.warnings) {
41
+ if (options.json) {
42
+ printReport(result1, true);
43
+ }
44
+ else {
45
+ console.log(kleur.green("✓ Repository is valid. No fixes needed."));
46
+ }
47
+ process.exit(EXIT_CODES.SUCCESS);
48
+ }
49
+ // Collect Plan
50
+ const plan = collectFixPlan(result1);
51
+ if (plan.actions.length === 0) {
52
+ if (options.json) {
53
+ printReport(result1, true);
54
+ }
55
+ else {
56
+ console.log(kleur.yellow("No fixable missing artifacts found."));
57
+ printReport(result1, false, undefined, options.strict);
58
+ }
59
+ process.exit(EXIT_CODES.INVALID); // Changed from POLICY_ERROR
60
+ }
61
+ // Apply Fixes
62
+ const fixResult = await applyFixPlan(plan, {
63
+ dryRun: options.fixDryRun,
64
+ yes: options.yes
65
+ });
66
+ if (options.fixDryRun) {
67
+ process.exit(EXIT_CODES.SUCCESS);
68
+ }
69
+ // 3. Re-validate (Final Pass)
70
+ const result2 = await validate({
20
71
  apply: options.apply || false,
21
72
  phase: options.phase,
22
73
  strict: options.strict || false,
74
+ writeBack: true,
75
+ frameworkResolution: resolution,
23
76
  });
24
- printReport(result, options.json, undefined, options.strict);
77
+ printReport(result2, options.json, fixResult, options.strict);
25
78
  let exitCode = EXIT_CODES.SUCCESS;
26
- if (!result.valid) {
27
- exitCode = EXIT_CODES.INVALID;
79
+ if (!result2.valid) {
80
+ exitCode = EXIT_CODES.INVALID; // Changed from POLICY_ERROR
28
81
  }
29
- else if (options.strict && result.warnings) {
82
+ else if (options.strict && result2.warnings) {
30
83
  exitCode = EXIT_CODES.VALID_WITH_WARNINGS;
31
84
  }
32
85
  process.exit(exitCode);
33
86
  }
34
- // 2. Fix Mode
35
- // Pass 1: Discovery
36
- const result1 = await validate({
37
- apply: false,
38
- phase: options.phase,
39
- strict: options.strict || false,
40
- writeBack: false
41
- });
42
- if (result1.valid && !result1.warnings) {
43
- if (options.json) {
44
- printReport(result1, true);
45
- }
46
- else {
47
- console.log(kleur.green("✓ Repository is valid. No fixes needed."));
48
- }
49
- process.exit(EXIT_CODES.SUCCESS);
50
- }
51
- // Collect Plan
52
- const plan = collectFixPlan(result1);
53
- if (plan.actions.length === 0) {
54
- if (options.json) {
55
- printReport(result1, true);
87
+ catch (e) {
88
+ if (e.name === "PolicyOverlayMissingError") {
89
+ console.error(kleur.red(`\n[Policy Error] ${e.message}`));
90
+ process.exit(EXIT_CODES.POLICY_ERROR);
56
91
  }
57
- else {
58
- console.log(kleur.yellow("No fixable missing artifacts found."));
59
- printReport(result1, false, undefined, options.strict);
92
+ if (e.name === "PolicyLoadError") {
93
+ console.error(kleur.red(`\n[Policy Error] ${e.message}`));
94
+ if (e.cause)
95
+ console.error(kleur.gray(e.cause));
96
+ process.exit(EXIT_CODES.POLICY_ERROR);
60
97
  }
61
- process.exit(EXIT_CODES.INVALID); // Changed from POLICY_ERROR
62
- }
63
- // Apply Fixes
64
- const fixResult = await applyFixPlan(plan, {
65
- dryRun: options.fixDryRun,
66
- yes: options.yes
67
- });
68
- if (options.fixDryRun) {
69
- process.exit(EXIT_CODES.SUCCESS);
70
- }
71
- // 3. Re-validate (Final Pass)
72
- const result2 = await validate({
73
- apply: options.apply || false,
74
- phase: options.phase,
75
- strict: options.strict || false,
76
- writeBack: true
77
- });
78
- printReport(result2, options.json, fixResult, options.strict);
79
- let exitCode = EXIT_CODES.SUCCESS;
80
- if (!result2.valid) {
81
- exitCode = EXIT_CODES.INVALID; // Changed from POLICY_ERROR
82
- }
83
- else if (options.strict && result2.warnings) {
84
- exitCode = EXIT_CODES.VALID_WITH_WARNINGS;
98
+ // Unexpected
99
+ console.error(kleur.red(`\n[Unexpected Error] ${e.message}`));
100
+ process.exit(EXIT_CODES.INVALID);
85
101
  }
86
- process.exit(exitCode);
87
102
  });