@icex-labs/icex-flow 0.3.0

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 (85) hide show
  1. package/README.md +158 -0
  2. package/SKILL.md +141 -0
  3. package/bin/icex-flow.mjs +3 -0
  4. package/dist/src/adapters/index.d.ts +1 -0
  5. package/dist/src/adapters/index.js +2 -0
  6. package/dist/src/adapters/index.js.map +1 -0
  7. package/dist/src/adapters/openclaw.d.ts +31 -0
  8. package/dist/src/adapters/openclaw.js +118 -0
  9. package/dist/src/adapters/openclaw.js.map +1 -0
  10. package/dist/src/cli.d.ts +1 -0
  11. package/dist/src/cli.js +95 -0
  12. package/dist/src/cli.js.map +1 -0
  13. package/dist/src/commands/context.d.ts +1 -0
  14. package/dist/src/commands/context.js +40 -0
  15. package/dist/src/commands/context.js.map +1 -0
  16. package/dist/src/commands/generate.d.ts +2 -0
  17. package/dist/src/commands/generate.js +230 -0
  18. package/dist/src/commands/generate.js.map +1 -0
  19. package/dist/src/commands/init.d.ts +1 -0
  20. package/dist/src/commands/init.js +104 -0
  21. package/dist/src/commands/init.js.map +1 -0
  22. package/dist/src/commands/learn.d.ts +13 -0
  23. package/dist/src/commands/learn.js +108 -0
  24. package/dist/src/commands/learn.js.map +1 -0
  25. package/dist/src/commands/list.d.ts +1 -0
  26. package/dist/src/commands/list.js +104 -0
  27. package/dist/src/commands/list.js.map +1 -0
  28. package/dist/src/commands/plan.d.ts +1 -0
  29. package/dist/src/commands/plan.js +88 -0
  30. package/dist/src/commands/plan.js.map +1 -0
  31. package/dist/src/commands/projects.d.ts +1 -0
  32. package/dist/src/commands/projects.js +69 -0
  33. package/dist/src/commands/projects.js.map +1 -0
  34. package/dist/src/commands/route.d.ts +1 -0
  35. package/dist/src/commands/route.js +38 -0
  36. package/dist/src/commands/route.js.map +1 -0
  37. package/dist/src/commands/validate.d.ts +1 -0
  38. package/dist/src/commands/validate.js +194 -0
  39. package/dist/src/commands/validate.js.map +1 -0
  40. package/dist/src/commands/verify.d.ts +1 -0
  41. package/dist/src/commands/verify.js +50 -0
  42. package/dist/src/commands/verify.js.map +1 -0
  43. package/dist/src/engine/architecture.d.ts +12 -0
  44. package/dist/src/engine/architecture.js +367 -0
  45. package/dist/src/engine/architecture.js.map +1 -0
  46. package/dist/src/engine/config.d.ts +24 -0
  47. package/dist/src/engine/config.js +164 -0
  48. package/dist/src/engine/config.js.map +1 -0
  49. package/dist/src/engine/context.d.ts +12 -0
  50. package/dist/src/engine/context.js +171 -0
  51. package/dist/src/engine/context.js.map +1 -0
  52. package/dist/src/engine/detect.d.ts +6 -0
  53. package/dist/src/engine/detect.js +300 -0
  54. package/dist/src/engine/detect.js.map +1 -0
  55. package/dist/src/engine/environment.d.ts +12 -0
  56. package/dist/src/engine/environment.js +399 -0
  57. package/dist/src/engine/environment.js.map +1 -0
  58. package/dist/src/engine/planner.d.ts +12 -0
  59. package/dist/src/engine/planner.js +130 -0
  60. package/dist/src/engine/planner.js.map +1 -0
  61. package/dist/src/engine/router.d.ts +7 -0
  62. package/dist/src/engine/router.js +56 -0
  63. package/dist/src/engine/router.js.map +1 -0
  64. package/dist/src/engine/verifier.d.ts +8 -0
  65. package/dist/src/engine/verifier.js +55 -0
  66. package/dist/src/engine/verifier.js.map +1 -0
  67. package/dist/src/index.d.ts +14 -0
  68. package/dist/src/index.js +13 -0
  69. package/dist/src/index.js.map +1 -0
  70. package/dist/src/presets/index.d.ts +11 -0
  71. package/dist/src/presets/index.js +352 -0
  72. package/dist/src/presets/index.js.map +1 -0
  73. package/dist/src/types.d.ts +161 -0
  74. package/dist/src/types.js +8 -0
  75. package/dist/src/types.js.map +1 -0
  76. package/dist/src/utils.d.ts +8 -0
  77. package/dist/src/utils.js +65 -0
  78. package/dist/src/utils.js.map +1 -0
  79. package/package.json +48 -0
  80. package/schemas/context.schema.json +38 -0
  81. package/schemas/routes.schema.json +33 -0
  82. package/schemas/workflow.schema.json +84 -0
  83. package/templates/context.manifest.json +21 -0
  84. package/templates/dev-chain.flow.json +112 -0
  85. package/templates/routes.json +37 -0
package/README.md ADDED
@@ -0,0 +1,158 @@
1
+ # icex-flow
2
+
3
+ **Deterministic agent workflow orchestration.** Eliminate randomness in AI agent pipelines.
4
+
5
+ > JSON decides. LLM executes. Every time, the same way.
6
+
7
+ ## The Problem
8
+
9
+ AI agents (OpenClaw, Claude Code, etc.) make freestyle decisions about:
10
+ - Which agent handles a task → **random routing**
11
+ - What context to inject → **forgotten rules, missed files**
12
+ - What steps to follow → **different path every run**
13
+ - Whether to verify results → **lies about success**
14
+
15
+ ## The Solution
16
+
17
+ `icex-flow` replaces LLM judgment with structured JSON definitions:
18
+
19
+ | Component | What it does | LLM decides? |
20
+ |-----------|-------------|:---:|
21
+ | **Routes** (`routes.json`) | Maps tasks → agents + workflows | No |
22
+ | **Context** (`context.manifest.json`) | Lists files to inject per step | No |
23
+ | **Workflows** (`*.flow.json`) | Defines steps + verification | No |
24
+ | **Verification** (built-in) | Checks step completion | No |
25
+
26
+ The LLM still does the intelligent work (writing code, analyzing problems). It just doesn't decide the **process**.
27
+
28
+ ## Install
29
+
30
+ ```bash
31
+ npm install -g icex-flow
32
+ ```
33
+
34
+ ## Quick Start
35
+
36
+ ```bash
37
+ # Initialize in your project
38
+ icex-flow init
39
+
40
+ # Edit the generated files
41
+ vim .icex-flow/routes.json
42
+ vim .icex-flow/context.manifest.json
43
+ vim .icex-flow/workflows/dev-chain.flow.json
44
+
45
+ # Validate
46
+ icex-flow validate
47
+
48
+ # Route a task
49
+ icex-flow route "fix the login bug" --labels bug
50
+ # → Agent: dev, Workflow: dev-chain, Confidence: keyword
51
+
52
+ # Generate execution plan
53
+ icex-flow plan dev-chain --input '{"issue_number":"42","branch_name":"fix/login","pr_title":"Fix login bug"}'
54
+ # → Step-by-step plan with resolved commands and verification
55
+
56
+ # Assemble context for a step
57
+ icex-flow context dev-chain --step implement
58
+ # → Concatenated content of all required files
59
+ ```
60
+
61
+ ## Commands
62
+
63
+ | Command | Description |
64
+ |---------|-------------|
65
+ | `icex-flow init [dir]` | Scaffold `.icex-flow/` with templates |
66
+ | `icex-flow validate [dir]` | Validate all JSON definitions |
67
+ | `icex-flow route "<task>"` | Route task to agent + workflow |
68
+ | `icex-flow plan <workflow>` | Generate deterministic execution plan |
69
+ | `icex-flow context [workflow]` | Assemble context from manifest |
70
+ | `icex-flow verify --command "..."` | Run step verification |
71
+ | `icex-flow list` | List workflows and routes |
72
+
73
+ ## Workflow Definition
74
+
75
+ A workflow is a JSON file defining a deterministic sequence of steps:
76
+
77
+ ```json
78
+ {
79
+ "name": "dev-chain",
80
+ "version": "1.0.0",
81
+ "description": "Issue → Code → Test → PR → Merge",
82
+ "inputs": {
83
+ "issue_number": { "type": "string", "required": true },
84
+ "branch_name": { "type": "string", "required": true }
85
+ },
86
+ "steps": [
87
+ {
88
+ "id": "create-branch",
89
+ "name": "Create Feature Branch",
90
+ "action": "shell",
91
+ "command": "git checkout -b {{branch_name}}",
92
+ "verify": {
93
+ "command": "git branch --show-current",
94
+ "expect": "{{branch_name}}"
95
+ }
96
+ },
97
+ {
98
+ "id": "implement",
99
+ "name": "Implement Changes",
100
+ "action": "agent",
101
+ "agent": "dev-coder",
102
+ "timeout": 600,
103
+ "input": "Implement issue #{{issue_number}}",
104
+ "verify": {
105
+ "command": "pytest tests/ -v",
106
+ "expect_exit": 0
107
+ }
108
+ }
109
+ ]
110
+ }
111
+ ```
112
+
113
+ ### Step Types
114
+
115
+ - **`shell`** — Run a command. Optionally capture output.
116
+ - **`agent`** — Spawn a subagent with input and timeout.
117
+ - **`notify`** — Send notifications to channels.
118
+ - **`gate`** — Wait for a condition (with retries).
119
+
120
+ ### Verification
121
+
122
+ Every step can have a `verify` block:
123
+
124
+ ```json
125
+ {
126
+ "verify": {
127
+ "command": "gh pr checks main --json state",
128
+ "expect": "SUCCESS",
129
+ "retry": 10,
130
+ "retry_delay": 30
131
+ }
132
+ }
133
+ ```
134
+
135
+ Verification runs after each step. If it fails, the workflow stops.
136
+
137
+ ## Platform Support
138
+
139
+ | Platform | Status | Integration |
140
+ |----------|--------|------------|
141
+ | **OpenClaw** | ✅ Supported | SKILL.md included, install as skill |
142
+ | **Claude Code** | 🔜 Planned | Programmatic API via `import { routeTask } from 'icex-flow'` |
143
+
144
+ ## Programmatic API
145
+
146
+ ```typescript
147
+ import { routeTask, planWorkflow, assembleContext, verifyStep } from 'icex-flow';
148
+
149
+ const result = routeTask(routesConfig, { description: "fix login bug", labels: ["bug"] });
150
+ // → { agent: "dev", workflow: "dev-chain", confidence: "keyword" }
151
+
152
+ const plan = planWorkflow(workflowDef, { issue_number: "42", branch_name: "fix/login" });
153
+ // → { steps: [...], variables: {...} }
154
+ ```
155
+
156
+ ## License
157
+
158
+ MIT — [icex-labs](https://github.com/icex-labs)
package/SKILL.md ADDED
@@ -0,0 +1,141 @@
1
+ ---
2
+ name: icex-flow
3
+ description: |
4
+ Deterministic agent workflow orchestration. Use when receiving any task that
5
+ should be routed to a specific agent or executed as a multi-step workflow.
6
+ Eliminates LLM freestyle decisions — routing, context assembly, step execution,
7
+ and verification are all defined in JSON, not left to model judgment.
8
+ Triggers: receiving a new task, spawning a subagent, executing a dev chain,
9
+ deploying changes, triaging inbox items, or any multi-step operation.
10
+ metadata:
11
+ openclaw:
12
+ emoji: "⚡"
13
+ requires:
14
+ bins: ["node"]
15
+ install:
16
+ - id: "npm"
17
+ kind: "npm"
18
+ package: "icex-flow"
19
+ bins: ["icex-flow"]
20
+ label: "Install icex-flow via npm"
21
+ ---
22
+
23
+ # icex-flow — Deterministic Agent Workflows
24
+
25
+ **Core principle: JSON decides, LLM executes.** No freestyle routing, no ad-hoc context, no skipped steps.
26
+
27
+ ## Quick Reference
28
+
29
+ ```bash
30
+ icex-flow init # Scaffold .icex-flow/ directory
31
+ icex-flow validate # Validate all definitions
32
+ icex-flow route "<task>" [--labels x] # Route task → agent + workflow
33
+ icex-flow plan <workflow> --input '{}' # Generate execution plan
34
+ icex-flow context [workflow] [--step x] # Assemble context from manifest
35
+ icex-flow verify --command "<cmd>" # Run step verification
36
+ icex-flow list # List workflows and routes
37
+ ```
38
+
39
+ ## MANDATORY: How to Use in Agent Sessions
40
+
41
+ When you receive a task, follow this exact sequence. **Do NOT deviate.**
42
+
43
+ ### Step 1: Route
44
+
45
+ ```bash
46
+ icex-flow route "<task description>" --labels "label1,label2"
47
+ ```
48
+
49
+ This returns the **agent** and **workflow** to use. Do NOT choose yourself.
50
+
51
+ ### Step 2: Assemble Context
52
+
53
+ ```bash
54
+ icex-flow context <workflow> --step <current-step>
55
+ ```
56
+
57
+ Read the output. This is the context you MUST inject before executing. Do NOT decide what files to read — the manifest decides.
58
+
59
+ ### Step 3: Plan
60
+
61
+ ```bash
62
+ icex-flow plan <workflow> --input '{"key":"value"}'
63
+ ```
64
+
65
+ This returns a step-by-step execution plan with resolved commands and verification. Follow it **in order**.
66
+
67
+ ### Step 4: Execute Each Step
68
+
69
+ For each step in the plan:
70
+ 1. Execute the action (shell command, spawn agent, send notification)
71
+ 2. Run verification: `icex-flow verify --command "<verify_cmd>" --expect "<expected>"`
72
+ 3. If verification fails → **STOP**. Do not continue. Report failure.
73
+ 4. If verification passes → proceed to next step.
74
+
75
+ ### Step 5: Report
76
+
77
+ After all steps complete (or on failure), send notifications as defined in the plan.
78
+
79
+ ## File Structure
80
+
81
+ ```
82
+ .icex-flow/
83
+ ├── routes.json # Task → agent + workflow mapping
84
+ ├── context.manifest.json # What files to inject per workflow/step
85
+ └── workflows/
86
+ ├── dev-chain.flow.json # Development workflow
87
+ ├── deploy.flow.json # Deployment workflow
88
+ └── *.flow.json # Custom workflows
89
+ ```
90
+
91
+ ## Workflow Definition Format
92
+
93
+ ```json
94
+ {
95
+ "name": "dev-chain",
96
+ "version": "1.0.0",
97
+ "description": "Issue → Code → Test → PR → Merge",
98
+ "inputs": {
99
+ "issue_number": { "type": "string", "required": true }
100
+ },
101
+ "steps": [
102
+ {
103
+ "id": "lock",
104
+ "name": "Lock Issue",
105
+ "action": "shell",
106
+ "command": "gh issue edit {{issue_number}} --add-label in-progress",
107
+ "verify": {
108
+ "command": "gh issue view {{issue_number}} --json labels",
109
+ "expect": "in-progress"
110
+ }
111
+ }
112
+ ]
113
+ }
114
+ ```
115
+
116
+ ### Step Actions
117
+
118
+ | Action | Description | Required Fields |
119
+ |--------|-------------|-----------------|
120
+ | `shell` | Run a shell command | `command` |
121
+ | `agent` | Spawn a subagent | `agent`, `input`, `timeout` |
122
+ | `notify` | Send notification | `channels`, `message` |
123
+ | `gate` | Wait for condition | `verify` (with retries) |
124
+
125
+ ### Variables
126
+
127
+ Use `{{variable_name}}` in any string field. Variables come from:
128
+ - Workflow `inputs` definitions
129
+ - `--input` JSON passed to `icex-flow plan`
130
+ - `capture` field on previous steps (captures command stdout)
131
+
132
+ ## Anti-Patterns (FORBIDDEN)
133
+
134
+ | Do NOT | Instead |
135
+ |--------|---------|
136
+ | Choose which agent handles a task | Run `icex-flow route` |
137
+ | Decide what context files to read | Run `icex-flow context` |
138
+ | Skip steps in a workflow | Follow the plan exactly |
139
+ | Skip verification after a step | Always run `icex-flow verify` |
140
+ | Improvise extra steps | Only execute what's in the plan |
141
+ | Report success without verification | Verify first, then report |
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { main } from '../dist/src/cli.js';
3
+ main(process.argv.slice(2));
@@ -0,0 +1 @@
1
+ export { handleTask, getChannelMode, shouldUseIcexFlow, routeViaCLI, planViaCLI } from './openclaw.js';
@@ -0,0 +1,2 @@
1
+ export { handleTask, getChannelMode, shouldUseIcexFlow, routeViaCLI, planViaCLI } from './openclaw.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * OpenClaw adapter for icex-flow
3
+ * Provides helpers for OpenClaw skills to use icex-flow routing and planning
4
+ */
5
+ import type { RouteResult, ExecutionPlan } from '../types.js';
6
+ interface OpenClawContext {
7
+ workspacePath: string;
8
+ channelId?: string;
9
+ agentId?: string;
10
+ sessionKey?: string;
11
+ }
12
+ interface OpenClawTaskInput {
13
+ description: string;
14
+ labels?: string[];
15
+ issueNumber?: string;
16
+ channelId?: string;
17
+ }
18
+ interface HandleTaskResult {
19
+ success: boolean;
20
+ error?: string;
21
+ route?: RouteResult;
22
+ plan?: ExecutionPlan;
23
+ context?: string;
24
+ configDir?: string;
25
+ }
26
+ export declare function getChannelMode(channelId: string): string;
27
+ export declare function shouldUseIcexFlow(channelId: string): boolean;
28
+ export declare function handleTask(ctx: OpenClawContext, task: OpenClawTaskInput): Promise<HandleTaskResult>;
29
+ export declare function routeViaCLI(description: string, labels?: string[]): string;
30
+ export declare function planViaCLI(workflow: string, input?: Record<string, string>): string;
31
+ export {};
@@ -0,0 +1,118 @@
1
+ /**
2
+ * OpenClaw adapter for icex-flow
3
+ * Provides helpers for OpenClaw skills to use icex-flow routing and planning
4
+ */
5
+ import { routeTask } from '../engine/router.js';
6
+ import { planWorkflow } from '../engine/planner.js';
7
+ import { assembleContext } from '../engine/context.js';
8
+ import { mergeRoutes, mergeWorkflows, mergeContextManifest } from '../engine/config.js';
9
+ import { execSync } from 'node:child_process';
10
+ import { existsSync, readFileSync } from 'node:fs';
11
+ import { join, resolve } from 'node:path';
12
+ // Resolve icex-flow config directory
13
+ // Priority: project-specific .icex-flow/ > workspace .icex-flow/ > ~/.icex-flow/
14
+ function resolveConfigDir(workspacePath, projectPath) {
15
+ const candidates = [
16
+ projectPath && join(projectPath, '.icex-flow'),
17
+ join(workspacePath, '.icex-flow'),
18
+ join(process.env.HOME || '~', '.icex-flow'),
19
+ ].filter(Boolean);
20
+ for (const candidate of candidates) {
21
+ if (existsSync(candidate))
22
+ return candidate;
23
+ }
24
+ throw new Error('No .icex-flow configuration found. Run: icex-flow init');
25
+ }
26
+ // Channel ID to mode mapping
27
+ const CHANNEL_MODES = {
28
+ '1477537830053089341': 'dev-execute', // #dev
29
+ '1477537900437438474': 'dev-execute', // #ops
30
+ '1477549408487997520': 'dev-execute', // #qa
31
+ '1477549454339866716': 'dev-discuss', // #arch
32
+ '1476693934255247545': 'casual', // #general
33
+ '1477538241233885296': 'read-only', // #notifications
34
+ };
35
+ export function getChannelMode(channelId) {
36
+ return CHANNEL_MODES[channelId] || 'casual';
37
+ }
38
+ export function shouldUseIcexFlow(channelId) {
39
+ const mode = getChannelMode(channelId);
40
+ return mode === 'dev-execute' || mode === 'dev-discuss';
41
+ }
42
+ // Main entry point for OpenClaw skills
43
+ export async function handleTask(ctx, task) {
44
+ const configDir = resolveConfigDir(ctx.workspacePath);
45
+ const projectDir = resolve(configDir, '..');
46
+ // 1. Route the task
47
+ const routes = mergeRoutes(projectDir);
48
+ if (!routes) {
49
+ return {
50
+ success: false,
51
+ error: 'No routes configuration found. Run: icex-flow init',
52
+ };
53
+ }
54
+ const routeResult = routeTask(routes, {
55
+ description: task.description,
56
+ labels: task.labels,
57
+ channel: task.channelId,
58
+ });
59
+ // 2. Find workflow
60
+ const allWorkflows = mergeWorkflows(projectDir);
61
+ const workflow = allWorkflows.find((w) => w.name === routeResult.workflow);
62
+ if (!workflow) {
63
+ // Also try loading directly from the workflows directory
64
+ const workflowPath = join(configDir, 'workflows', `${routeResult.workflow}.flow.json`);
65
+ if (!existsSync(workflowPath)) {
66
+ return {
67
+ success: false,
68
+ error: `Workflow "${routeResult.workflow}" not found`,
69
+ route: routeResult,
70
+ };
71
+ }
72
+ const loadedWorkflow = JSON.parse(readFileSync(workflowPath, 'utf-8'));
73
+ return buildResult(loadedWorkflow, routeResult, task, configDir, projectDir);
74
+ }
75
+ return buildResult(workflow, routeResult, task, configDir, projectDir);
76
+ }
77
+ function buildResult(workflow, routeResult, task, configDir, projectDir) {
78
+ // 3. Generate plan
79
+ const variables = {};
80
+ if (task.issueNumber)
81
+ variables.issue_number = task.issueNumber;
82
+ if (task.description)
83
+ variables.task_description = task.description;
84
+ const plan = planWorkflow(workflow, variables);
85
+ // 4. Assemble context for the workflow
86
+ const manifest = mergeContextManifest(projectDir);
87
+ let context;
88
+ if (manifest) {
89
+ try {
90
+ const firstStepId = plan.steps[0]?.id;
91
+ context = assembleContext(manifest, projectDir, routeResult.workflow, firstStepId, plan.variables);
92
+ }
93
+ catch {
94
+ // Context assembly is best-effort; don't fail the whole task
95
+ }
96
+ }
97
+ return {
98
+ success: true,
99
+ route: routeResult,
100
+ plan,
101
+ context,
102
+ configDir,
103
+ };
104
+ }
105
+ // CLI wrapper for simple cases
106
+ export function routeViaCLI(description, labels) {
107
+ const args = [`icex-flow route "${description}"`];
108
+ if (labels?.length)
109
+ args.push(`--labels ${labels.join(',')}`);
110
+ return execSync(args.join(' '), { encoding: 'utf-8' });
111
+ }
112
+ export function planViaCLI(workflow, input) {
113
+ const args = [`icex-flow plan ${workflow}`];
114
+ if (input)
115
+ args.push(`--input '${JSON.stringify(input)}'`);
116
+ return execSync(args.join(' '), { encoding: 'utf-8' });
117
+ }
118
+ //# sourceMappingURL=openclaw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw.js","sourceRoot":"","sources":["../../../src/adapters/openclaw.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function main(args: string[]): void;
@@ -0,0 +1,95 @@
1
+ import { cmdInit } from './commands/init.js';
2
+ import { cmdValidate } from './commands/validate.js';
3
+ import { cmdRoute } from './commands/route.js';
4
+ import { cmdContext } from './commands/context.js';
5
+ import { cmdPlan } from './commands/plan.js';
6
+ import { cmdList } from './commands/list.js';
7
+ import { cmdVerify } from './commands/verify.js';
8
+ import { cmdProjects } from './commands/projects.js';
9
+ import { cmdGenerate } from './commands/generate.js';
10
+ import { cmdLearn } from './commands/learn.js';
11
+ const VERSION = '0.2.0';
12
+ const HELP = `
13
+ icex-flow v${VERSION} — Deterministic agent workflow orchestration
14
+
15
+ Usage: icex-flow <command> [options]
16
+
17
+ Commands:
18
+ init [dir] [--force] Initialize .icex-flow/ with smart auto-detection
19
+ generate [--dir .] Auto-generate PROJECT.md from scanned project
20
+ learn "<knowledge>" Store project knowledge (env, safety, arch)
21
+ learn --list List all stored knowledge
22
+ learn --remove <id> Remove a knowledge entry
23
+ validate [dir] [--global] Validate all workflow definitions
24
+ route "<description>" [--labels] Route a task to agent + workflow
25
+ context [workflow] [--step] Assemble context from manifest
26
+ plan <workflow> [--input '{}'] Generate deterministic execution plan
27
+ list [--dir .] List workflows and routes (merged)
28
+ verify --command "<cmd>" Run step verification
29
+ projects [list|add|remove] Manage registered projects
30
+
31
+ Options:
32
+ --dir <path> Working directory (default: .)
33
+ --json Output as JSON
34
+ --help, -h Show help
35
+ --version, -v Show version
36
+
37
+ Global Config: ~/.icex-flow/
38
+ config.json Global settings
39
+ projects.json Registry of all initialized projects
40
+ context/L0-global/ Global rules shared across all projects
41
+ workflows/ Global workflow templates (overridable per project)
42
+
43
+ Examples:
44
+ icex-flow init
45
+ icex-flow init --force
46
+ icex-flow route "fix login bug" --labels bug
47
+ icex-flow plan dev-chain --input '{"issue_number":"42","branch_name":"fix/login"}'
48
+ icex-flow context dev-chain --step implement
49
+ icex-flow verify --command "pytest tests/ -v" --expect-exit 0
50
+ icex-flow projects
51
+ icex-flow projects add /path/to/project
52
+ icex-flow projects remove /path/to/project
53
+ icex-flow validate --global
54
+ `.trim();
55
+ export function main(args) {
56
+ const command = args[0];
57
+ const rest = args.slice(1);
58
+ switch (command) {
59
+ case 'init':
60
+ return cmdInit(rest);
61
+ case 'generate':
62
+ return cmdGenerate(rest);
63
+ case 'learn':
64
+ return cmdLearn(rest);
65
+ case 'validate':
66
+ return cmdValidate(rest);
67
+ case 'route':
68
+ return cmdRoute(rest);
69
+ case 'context':
70
+ return cmdContext(rest);
71
+ case 'plan':
72
+ return cmdPlan(rest);
73
+ case 'list':
74
+ return cmdList(rest);
75
+ case 'verify':
76
+ return cmdVerify(rest);
77
+ case 'projects':
78
+ return cmdProjects(rest);
79
+ case '--version':
80
+ case '-v':
81
+ console.log(`icex-flow v${VERSION}`);
82
+ return;
83
+ case '--help':
84
+ case '-h':
85
+ case undefined:
86
+ console.log(HELP);
87
+ return;
88
+ default:
89
+ console.error(`Unknown command: ${command}`);
90
+ console.log('');
91
+ console.log(HELP);
92
+ process.exit(1);
93
+ }
94
+ }
95
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB,MAAM,IAAI,GAAG;aACA,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyCnB,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,UAAU,IAAI,CAAC,IAAc;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE3B,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM;YACT,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,KAAK,UAAU;YACb,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;QAC3B,KAAK,OAAO;YACV,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;QACxB,KAAK,UAAU;YACb,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;QAC3B,KAAK,OAAO;YACV,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;QACxB,KAAK,SAAS;YACZ,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;QAC1B,KAAK,MAAM;YACT,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,KAAK,MAAM;YACT,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,KAAK,QAAQ;YACX,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;QACzB,KAAK,UAAU;YACb,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;QAC3B,KAAK,WAAW,CAAC;QACjB,KAAK,IAAI;YACP,OAAO,CAAC,GAAG,CAAC,cAAc,OAAO,EAAE,CAAC,CAAC;YACrC,OAAO;QACT,KAAK,QAAQ,CAAC;QACd,KAAK,IAAI,CAAC;QACV,KAAK,SAAS;YACZ,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClB,OAAO;QACT;YACE,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;YAC7C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function cmdContext(args: string[]): void;
@@ -0,0 +1,40 @@
1
+ import { join, resolve } from 'node:path';
2
+ import { loadJson, parseFlags } from '../utils.js';
3
+ import { assembleContext, listContextFiles } from '../engine/context.js';
4
+ import { mergeContextManifest } from '../engine/config.js';
5
+ export function cmdContext(args) {
6
+ const { positional, flags } = parseFlags(args);
7
+ const workflow = positional[0];
8
+ const step = flags['step'];
9
+ const dir = flags['dir'] ?? '.';
10
+ const dryRun = flags['dry-run'] === 'true';
11
+ const baseDir = resolve(dir);
12
+ const manifestPath = join(baseDir, '.icex-flow', 'context.manifest.json');
13
+ // Try merged manifest (global + project), fall back to project-only
14
+ let manifest = mergeContextManifest(baseDir);
15
+ if (!manifest) {
16
+ manifest = loadJson(manifestPath);
17
+ }
18
+ // Parse vars from --var key=value flags
19
+ const vars = {};
20
+ if (flags['var']) {
21
+ for (const pair of flags['var'].split(',')) {
22
+ const [k, v] = pair.split('=');
23
+ if (k && v)
24
+ vars[k] = v;
25
+ }
26
+ }
27
+ if (dryRun) {
28
+ const files = listContextFiles(manifest, baseDir, workflow, step, vars);
29
+ console.log('Files to inject:');
30
+ for (const f of files) {
31
+ console.log(` - ${f}`);
32
+ }
33
+ console.log(`\nTotal: ${files.length} files`);
34
+ }
35
+ else {
36
+ const output = assembleContext(manifest, baseDir, workflow, step, vars);
37
+ console.log(output);
38
+ }
39
+ }
40
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAG3D,MAAM,UAAU,UAAU,CAAC,IAAc;IACvC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC;IAChC,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC;IAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,uBAAuB,CAAC,CAAC;IAE1E,oEAAoE;IACpE,IAAI,QAAQ,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,QAAQ,CAAkB,YAAY,CAAC,CAAC;IACrD,CAAC;IAED,wCAAwC;IACxC,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACjB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3C,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,IAAI,CAAC;gBAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACxE,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAChC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACxE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runGenerate(dir: string): void;
2
+ export declare function cmdGenerate(args: string[]): void;