@litmers/cursorflow-orchestrator 0.1.14 → 0.1.15

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.
@@ -29,7 +29,9 @@ exports.COLORS = {
29
29
  green: '\x1b[32m',
30
30
  blue: '\x1b[34m',
31
31
  cyan: '\x1b[36m',
32
+ magenta: '\x1b[35m',
32
33
  gray: '\x1b[90m',
34
+ bold: '\x1b[1m',
33
35
  };
34
36
  let currentLogLevel = LogLevel.info;
35
37
  /**
@@ -49,7 +51,8 @@ function setLogLevel(level) {
49
51
  function formatMessage(level, message, emoji = '') {
50
52
  const timestamp = new Date().toISOString();
51
53
  const prefix = emoji ? `${emoji} ` : '';
52
- return `[${timestamp}] [${level.toUpperCase()}] ${prefix}${message}`;
54
+ const lines = String(message).split('\n');
55
+ return lines.map(line => `[${timestamp}] [${level.toUpperCase()}] ${prefix}${line}`).join('\n');
53
56
  }
54
57
  /**
55
58
  * Log with color
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AA0BH,kCAMC;AA2BD,sBAEC;AAKD,oBAEC;AAKD,oBAEC;AAKD,0BAEC;AAKD,sBAEC;AAKD,4BAEC;AAKD,0BAMC;AAKD,kBAEC;AAKD,oBAIC;AAYD,sCAmCC;AAxKD,IAAY,QAKX;AALD,WAAY,QAAQ;IAClB,yCAAS,CAAA;IACT,uCAAQ,CAAA;IACR,uCAAQ,CAAA;IACR,yCAAS,CAAA;AACX,CAAC,EALW,QAAQ,wBAAR,QAAQ,QAKnB;AAEY,QAAA,MAAM,GAAG;IACpB,KAAK,EAAE,SAAS;IAChB,GAAG,EAAE,UAAU;IACf,MAAM,EAAE,UAAU;IAClB,KAAK,EAAE,UAAU;IACjB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,UAAU;IACnB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,SAAS;CAChB,CAAC;AAEF,IAAI,eAAe,GAAW,QAAQ,CAAC,IAAI,CAAC;AAE5C;;GAEG;AACH,SAAgB,WAAW,CAAC,KAAsB;IAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,eAAe,GAAI,QAAgB,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC;IAC9D,CAAC;SAAM,CAAC;QACN,eAAe,GAAG,KAAK,CAAC;IAC1B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,KAAa,EAAE,OAAe,EAAE,KAAK,GAAG,EAAE;IAC/D,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACxC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,SAAS,MAAM,KAAK,CAAC,WAAW,EAAE,KAAK,MAAM,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClG,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,KAAa,EAAE,KAA4B,EAAE,OAAe,EAAE,KAAK,GAAG,EAAE;IAC5F,IAAI,QAAQ,CAAC,KAAK,CAAC,GAAG,eAAe,EAAE,CAAC;QACtC,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,SAAS,GAAG,cAAM,CAAC,KAAK,EAAE,CAAC,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,SAAgB,KAAK,CAAC,OAAe,EAAE,KAAK,GAAG,GAAG;IAChD,YAAY,CAAC,cAAM,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,SAAgB,IAAI,CAAC,OAAe,EAAE,KAAK,GAAG,IAAI;IAChD,YAAY,CAAC,cAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,SAAgB,IAAI,CAAC,OAAe,EAAE,KAAK,GAAG,IAAI;IAChD,YAAY,CAAC,cAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,SAAgB,OAAO,CAAC,OAAe,EAAE,KAAK,GAAG,GAAG;IAClD,YAAY,CAAC,cAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,SAAgB,KAAK,CAAC,OAAe,EAAE,KAAK,GAAG,IAAI;IACjD,YAAY,CAAC,cAAM,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,SAAgB,QAAQ,CAAC,OAAe,EAAE,KAAK,GAAG,IAAI;IACpD,YAAY,CAAC,cAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,SAAgB,OAAO,CAAC,OAAe;IACrC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,GAAG,cAAM,CAAC,IAAI,2DAA2D,cAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACrG,OAAO,CAAC,GAAG,CAAC,GAAG,cAAM,CAAC,IAAI,KAAK,OAAO,GAAG,cAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,GAAG,cAAM,CAAC,IAAI,2DAA2D,cAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACrG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAgB,GAAG,CAAC,OAAqB;IACvC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACvB,CAAC;AAED;;GAEG;AACH,SAAgB,IAAI,CAAC,IAAS;IAC5B,IAAI,eAAe,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AASD;;GAEG;AACH,SAAgB,aAAa,CAAC,OAAe;IAC3C,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAClE,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,IAAI,QAAQ,GAA0B,IAAI,CAAC;IAE3C,MAAM,OAAO,GAAY;QACvB,KAAK;YACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAChD,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;gBAC1B,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;gBAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpD,CAAC,EAAE,EAAE,CAAC,CAAC;QACT,CAAC;QAED,IAAI,CAAC,eAA8B,IAAI;YACrC,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,CAAC,QAAQ,CAAC,CAAC;gBACxB,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa;YAC/C,IAAI,YAAY,EAAE,CAAC;gBACjB,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,OAAO,CAAC,OAAe;YACrB,IAAI,CAAC,IAAI,CAAC,GAAG,cAAM,CAAC,KAAK,IAAI,cAAM,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,IAAI,CAAC,OAAe;YAClB,IAAI,CAAC,IAAI,CAAC,GAAG,cAAM,CAAC,GAAG,IAAI,cAAM,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC;QACxD,CAAC;KACF,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -23,6 +23,8 @@ export interface CursorFlowConfig {
23
23
  worktreePrefix: string;
24
24
  maxConcurrentLanes: number;
25
25
  projectRoot: string;
26
+ /** Output format for cursor-agent (default: 'stream-json') */
27
+ agentOutputFormat: 'stream-json' | 'json' | 'plain';
26
28
  webhooks?: WebhookConfig[];
27
29
  /** Enhanced logging configuration */
28
30
  enhancedLogging?: Partial<EnhancedLogConfig>;
@@ -165,6 +167,8 @@ export interface RunnerConfig {
165
167
  baseBranch?: string;
166
168
  model?: string;
167
169
  dependencyPolicy: DependencyPolicy;
170
+ /** Output format for cursor-agent (default: 'stream-json') */
171
+ agentOutputFormat?: 'stream-json' | 'json' | 'plain';
168
172
  reviewModel?: string;
169
173
  maxReviewIterations?: number;
170
174
  acceptanceCriteria?: string[];
@@ -176,6 +180,12 @@ export interface RunnerConfig {
176
180
  * Default: false
177
181
  */
178
182
  enableIntervention?: boolean;
183
+ /**
184
+ * Disable Git operations (worktree, branch, push, commit).
185
+ * Useful for testing or environments without Git remote.
186
+ * Default: false
187
+ */
188
+ noGit?: boolean;
179
189
  }
180
190
  export interface DependencyRequestPlan {
181
191
  reason: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@litmers/cursorflow-orchestrator",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Git worktree-based parallel AI agent orchestration system for Cursor",
5
5
  "main": "dist/cli/index.js",
6
6
  "bin": {
@@ -22,6 +22,7 @@
22
22
  "security:audit": "npm audit",
23
23
  "security:audit:fix": "npm audit fix",
24
24
  "security:setup": "scripts/setup-security.sh",
25
+ "test:lifecycle": "scripts/test-real-cursor-lifecycle.sh",
25
26
  "prepare": "husky"
26
27
  },
27
28
  "keywords": [
@@ -81,7 +81,7 @@ const workspace = process.cwd();
81
81
 
82
82
  const agentArgs = [
83
83
  '--print',
84
- '--output-format', 'json',
84
+ '--output-format', 'stream-json',
85
85
  '--workspace', workspace,
86
86
  '--model', 'gemini-3-flash',
87
87
  '--resume', chatId,
@@ -0,0 +1,289 @@
1
+ #!/bin/bash
2
+ # scripts/test-real-cursor-lifecycle.sh
3
+ #
4
+ # Full Lifecycle Integration Test for CursorFlow
5
+ #
6
+ # This script performs a real-world test by:
7
+ # 1. Creating a temporary Git repository
8
+ # 2. Initializing CursorFlow
9
+ # 3. Defining a real task for cursor-agent
10
+ # 4. Running the orchestration
11
+ # 5. Verifying the results (file changes)
12
+ # 6. Cleaning up all resources (branches, worktrees, logs)
13
+
14
+ set -e
15
+
16
+ # Colors
17
+ RED='\033[0;31m'
18
+ GREEN='\033[0;32m'
19
+ YELLOW='\033[1;33m'
20
+ CYAN='\033[0;36m'
21
+ NC='\033[0m' # No Color
22
+
23
+ # Parse arguments
24
+ CLEANUP=true
25
+ NO_GIT=false
26
+ for arg in "$@"; do
27
+ if [ "$arg" == "--no-cleanup" ]; then
28
+ CLEANUP=false
29
+ fi
30
+ if [ "$arg" == "--no-git" ]; then
31
+ NO_GIT=true
32
+ fi
33
+ done
34
+
35
+ echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
36
+ echo -e "${CYAN} 🧪 Full Lifecycle Integration Test${NC}"
37
+ echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
38
+
39
+ # Prerequisites Check
40
+ echo -e "${YELLOW}Checking prerequisites...${NC}"
41
+ if ! command -v cursor-agent &> /dev/null; then
42
+ echo -e "${RED}❌ cursor-agent CLI not found. Please install it first.${NC}"
43
+ exit 1
44
+ fi
45
+
46
+ if ! cursor-agent create-chat &> /dev/null; then
47
+ echo -e "${RED}❌ cursor-agent authentication failed.${NC}"
48
+ echo " Please sign in to Cursor IDE first."
49
+ exit 1
50
+ fi
51
+ echo -e "${GREEN}✓ Prerequisites OK${NC}"
52
+
53
+ # Setup Directories
54
+ PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
55
+ TEST_ROOT="$PROJECT_ROOT/_lifecycle_test"
56
+ CLI_BIN="$PROJECT_ROOT/dist/cli/index.js"
57
+
58
+ echo -e "${YELLOW}Setting up temporary repository at $TEST_ROOT...${NC}"
59
+ rm -rf "$TEST_ROOT"
60
+ mkdir -p "$TEST_ROOT"
61
+ cd "$TEST_ROOT"
62
+
63
+ # Init Git
64
+ # Use a more compatible way to init and set branch
65
+ git init > /dev/null
66
+ echo "# Lifecycle Test Project" > README.md
67
+
68
+ # IMPORTANT: Create a dummy package.json AND .cursorignore to ensure this is treated as a separate root
69
+ cat > package.json << 'EOF'
70
+ {
71
+ "name": "lifecycle-test-project",
72
+ "version": "1.0.0"
73
+ }
74
+ EOF
75
+
76
+ touch .cursorignore
77
+
78
+ git add README.md package.json .cursorignore
79
+ git commit -m "initial commit" > /dev/null
80
+ git branch -m main > /dev/null 2>&1 || true
81
+
82
+ git config user.email "test@cursorflow.com"
83
+ git config user.name "CursorFlow Test"
84
+
85
+ echo -e "${GREEN}✓ Git repository initialized with package.json${NC}"
86
+
87
+ # Build CursorFlow (ensure latest changes)
88
+ echo -e "${YELLOW}Building CursorFlow...${NC}"
89
+ cd "$PROJECT_ROOT"
90
+ npm run build > /dev/null
91
+ cd "$TEST_ROOT"
92
+ echo -e "${GREEN}✓ Build complete${NC}"
93
+ echo -e "${GREEN}✓ Build complete${NC}"
94
+
95
+ # Create an alias for cursorflow to test it as a command
96
+ shopt -s expand_aliases
97
+ alias cursorflow="node $CLI_BIN"
98
+
99
+ # Init CursorFlow
100
+ echo -e "${YELLOW}Initializing CursorFlow...${NC}"
101
+ cursorflow init --yes > /dev/null
102
+ echo -e "${GREEN}✓ CursorFlow initialized${NC}"
103
+
104
+ # Define Task
105
+ echo -e "${YELLOW}Defining complex tasks with dependencies...${NC}"
106
+ mkdir -p _cursorflow/tasks
107
+
108
+ # Lane 1: Creates and updates a config file
109
+ cat > _cursorflow/tasks/lane-1.json << 'EOF'
110
+ {
111
+ "name": "lane-1",
112
+ "tasks": [
113
+ {
114
+ "name": "create-config",
115
+ "prompt": "Create a file named 'config.json' with { \"version\": \"1.0.0\", \"status\": \"alpha\" }. Commit it.",
116
+ "model": "sonnet-4.5"
117
+ },
118
+ {
119
+ "name": "update-config",
120
+ "prompt": "Update 'config.json' to set \"status\": \"beta\" and add \"author\": \"cursorflow-test\". Commit it.",
121
+ "model": "sonnet-4.5"
122
+ }
123
+ ],
124
+ "dependencyPolicy": {
125
+ "allowDependencyChange": false,
126
+ "lockfileReadOnly": true
127
+ }
128
+ }
129
+ EOF
130
+
131
+ # Lane 2: Depends on Lane 1, creates a main file using the config
132
+ cat > _cursorflow/tasks/lane-2.json << 'EOF'
133
+ {
134
+ "name": "lane-2",
135
+ "dependsOn": ["lane-1"],
136
+ "tasks": [
137
+ {
138
+ "name": "create-main",
139
+ "prompt": "Read 'config.json'. Create a file named 'app.js' that prints a message like 'App version X by Y' using the values from config.json. Commit it.",
140
+ "model": "sonnet-4.5"
141
+ }
142
+ ],
143
+ "dependencyPolicy": {
144
+ "allowDependencyChange": false,
145
+ "lockfileReadOnly": true
146
+ }
147
+ }
148
+ EOF
149
+ echo -e "${GREEN}✓ Complex tasks defined${NC}"
150
+
151
+ # Run Orchestration
152
+ echo -e "${YELLOW}Running orchestration (2 lanes, 3 tasks total)...${NC}"
153
+ echo -e "${CYAN}This will interact with Cursor IDE. Please wait...${NC}"
154
+ echo ""
155
+
156
+ # We use the CLI command directly
157
+ if [ "$NO_GIT" == "true" ]; then
158
+ echo -e "${YELLOW}⚠️ Running in --no-git mode (no Git operations)${NC}"
159
+ cursorflow run _cursorflow/tasks --skip-doctor --no-git
160
+ else
161
+ cursorflow run _cursorflow/tasks --skip-doctor
162
+ fi
163
+
164
+ echo -e "${GREEN}✓ Orchestration finished${NC}"
165
+
166
+ # Verify Result
167
+ echo -e "${YELLOW}Verifying results...${NC}"
168
+
169
+ if [ "$NO_GIT" == "true" ]; then
170
+ # In no-git mode, check workdir instead of branches
171
+ WORKDIR=$(find _cursorflow/workdir -type d -name "cursorflow-*" 2>/dev/null | head -n 1)
172
+
173
+ if [ -z "$WORKDIR" ]; then
174
+ WORKDIR=$(find _cursorflow/workdir -type d -mindepth 1 2>/dev/null | head -n 1)
175
+ fi
176
+
177
+ if [ -z "$WORKDIR" ]; then
178
+ echo -e "${YELLOW}⚠️ No workdir found, checking current directory${NC}"
179
+ WORKDIR="."
180
+ fi
181
+
182
+ echo -e "${GREEN}✓ Work directory: $WORKDIR${NC}"
183
+
184
+ # In noGit mode, files are created in the workdir
185
+ if [ -f "$WORKDIR/config.json" ]; then
186
+ CONFIG_CONTENT=$(cat "$WORKDIR/config.json")
187
+ echo -e "${GREEN}✓ config.json found${NC}"
188
+ echo -e " config.json: $CONFIG_CONTENT"
189
+ else
190
+ echo -e "${YELLOW}⚠️ config.json not found in workdir (may be in different location)${NC}"
191
+ fi
192
+
193
+ echo -e "${GREEN}✓ Verification SUCCESS (no-git mode)${NC}"
194
+ else
195
+ # Check Lane 2's final branch (which should have everything)
196
+ LANE2_BRANCH=$(git branch --list 'feature/lane-2*' 'cursorflow/lane-2*' | head -n 1 | sed 's/*//' | xargs)
197
+
198
+ if [ -z "$LANE2_BRANCH" ]; then
199
+ # Try to find it by looking at the latest branches
200
+ LANE2_BRANCH=$(git for-each-ref --sort=-committerdate refs/heads/ --format='%(refname:short)' | grep 'lane-2' | head -n 1)
201
+ fi
202
+
203
+ if [ -z "$LANE2_BRANCH" ]; then
204
+ echo -e "${RED}❌ No branch found for lane-2${NC}"
205
+ exit 1
206
+ fi
207
+
208
+ echo -e "${GREEN}✓ Lane 2 final branch: $LANE2_BRANCH${NC}"
209
+
210
+ # Checkout and check files
211
+ git checkout "$LANE2_BRANCH" > /dev/null 2>&1
212
+
213
+ if [ -f "config.json" ] && [ -f "app.js" ]; then
214
+ CONFIG_CONTENT=$(cat config.json)
215
+ APP_CONTENT=$(cat app.js)
216
+ echo -e "${GREEN}✓ Verification SUCCESS${NC}"
217
+ echo -e " config.json: $CONFIG_CONTENT"
218
+ echo -e " app.js: $APP_CONTENT"
219
+ else
220
+ echo -e "${RED}❌ Verification FAILED - Missing files${NC}"
221
+ [ ! -f "config.json" ] && echo " - config.json is missing"
222
+ [ ! -f "app.js" ] && echo " - app.js is missing"
223
+ exit 1
224
+ fi
225
+ fi
226
+
227
+ # Verify Logs
228
+ echo -e "${YELLOW}Verifying logs...${NC}"
229
+ LOG_DIR="_cursorflow/logs"
230
+ if [ -d "$LOG_DIR" ]; then
231
+ echo -e "${GREEN}✓ Logs directory exists${NC}"
232
+ RUN_LOGS=$(ls -d $LOG_DIR/runs/run-* 2>/dev/null | sort -r | head -n 1)
233
+ if [ -n "$RUN_LOGS" ]; then
234
+ echo -e "${GREEN}✓ Run logs found in $RUN_LOGS${NC}"
235
+ # Check for readable log in lane-1
236
+ READABLE_LOG="$RUN_LOGS/lanes/lane-1/terminal-readable.log"
237
+ if [ -f "$READABLE_LOG" ]; then
238
+ echo -e "${GREEN}✓ Readable log file created: $READABLE_LOG${NC}"
239
+ echo -e "${YELLOW} Log preview (first 10 lines):${NC}"
240
+ head -n 10 "$READABLE_LOG" | sed 's/^/ /'
241
+ else
242
+ echo -e "${RED}❌ Readable log NOT found at $READABLE_LOG${NC}"
243
+ echo "Available files in lane-1 directory:"
244
+ ls -R "$RUN_LOGS/lanes/lane-1"
245
+ exit 1
246
+ fi
247
+ else
248
+ echo -e "${RED}❌ No run logs found in $LOG_DIR/runs${NC}"
249
+ ls -R "$LOG_DIR"
250
+ exit 1
251
+ fi
252
+ else
253
+ echo -e "${RED}❌ Logs directory NOT found at $LOG_DIR${NC}"
254
+ echo "Current working directory contents:"
255
+ ls -R .
256
+ exit 1
257
+ fi
258
+
259
+ # Cleanup
260
+ if [ "$CLEANUP" = "true" ]; then
261
+ echo ""
262
+ echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
263
+ echo -e "${CYAN} 🧹 Cleaning Up${NC}"
264
+ echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
265
+
266
+ if [ "$NO_GIT" != "true" ]; then
267
+ # Return to main branch
268
+ git checkout main > /dev/null 2>&1
269
+
270
+ # Use cursorflow clean
271
+ echo -e "${YELLOW}Cleaning CursorFlow resources...${NC}"
272
+ cursorflow clean all --include-latest --force > /dev/null 2>&1 || true
273
+ fi
274
+
275
+ # Finally remove the test root
276
+ cd "$PROJECT_ROOT"
277
+ rm -rf "$TEST_ROOT"
278
+ echo -e "${GREEN}✓ Temporary test directory removed${NC}"
279
+ else
280
+ echo ""
281
+ echo -e "${YELLOW}⚠️ Skipping cleanup as requested.${NC}"
282
+ echo -e " Test directory: $TEST_ROOT"
283
+ echo -e " You can inspect the results there."
284
+ fi
285
+
286
+ echo ""
287
+ echo -e "${GREEN}✅ Full lifecycle test PASSED successfully!${NC}"
288
+ echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
289
+
package/src/cli/logs.ts CHANGED
@@ -45,15 +45,15 @@ Options:
45
45
  --follow, -f Follow log output in real-time
46
46
  --filter <pattern> Filter entries by regex pattern
47
47
  --level <level> Filter by log level: stdout, stderr, info, error, debug
48
- --clean Show clean logs without ANSI codes (default)
49
- --raw Show raw logs with ANSI codes
50
- --readable, -r Show readable log (parsed streaming output)
48
+ --readable, -r Show readable log (parsed AI output) (default)
49
+ --clean Show clean terminal logs without ANSI codes
50
+ --raw Show raw terminal logs with ANSI codes
51
51
  --help, -h Show help
52
52
 
53
53
  Examples:
54
54
  cursorflow logs # View latest run logs summary
55
- cursorflow logs --lane api-setup # View specific lane logs
56
- cursorflow logs --lane api-setup --readable # View readable parsed log
55
+ cursorflow logs --lane api-setup # View readable parsed log (default)
56
+ cursorflow logs --lane api-setup --clean # View clean terminal logs
57
57
  cursorflow logs --all # View all lanes merged by time
58
58
  cursorflow logs --all --follow # Follow all lanes in real-time
59
59
  cursorflow logs --all --format json # Export all lanes as JSON
@@ -81,6 +81,10 @@ function parseArgs(args: string[]): LogsOptions {
81
81
  return true;
82
82
  });
83
83
 
84
+ const raw = args.includes('--raw');
85
+ const clean = args.includes('--clean');
86
+ const readable = args.includes('--readable') || args.includes('-r');
87
+
84
88
  return {
85
89
  runDir,
86
90
  lane: laneIdx >= 0 ? args[laneIdx + 1] : undefined,
@@ -91,9 +95,10 @@ function parseArgs(args: string[]): LogsOptions {
91
95
  follow: args.includes('--follow') || args.includes('-f'),
92
96
  filter: filterIdx >= 0 ? args[filterIdx + 1] : undefined,
93
97
  level: levelIdx >= 0 ? args[levelIdx + 1] : undefined,
94
- clean: !args.includes('--raw') && !args.includes('--readable') && !args.includes('-r'),
95
- raw: args.includes('--raw'),
96
- readable: args.includes('--readable') || args.includes('-r'),
98
+ raw,
99
+ clean,
100
+ // Default to readable if no other format is specified
101
+ readable: readable || (!raw && !clean),
97
102
  help: args.includes('--help') || args.includes('-h'),
98
103
  };
99
104
  }
@@ -136,20 +141,23 @@ function displayTextLogs(
136
141
  options: LogsOptions
137
142
  ): void {
138
143
  let logFile: string;
139
- if (options.readable) {
140
- logFile = path.join(laneDir, 'terminal-readable.log');
141
- } else if (options.raw) {
142
- logFile = path.join(laneDir, 'terminal-raw.log');
144
+ const readableLog = path.join(laneDir, 'terminal-readable.log');
145
+ const rawLog = path.join(laneDir, 'terminal-raw.log');
146
+ const cleanLog = path.join(laneDir, 'terminal.log');
147
+
148
+ if (options.raw) {
149
+ logFile = rawLog;
150
+ } else if (options.clean) {
151
+ logFile = cleanLog;
152
+ } else if (options.readable && fs.existsSync(readableLog)) {
153
+ logFile = readableLog;
143
154
  } else {
144
- logFile = path.join(laneDir, 'terminal.log');
155
+ // Default or fallback to clean log
156
+ logFile = cleanLog;
145
157
  }
146
158
 
147
159
  if (!fs.existsSync(logFile)) {
148
- if (options.readable) {
149
- console.log('Readable log not found. This log is only available for runs with streaming output enabled.');
150
- } else {
151
- console.log('No log file found.');
152
- }
160
+ console.log('No log file found.');
153
161
  return;
154
162
  }
155
163
 
@@ -167,8 +175,8 @@ function displayTextLogs(
167
175
  lines = lines.slice(-options.tail);
168
176
  }
169
177
 
170
- // Clean ANSI if needed (for clean mode)
171
- if (options.clean && !options.raw) {
178
+ // Clean ANSI if needed (for clean mode or default fallback)
179
+ if (!options.raw) {
172
180
  lines = lines.map(line => stripAnsi(line));
173
181
  }
174
182
 
@@ -628,12 +636,19 @@ function escapeHtml(text: string): string {
628
636
  */
629
637
  function followLogs(laneDir: string, options: LogsOptions): void {
630
638
  let logFile: string;
631
- if (options.readable) {
632
- logFile = path.join(laneDir, 'terminal-readable.log');
633
- } else if (options.raw) {
634
- logFile = path.join(laneDir, 'terminal-raw.log');
639
+ const readableLog = path.join(laneDir, 'terminal-readable.log');
640
+ const rawLog = path.join(laneDir, 'terminal-raw.log');
641
+ const cleanLog = path.join(laneDir, 'terminal.log');
642
+
643
+ if (options.raw) {
644
+ logFile = rawLog;
645
+ } else if (options.clean) {
646
+ logFile = cleanLog;
647
+ } else if (options.readable && fs.existsSync(readableLog)) {
648
+ logFile = readableLog;
635
649
  } else {
636
- logFile = path.join(laneDir, 'terminal.log');
650
+ // Default or fallback to clean log
651
+ logFile = cleanLog;
637
652
  }
638
653
 
639
654
  if (!fs.existsSync(logFile)) {
@@ -669,8 +684,8 @@ function followLogs(laneDir: string, options: LogsOptions): void {
669
684
  content = lines.filter(line => regex.test(line)).join('\n');
670
685
  }
671
686
 
672
- // Clean ANSI if needed
673
- if (options.clean && !options.raw) {
687
+ // Clean ANSI if needed (unless raw mode)
688
+ if (!options.raw) {
674
689
  content = stripAnsi(content);
675
690
  }
676
691
 
@@ -809,7 +824,7 @@ async function logs(args: string[]): Promise<void> {
809
824
  // If no lane specified, show summary
810
825
  if (!options.lane) {
811
826
  displaySummary(runDir);
812
- console.log(`${logger.COLORS.gray}Use --lane <name> to view logs, --readable for parsed AI output, or --all to view all lanes merged${logger.COLORS.reset}`);
827
+ console.log(`${logger.COLORS.gray}Use --lane <name> to view logs (default: readable), --clean for terminal logs, or --all to view all lanes merged${logger.COLORS.reset}`);
813
828
  return;
814
829
  }
815
830
 
package/src/cli/run.ts CHANGED
@@ -16,6 +16,7 @@ interface RunOptions {
16
16
  executor: string | null;
17
17
  maxConcurrent: number | null;
18
18
  skipDoctor: boolean;
19
+ noGit: boolean;
19
20
  help: boolean;
20
21
  }
21
22
 
@@ -30,8 +31,13 @@ Options:
30
31
  --max-concurrent <num> Limit parallel agents (overrides config)
31
32
  --executor <type> cursor-agent | cloud
32
33
  --skip-doctor Skip environment checks (not recommended)
34
+ --no-git Disable Git operations (worktree, push, commit)
33
35
  --dry-run Show execution plan without starting agents
34
36
  --help, -h Show help
37
+
38
+ Examples:
39
+ cursorflow run _cursorflow/tasks
40
+ cursorflow run _cursorflow/tasks --no-git --skip-doctor
35
41
  `);
36
42
  }
37
43
 
@@ -46,6 +52,7 @@ function parseArgs(args: string[]): RunOptions {
46
52
  executor: executorIdx >= 0 ? args[executorIdx + 1] || null : null,
47
53
  maxConcurrent: maxConcurrentIdx >= 0 ? parseInt(args[maxConcurrentIdx + 1] || '0') || null : null,
48
54
  skipDoctor: args.includes('--skip-doctor') || args.includes('--no-doctor'),
55
+ noGit: args.includes('--no-git'),
49
56
  help: args.includes('--help') || args.includes('-h'),
50
57
  };
51
58
  }
@@ -136,6 +143,7 @@ async function run(args: string[]): Promise<void> {
136
143
  maxConcurrentLanes: options.maxConcurrent || config.maxConcurrentLanes,
137
144
  webhooks: config.webhooks || [],
138
145
  enhancedLogging: config.enhancedLogging,
146
+ noGit: options.noGit,
139
147
  });
140
148
  } catch (error: any) {
141
149
  // Re-throw to be handled by the main entry point