@litmers/cursorflow-orchestrator 0.1.15 → 0.1.20
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.
- package/CHANGELOG.md +23 -1
- package/README.md +26 -7
- package/commands/cursorflow-run.md +2 -0
- package/commands/cursorflow-triggers.md +250 -0
- package/dist/cli/clean.js +8 -7
- package/dist/cli/clean.js.map +1 -1
- package/dist/cli/index.js +5 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.js +20 -14
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/logs.js +64 -47
- package/dist/cli/logs.js.map +1 -1
- package/dist/cli/monitor.js +27 -17
- package/dist/cli/monitor.js.map +1 -1
- package/dist/cli/prepare.js +73 -33
- package/dist/cli/prepare.js.map +1 -1
- package/dist/cli/resume.js +193 -40
- package/dist/cli/resume.js.map +1 -1
- package/dist/cli/run.js +3 -2
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/signal.js +7 -7
- package/dist/cli/signal.js.map +1 -1
- package/dist/core/orchestrator.d.ts +2 -1
- package/dist/core/orchestrator.js +54 -93
- package/dist/core/orchestrator.js.map +1 -1
- package/dist/core/reviewer.d.ts +6 -4
- package/dist/core/reviewer.js +7 -5
- package/dist/core/reviewer.js.map +1 -1
- package/dist/core/runner.d.ts +8 -0
- package/dist/core/runner.js +219 -32
- package/dist/core/runner.js.map +1 -1
- package/dist/utils/config.js +20 -10
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/doctor.js +35 -7
- package/dist/utils/doctor.js.map +1 -1
- package/dist/utils/enhanced-logger.d.ts +2 -2
- package/dist/utils/enhanced-logger.js +114 -43
- package/dist/utils/enhanced-logger.js.map +1 -1
- package/dist/utils/git.js +163 -10
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/log-formatter.d.ts +16 -0
- package/dist/utils/log-formatter.js +194 -0
- package/dist/utils/log-formatter.js.map +1 -0
- package/dist/utils/path.d.ts +19 -0
- package/dist/utils/path.js +77 -0
- package/dist/utils/path.js.map +1 -0
- package/dist/utils/repro-thinking-logs.d.ts +1 -0
- package/dist/utils/repro-thinking-logs.js +80 -0
- package/dist/utils/repro-thinking-logs.js.map +1 -0
- package/dist/utils/state.d.ts +4 -1
- package/dist/utils/state.js +11 -8
- package/dist/utils/state.js.map +1 -1
- package/dist/utils/template.d.ts +14 -0
- package/dist/utils/template.js +122 -0
- package/dist/utils/template.js.map +1 -0
- package/dist/utils/types.d.ts +13 -0
- package/dist/utils/webhook.js +3 -0
- package/dist/utils/webhook.js.map +1 -1
- package/package.json +4 -2
- package/scripts/ai-security-check.js +3 -0
- package/scripts/local-security-gate.sh +9 -1
- package/scripts/verify-and-fix.sh +37 -0
- package/src/cli/clean.ts +8 -7
- package/src/cli/index.ts +5 -1
- package/src/cli/init.ts +19 -15
- package/src/cli/logs.ts +67 -47
- package/src/cli/monitor.ts +28 -18
- package/src/cli/prepare.ts +75 -35
- package/src/cli/resume.ts +810 -626
- package/src/cli/run.ts +3 -2
- package/src/cli/signal.ts +7 -6
- package/src/core/orchestrator.ts +68 -93
- package/src/core/reviewer.ts +14 -9
- package/src/core/runner.ts +229 -33
- package/src/utils/config.ts +19 -11
- package/src/utils/doctor.ts +38 -7
- package/src/utils/enhanced-logger.ts +117 -49
- package/src/utils/git.ts +145 -11
- package/src/utils/log-formatter.ts +162 -0
- package/src/utils/path.ts +45 -0
- package/src/utils/repro-thinking-logs.ts +54 -0
- package/src/utils/state.ts +16 -8
- package/src/utils/template.ts +92 -0
- package/src/utils/types.ts +13 -0
- package/src/utils/webhook.ts +3 -0
- package/templates/basic.json +21 -0
- package/scripts/simple-logging-test.sh +0 -97
- package/scripts/test-real-cursor-lifecycle.sh +0 -289
- package/scripts/test-real-logging.sh +0 -289
- package/scripts/test-streaming-multi-task.sh +0 -247
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.isSafePath = isSafePath;
|
|
37
|
+
exports.safeJoin = safeJoin;
|
|
38
|
+
exports.normalizePath = normalizePath;
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
/**
|
|
41
|
+
* Ensures that a path is safe and stays within a base directory.
|
|
42
|
+
* Prevents path traversal attacks.
|
|
43
|
+
*/
|
|
44
|
+
function isSafePath(baseDir, ...parts) {
|
|
45
|
+
const joined = path.join(baseDir, ...parts); // nosemgrep
|
|
46
|
+
const resolvedBase = path.resolve(baseDir); // nosemgrep
|
|
47
|
+
const resolvedJoined = path.resolve(joined); // nosemgrep
|
|
48
|
+
return resolvedJoined.startsWith(resolvedBase);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Safely joins path parts and ensures the result is within the base directory.
|
|
52
|
+
* Throws an error if path traversal is detected.
|
|
53
|
+
*
|
|
54
|
+
* @param baseDir The base directory that the resulting path must be within
|
|
55
|
+
* @param parts Path parts to join
|
|
56
|
+
* @returns The joined path
|
|
57
|
+
* @throws Error if the resulting path is outside the base directory
|
|
58
|
+
*/
|
|
59
|
+
function safeJoin(baseDir, ...parts) {
|
|
60
|
+
const joined = path.join(baseDir, ...parts); // nosemgrep
|
|
61
|
+
const resolvedBase = path.resolve(baseDir); // nosemgrep
|
|
62
|
+
const resolvedJoined = path.resolve(joined); // nosemgrep
|
|
63
|
+
if (!resolvedJoined.startsWith(resolvedBase)) {
|
|
64
|
+
throw new Error(`Potential path traversal detected: ${joined} is outside of ${baseDir}`);
|
|
65
|
+
}
|
|
66
|
+
return joined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Normalizes a path and checks if it's absolute or relative to project root.
|
|
70
|
+
*/
|
|
71
|
+
function normalizePath(p, projectRoot) {
|
|
72
|
+
if (path.isAbsolute(p)) {
|
|
73
|
+
return path.normalize(p);
|
|
74
|
+
}
|
|
75
|
+
return path.join(projectRoot, p); // nosemgrep
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,gCAMC;AAWD,4BAUC;AAKD,sCAKC;AA3CD,2CAA6B;AAE7B;;;GAGG;AACH,SAAgB,UAAU,CAAC,OAAe,EAAE,GAAG,KAAe;IAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,YAAY;IACzD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY;IACxD,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY;IAEzD,OAAO,cAAc,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,QAAQ,CAAC,OAAe,EAAE,GAAG,KAAe;IAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,YAAY;IACzD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY;IACxD,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY;IAEzD,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,sCAAsC,MAAM,kBAAkB,OAAO,EAAE,CAAC,CAAC;IAC3F,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAgB,aAAa,CAAC,CAAS,EAAE,WAAmB;IAC1D,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY;AAChD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const fs = __importStar(require("fs"));
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const enhanced_logger_1 = require("./enhanced-logger");
|
|
39
|
+
async function testThinkingLogs() {
|
|
40
|
+
const testDir = path.join(process.cwd(), '_test_thinking_logs');
|
|
41
|
+
if (fs.existsSync(testDir)) {
|
|
42
|
+
fs.rmSync(testDir, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
fs.mkdirSync(testDir, { recursive: true });
|
|
45
|
+
console.log('--- Initializing Log Manager ---');
|
|
46
|
+
const manager = (0, enhanced_logger_1.createLogManager)(testDir, 'test-lane-thinking', {
|
|
47
|
+
writeJsonLog: true,
|
|
48
|
+
keepRawLogs: true
|
|
49
|
+
});
|
|
50
|
+
manager.setTask('repro-thinking-task', 'sonnet-4.5-thinking');
|
|
51
|
+
const logLines = [
|
|
52
|
+
'{"type":"tool_call","subtype":"started","call_id":"0_tool_54a8fcc9-6981-4f59-aeb6-3ab6d37b2","tool_call":{"readToolCall":{"args":{"path":"/home/eugene/workbench/workbench-os-eungjin/_cursorflow/worktrees/cursorflow/run-mjfxp57i/agent_output.txt"}}}}',
|
|
53
|
+
'{"type":"thinking","subtype":"delta","text":"**Defining Installation Strategy**\\n\\nI\'ve considered the `package.json` file as the central point for installation in automated environments. Thinking now about how that impacts the user\'s ultimate goal, given this is how the process begins in these environments.\\n\\n\\n"}',
|
|
54
|
+
'{"type":"thinking","subtype":"delta","text":"**Clarifying Execution Context**\\n\\nI\'m focused on the user\'s explicit command: `pnpm add @convex-dev/agent ai @ai-sdk/google zod`. My inability to directly execute this is a key constraint. I\'m exploring ways to inform the user about this. I\'ve considered that, without the tools required to run the original command, any attempt to run a command like `grep` or `date` is pointless and will fail.\\n\\n\\n"}',
|
|
55
|
+
'{"type":"tool_call","subtype":"started","call_id":"0_tool_d8f826c8-9d8f-4cab-9ff8-1c47d1ac1","tool_call":{"shellToolCall":{"args":{"command":"date"}}}}'
|
|
56
|
+
];
|
|
57
|
+
console.log('\n--- Feeding Log Lines to Manager ---');
|
|
58
|
+
for (const line of logLines) {
|
|
59
|
+
console.log('Processing:', line.substring(0, 100) + '...');
|
|
60
|
+
manager.writeStdout(line + '\n');
|
|
61
|
+
}
|
|
62
|
+
manager.close();
|
|
63
|
+
console.log('\n--- Verifying terminal-readable.log ---');
|
|
64
|
+
const readableLog = fs.readFileSync(path.join(testDir, 'terminal-readable.log'), 'utf8');
|
|
65
|
+
console.log(readableLog);
|
|
66
|
+
console.log('\n--- Verifying terminal.jsonl (last 3 entries) ---');
|
|
67
|
+
const jsonlLog = fs.readFileSync(path.join(testDir, 'terminal.jsonl'), 'utf8');
|
|
68
|
+
const lines = jsonlLog.trim().split('\n');
|
|
69
|
+
for (const line of lines.slice(-3)) {
|
|
70
|
+
const parsed = JSON.parse(line);
|
|
71
|
+
console.log(JSON.stringify({
|
|
72
|
+
level: parsed.level,
|
|
73
|
+
message: parsed.message.substring(0, 50) + '...',
|
|
74
|
+
hasMetadata: !!parsed.metadata,
|
|
75
|
+
metadataType: parsed.metadata?.type
|
|
76
|
+
}, null, 2));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
testThinkingLogs().catch(console.error);
|
|
80
|
+
//# sourceMappingURL=repro-thinking-logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repro-thinking-logs.js","sourceRoot":"","sources":["../../src/utils/repro-thinking-logs.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,2CAA6B;AAC7B,uDAAqD;AAErD,KAAK,UAAU,gBAAgB;IAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,qBAAqB,CAAC,CAAC;IAChE,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC;IACD,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE3C,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,IAAA,kCAAgB,EAAC,OAAO,EAAE,oBAAoB,EAAE;QAC9D,YAAY,EAAE,IAAI;QAClB,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IAEH,OAAO,CAAC,OAAO,CAAC,qBAAqB,EAAE,qBAAqB,CAAC,CAAC;IAE9D,MAAM,QAAQ,GAAG;QACf,2PAA2P;QAC3P,sUAAsU;QACtU,6cAA6c;QAC7c,yJAAyJ;KAC1J,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IACtD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QAC3D,OAAO,CAAC,WAAW,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,CAAC,KAAK,EAAE,CAAC;IAEhB,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,uBAAuB,CAAC,EAAE,MAAM,CAAC,CAAC;IACzF,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAEzB,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC,CAAC;IAC/E,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;YACzB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK;YAChD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ;YAC9B,YAAY,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI;SACpC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACf,CAAC;AACH,CAAC;AAED,gBAAgB,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
|
package/dist/utils/state.d.ts
CHANGED
|
@@ -22,7 +22,10 @@ export declare function readLog<T = any>(logPath: string): T[];
|
|
|
22
22
|
/**
|
|
23
23
|
* Create initial lane state
|
|
24
24
|
*/
|
|
25
|
-
export declare function createLaneState(laneName: string, config: RunnerConfig
|
|
25
|
+
export declare function createLaneState(laneName: string, config: RunnerConfig, tasksFile?: string, options?: {
|
|
26
|
+
pipelineBranch?: string;
|
|
27
|
+
worktreeDir?: string;
|
|
28
|
+
}): LaneState;
|
|
26
29
|
/**
|
|
27
30
|
* Update lane state
|
|
28
31
|
*/
|
package/dist/utils/state.js
CHANGED
|
@@ -50,6 +50,7 @@ exports.listLanesInRun = listLanesInRun;
|
|
|
50
50
|
exports.getLaneStateSummary = getLaneStateSummary;
|
|
51
51
|
const fs = __importStar(require("fs"));
|
|
52
52
|
const path = __importStar(require("path"));
|
|
53
|
+
const path_1 = require("./path");
|
|
53
54
|
/**
|
|
54
55
|
* Save state to JSON file
|
|
55
56
|
*/
|
|
@@ -109,18 +110,20 @@ function readLog(logPath) {
|
|
|
109
110
|
/**
|
|
110
111
|
* Create initial lane state
|
|
111
112
|
*/
|
|
112
|
-
function createLaneState(laneName, config) {
|
|
113
|
+
function createLaneState(laneName, config, tasksFile, options = {}) {
|
|
113
114
|
return {
|
|
114
115
|
label: laneName,
|
|
115
116
|
status: 'pending',
|
|
116
117
|
currentTaskIndex: 0,
|
|
117
118
|
totalTasks: config.tasks ? config.tasks.length : 0,
|
|
118
|
-
worktreeDir: null,
|
|
119
|
-
pipelineBranch: null,
|
|
119
|
+
worktreeDir: options.worktreeDir || null,
|
|
120
|
+
pipelineBranch: options.pipelineBranch || null,
|
|
120
121
|
startTime: Date.now(),
|
|
121
122
|
endTime: null,
|
|
122
123
|
error: null,
|
|
123
124
|
dependencyRequest: null,
|
|
125
|
+
tasksFile,
|
|
126
|
+
dependsOn: config.dependsOn || [],
|
|
124
127
|
};
|
|
125
128
|
}
|
|
126
129
|
/**
|
|
@@ -174,13 +177,13 @@ function getLatestRunDir(logsDir) {
|
|
|
174
177
|
return null;
|
|
175
178
|
}
|
|
176
179
|
const runs = fs.readdirSync(logsDir)
|
|
177
|
-
.filter(f => fs.statSync(
|
|
180
|
+
.filter(f => fs.statSync((0, path_1.safeJoin)(logsDir, f)).isDirectory())
|
|
178
181
|
.sort()
|
|
179
182
|
.reverse();
|
|
180
183
|
if (runs.length === 0) {
|
|
181
184
|
return null;
|
|
182
185
|
}
|
|
183
|
-
return
|
|
186
|
+
return (0, path_1.safeJoin)(logsDir, runs[0]);
|
|
184
187
|
}
|
|
185
188
|
/**
|
|
186
189
|
* List all lanes in a run directory
|
|
@@ -190,11 +193,11 @@ function listLanesInRun(runDir) {
|
|
|
190
193
|
return [];
|
|
191
194
|
}
|
|
192
195
|
return fs.readdirSync(runDir)
|
|
193
|
-
.filter(f => fs.statSync(
|
|
196
|
+
.filter(f => fs.statSync((0, path_1.safeJoin)(runDir, f)).isDirectory())
|
|
194
197
|
.map(laneName => ({
|
|
195
198
|
name: laneName,
|
|
196
|
-
dir:
|
|
197
|
-
statePath:
|
|
199
|
+
dir: (0, path_1.safeJoin)(runDir, laneName),
|
|
200
|
+
statePath: (0, path_1.safeJoin)(runDir, laneName, 'state.json'),
|
|
198
201
|
}));
|
|
199
202
|
}
|
|
200
203
|
/**
|
package/dist/utils/state.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/utils/state.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/utils/state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template loading utilities for CursorFlow
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Fetch remote template from URL
|
|
6
|
+
*/
|
|
7
|
+
export declare function fetchRemoteTemplate(url: string): Promise<any>;
|
|
8
|
+
/**
|
|
9
|
+
* Resolve template from various sources:
|
|
10
|
+
* 1. URL (starts with http:// or https://)
|
|
11
|
+
* 2. Built-in template (name without .json)
|
|
12
|
+
* 3. Local file path
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveTemplate(templatePath: string): Promise<any>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Template loading utilities for CursorFlow
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.fetchRemoteTemplate = fetchRemoteTemplate;
|
|
40
|
+
exports.resolveTemplate = resolveTemplate;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const https = __importStar(require("https"));
|
|
44
|
+
const http = __importStar(require("http"));
|
|
45
|
+
const logger = __importStar(require("./logger"));
|
|
46
|
+
const path_1 = require("./path");
|
|
47
|
+
const config_1 = require("./config");
|
|
48
|
+
/**
|
|
49
|
+
* Fetch remote template from URL
|
|
50
|
+
*/
|
|
51
|
+
async function fetchRemoteTemplate(url) {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const protocol = url.startsWith('https') ? https : http;
|
|
54
|
+
protocol.get(url, (res) => {
|
|
55
|
+
if (res.statusCode !== 200) {
|
|
56
|
+
reject(new Error(`Failed to fetch template from ${url}: Status ${res.statusCode}`));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
let data = '';
|
|
60
|
+
res.on('data', (chunk) => {
|
|
61
|
+
data += chunk;
|
|
62
|
+
});
|
|
63
|
+
res.on('end', () => {
|
|
64
|
+
try {
|
|
65
|
+
resolve(JSON.parse(data));
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
reject(new Error(`Failed to parse template JSON from ${url}: ${e}`));
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}).on('error', (err) => {
|
|
72
|
+
reject(new Error(`Network error while fetching template from ${url}: ${err.message}`));
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Resolve template from various sources:
|
|
78
|
+
* 1. URL (starts with http:// or https://)
|
|
79
|
+
* 2. Built-in template (name without .json)
|
|
80
|
+
* 3. Local file path
|
|
81
|
+
*/
|
|
82
|
+
async function resolveTemplate(templatePath) {
|
|
83
|
+
// 1. Remote URL
|
|
84
|
+
if (templatePath.startsWith('http://') || templatePath.startsWith('https://')) {
|
|
85
|
+
logger.info(`Fetching remote template: ${templatePath}`);
|
|
86
|
+
return fetchRemoteTemplate(templatePath);
|
|
87
|
+
}
|
|
88
|
+
// 2. Built-in template
|
|
89
|
+
// Search in templates/ directory of the project root
|
|
90
|
+
try {
|
|
91
|
+
const projectRoot = (0, config_1.findProjectRoot)();
|
|
92
|
+
const builtInPath = (0, path_1.safeJoin)(projectRoot, 'templates', templatePath.endsWith('.json') ? templatePath : `${templatePath}.json`);
|
|
93
|
+
if (fs.existsSync(builtInPath)) {
|
|
94
|
+
logger.info(`Using built-in template: ${templatePath}`);
|
|
95
|
+
return JSON.parse(fs.readFileSync(builtInPath, 'utf8'));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
// Ignore error if project root not found, try other methods
|
|
100
|
+
}
|
|
101
|
+
// Fallback for built-in templates relative to the module (for installed package)
|
|
102
|
+
const templatesDir = path.resolve(__dirname, '../../templates');
|
|
103
|
+
const templateFileName = templatePath.endsWith('.json') ? templatePath : `${templatePath}.json`;
|
|
104
|
+
const modulePath = (0, path_1.safeJoin)(templatesDir, templateFileName);
|
|
105
|
+
if (fs.existsSync(modulePath)) {
|
|
106
|
+
logger.info(`Using module template: ${templatePath}`);
|
|
107
|
+
return JSON.parse(fs.readFileSync(modulePath, 'utf8'));
|
|
108
|
+
}
|
|
109
|
+
// 3. Local file path
|
|
110
|
+
const localPath = (0, path_1.safeJoin)(process.cwd(), templatePath);
|
|
111
|
+
if (fs.existsSync(localPath)) {
|
|
112
|
+
logger.info(`Using local template: ${templatePath}`);
|
|
113
|
+
try {
|
|
114
|
+
return JSON.parse(fs.readFileSync(localPath, 'utf8'));
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
throw new Error(`Failed to parse local template ${templatePath}: ${e}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
throw new Error(`Template not found: ${templatePath}. It must be a URL, a built-in template name, or a local file path.`);
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/utils/template.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaH,kDA0BC;AAQD,0CAyCC;AAtFD,uCAAyB;AACzB,2CAA6B;AAC7B,6CAA+B;AAC/B,2CAA6B;AAC7B,iDAAmC;AACnC,iCAAkC;AAClC,qCAA2C;AAE3C;;GAEG;AACI,KAAK,UAAU,mBAAmB,CAAC,GAAW;IACnD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QAExD,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;gBAC3B,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,GAAG,YAAY,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;gBACpF,OAAO;YACT,CAAC;YAED,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;gBACvB,IAAI,IAAI,KAAK,CAAC;YAChB,CAAC,CAAC,CAAC;YAEH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjB,IAAI,CAAC;oBACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC5B,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,MAAM,CAAC,IAAI,KAAK,CAAC,sCAAsC,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACrB,MAAM,CAAC,IAAI,KAAK,CAAC,8CAA8C,GAAG,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACzF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,eAAe,CAAC,YAAoB;IACxD,gBAAgB;IAChB,IAAI,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9E,MAAM,CAAC,IAAI,CAAC,6BAA6B,YAAY,EAAE,CAAC,CAAC;QACzD,OAAO,mBAAmB,CAAC,YAAY,CAAC,CAAC;IAC3C,CAAC;IAED,uBAAuB;IACvB,qDAAqD;IACrD,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAA,wBAAe,GAAE,CAAC;QACtC,MAAM,WAAW,GAAG,IAAA,eAAQ,EAAC,WAAW,EAAE,WAAW,EAAE,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,OAAO,CAAC,CAAC;QAC/H,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/B,MAAM,CAAC,IAAI,CAAC,4BAA4B,YAAY,EAAE,CAAC,CAAC;YACxD,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,4DAA4D;IAC9D,CAAC;IAED,iFAAiF;IACjF,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;IAChE,MAAM,gBAAgB,GAAG,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,OAAO,CAAC;IAChG,MAAM,UAAU,GAAG,IAAA,eAAQ,EAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;IAC5D,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,0BAA0B,YAAY,EAAE,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,qBAAqB;IACrB,MAAM,SAAS,GAAG,IAAA,eAAQ,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,CAAC;IACxD,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,yBAAyB,YAAY,EAAE,CAAC,CAAC;QACrD,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,kCAAkC,YAAY,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,uBAAuB,YAAY,qEAAqE,CAAC,CAAC;AAC5H,CAAC"}
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export interface CursorFlowConfig {
|
|
|
16
16
|
lockfileReadOnly: boolean;
|
|
17
17
|
enableReview: boolean;
|
|
18
18
|
reviewModel: string;
|
|
19
|
+
reviewAllTasks?: boolean;
|
|
19
20
|
maxReviewIterations: number;
|
|
20
21
|
defaultLaneConfig: LaneConfig;
|
|
21
22
|
logLevel: string;
|
|
@@ -157,19 +158,26 @@ export interface Task {
|
|
|
157
158
|
model?: string;
|
|
158
159
|
/** Acceptance criteria for the AI reviewer to validate */
|
|
159
160
|
acceptanceCriteria?: string[];
|
|
161
|
+
/** Task-level dependencies (format: "lane:task") */
|
|
162
|
+
dependsOn?: string[];
|
|
163
|
+
/** Task execution timeout in milliseconds. Overrides lane-level timeout. */
|
|
164
|
+
timeout?: number;
|
|
160
165
|
}
|
|
161
166
|
export interface RunnerConfig {
|
|
162
167
|
tasks: Task[];
|
|
163
168
|
dependsOn?: string[];
|
|
164
169
|
pipelineBranch?: string;
|
|
170
|
+
worktreeDir?: string;
|
|
165
171
|
branchPrefix?: string;
|
|
166
172
|
worktreeRoot?: string;
|
|
167
173
|
baseBranch?: string;
|
|
168
174
|
model?: string;
|
|
169
175
|
dependencyPolicy: DependencyPolicy;
|
|
176
|
+
enableReview?: boolean;
|
|
170
177
|
/** Output format for cursor-agent (default: 'stream-json') */
|
|
171
178
|
agentOutputFormat?: 'stream-json' | 'json' | 'plain';
|
|
172
179
|
reviewModel?: string;
|
|
180
|
+
reviewAllTasks?: boolean;
|
|
173
181
|
maxReviewIterations?: number;
|
|
174
182
|
acceptanceCriteria?: string[];
|
|
175
183
|
/** Task execution timeout in milliseconds. Default: 600000 (10 minutes) */
|
|
@@ -224,6 +232,7 @@ export interface ReviewResult {
|
|
|
224
232
|
export interface TaskResult {
|
|
225
233
|
taskName: string;
|
|
226
234
|
taskBranch: string;
|
|
235
|
+
acceptanceCriteria?: string[];
|
|
227
236
|
[key: string]: any;
|
|
228
237
|
}
|
|
229
238
|
export interface LaneState {
|
|
@@ -241,6 +250,10 @@ export interface LaneState {
|
|
|
241
250
|
tasksFile?: string;
|
|
242
251
|
dependsOn?: string[];
|
|
243
252
|
pid?: number;
|
|
253
|
+
/** List of completed task names in this lane */
|
|
254
|
+
completedTasks?: string[];
|
|
255
|
+
/** Task-level dependencies currently being waited for (format: "lane:task") */
|
|
256
|
+
waitingFor?: string[];
|
|
244
257
|
}
|
|
245
258
|
export interface ConversationEntry {
|
|
246
259
|
timestamp: string;
|
package/dist/utils/webhook.js
CHANGED
|
@@ -84,6 +84,9 @@ async function sendWebhook(config, event) {
|
|
|
84
84
|
try {
|
|
85
85
|
const controller = new AbortController();
|
|
86
86
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
87
|
+
// SECURITY NOTE: Intentionally sending event data to configured webhook URLs.
|
|
88
|
+
// This is the expected behavior - users explicitly configure webhook endpoints
|
|
89
|
+
// to receive CursorFlow events. The data is JSON-serialized event metadata.
|
|
87
90
|
const response = await fetch(config.url, {
|
|
88
91
|
method: 'POST',
|
|
89
92
|
headers,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/utils/webhook.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/utils/webhook.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@litmers/cursorflow-orchestrator",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20",
|
|
4
4
|
"description": "Git worktree-based parallel AI agent orchestration system for Cursor",
|
|
5
5
|
"main": "dist/cli/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
"security:audit": "npm audit",
|
|
23
23
|
"security:audit:fix": "npm audit fix",
|
|
24
24
|
"security:setup": "scripts/setup-security.sh",
|
|
25
|
-
"
|
|
25
|
+
"verify": "scripts/verify-and-fix.sh",
|
|
26
|
+
"test:lifecycle": "tests/scripts/test-real-cursor-lifecycle.sh",
|
|
27
|
+
"test:comprehensive": "tests/scripts/test-comprehensive-lifecycle.sh",
|
|
26
28
|
"prepare": "husky"
|
|
27
29
|
},
|
|
28
30
|
"keywords": [
|
|
@@ -101,6 +101,9 @@ async function analyzeCodeWithAI(code, filename) {
|
|
|
101
101
|
const prompt = createSecurityPrompt(code, filename);
|
|
102
102
|
|
|
103
103
|
try {
|
|
104
|
+
// SECURITY NOTE: Intentionally sending code to OpenAI API for security analysis.
|
|
105
|
+
// This is the expected behavior - the script's purpose is AI-powered code review.
|
|
106
|
+
// Code is sent over HTTPS to OpenAI's secure API endpoint.
|
|
104
107
|
const response = await fetch('https://api.openai.com/v1/chat/completions', {
|
|
105
108
|
method: 'POST',
|
|
106
109
|
headers: {
|
|
@@ -45,7 +45,15 @@ echo -e "\n${BLUE}[3/4] Checking for hardcoded secrets...${NC}"
|
|
|
45
45
|
# .cursorignore나 .gitignore에 있는 파일은 제외
|
|
46
46
|
# .github, *.md, scripts/setup-security.sh 등은 제외
|
|
47
47
|
# 변수 선언이나 에러 메시지에 포함된 키워드는 제외하도록 필터 강화
|
|
48
|
-
|
|
48
|
+
RAW_SECRETS=$(git grep -Ei "api[_-]?key|secret|password|token|bearer|private[_-]?key" -- ":!package-lock.json" ":!*.md" ":!scripts/setup-security.sh" ":!scripts/ai-security-check.js" ":!.github/*" ":!scripts/local-security-gate.sh" | grep -v "process.env" | grep -v "example" | grep -v "\${{" | grep -vE "stderr\.includes|checkCursorApiKey|CURSOR_API_KEY|api key|API_KEY" || true)
|
|
49
|
+
|
|
50
|
+
# .secretsignore 파일이 있으면 해당 패턴을 제외
|
|
51
|
+
if [ -f .secretsignore ] && [ -n "$RAW_SECRETS" ]; then
|
|
52
|
+
# grep -v -f를 사용하여 .secretsignore에 있는 패턴이 포함된 줄을 제외
|
|
53
|
+
SECRETS_FOUND=$(echo "$RAW_SECRETS" | grep -v -f .secretsignore || true)
|
|
54
|
+
else
|
|
55
|
+
SECRETS_FOUND="$RAW_SECRETS"
|
|
56
|
+
fi
|
|
49
57
|
|
|
50
58
|
if [ -z "$SECRETS_FOUND" ]; then
|
|
51
59
|
echo -e "${GREEN}✅ No obvious secrets found in tracked files.${NC}"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# 작업 후 품질 검증 및 자동 수정 스크립트
|
|
4
|
+
# Husky pre-push 훅과 유사하지만, 자동 수정(fix)을 시도합니다.
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
echo "🛠️ Starting Post-Work Verification & Fix..."
|
|
9
|
+
|
|
10
|
+
# 1. 의존성 취약점 확인 및 수정
|
|
11
|
+
echo -e "\n📦 Checking dependencies (npm audit)..."
|
|
12
|
+
if ! npm audit --audit-level=high; then
|
|
13
|
+
echo "⚠️ High severity issues found. Attempting 'npm audit fix'..."
|
|
14
|
+
npm audit fix
|
|
15
|
+
# 다시 확인
|
|
16
|
+
if ! npm audit --audit-level=high; then
|
|
17
|
+
echo "❌ Vulnerabilities still exist after fix. Please check manually."
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
else
|
|
21
|
+
echo "✅ Dependencies are clean."
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# 2. 테스트 실행
|
|
25
|
+
echo -e "\n🧪 Running tests..."
|
|
26
|
+
npm test
|
|
27
|
+
|
|
28
|
+
# 3. 보안 게이트 실행 (새로 추가한 .secretsignore 적용됨)
|
|
29
|
+
echo -e "\n🔒 Running Local Security Gate..."
|
|
30
|
+
./scripts/local-security-gate.sh
|
|
31
|
+
|
|
32
|
+
# 4. 패키지 유효성 검사
|
|
33
|
+
echo -e "\n📦 Validating package..."
|
|
34
|
+
npm run validate
|
|
35
|
+
|
|
36
|
+
echo -e "\n✅ All checks passed! Ready to push."
|
|
37
|
+
|
package/src/cli/clean.ts
CHANGED
|
@@ -9,6 +9,7 @@ import * as path from 'path';
|
|
|
9
9
|
import * as logger from '../utils/logger';
|
|
10
10
|
import * as git from '../utils/git';
|
|
11
11
|
import { loadConfig, getLogsDir, getTasksDir } from '../utils/config';
|
|
12
|
+
import { safeJoin } from '../utils/path';
|
|
12
13
|
|
|
13
14
|
interface CleanOptions {
|
|
14
15
|
type?: string;
|
|
@@ -105,7 +106,7 @@ async function cleanWorktrees(config: any, repoRoot: string, options: CleanOptio
|
|
|
105
106
|
logger.info('\nChecking worktrees...');
|
|
106
107
|
const worktrees = git.listWorktrees(repoRoot);
|
|
107
108
|
|
|
108
|
-
const worktreeRoot =
|
|
109
|
+
const worktreeRoot = safeJoin(repoRoot, config.worktreeRoot || '_cursorflow/worktrees');
|
|
109
110
|
let toRemove = worktrees.filter(wt => {
|
|
110
111
|
// Skip main worktree
|
|
111
112
|
if (wt.path === repoRoot) return false;
|
|
@@ -178,7 +179,7 @@ async function cleanBranches(config: any, repoRoot: string, options: CleanOption
|
|
|
178
179
|
|
|
179
180
|
const branches = result.stdout
|
|
180
181
|
.split('\n')
|
|
181
|
-
.map(b => b.replace(
|
|
182
|
+
.map(b => b.replace(/\*/g, '').trim())
|
|
182
183
|
.filter(b => b && b !== 'main' && b !== 'master');
|
|
183
184
|
|
|
184
185
|
const prefix = config.branchPrefix || 'feature/';
|
|
@@ -226,9 +227,9 @@ async function cleanLogs(config: any, options: CleanOptions) {
|
|
|
226
227
|
const entries = fs.readdirSync(logsDir, { withFileTypes: true });
|
|
227
228
|
let items = entries.map(entry => ({
|
|
228
229
|
name: entry.name,
|
|
229
|
-
path:
|
|
230
|
+
path: safeJoin(logsDir, entry.name),
|
|
230
231
|
isDir: entry.isDirectory(),
|
|
231
|
-
mtime: getModTime(
|
|
232
|
+
mtime: getModTime(safeJoin(logsDir, entry.name))
|
|
232
233
|
}));
|
|
233
234
|
|
|
234
235
|
if (items.length <= 1) {
|
|
@@ -288,9 +289,9 @@ async function cleanTasks(config: any, options: CleanOptions) {
|
|
|
288
289
|
.filter(entry => entry.name !== 'example')
|
|
289
290
|
.map(entry => ({
|
|
290
291
|
name: entry.name,
|
|
291
|
-
path:
|
|
292
|
+
path: safeJoin(tasksDir, entry.name),
|
|
292
293
|
isDir: entry.isDirectory(),
|
|
293
|
-
mtime: getModTime(
|
|
294
|
+
mtime: getModTime(safeJoin(tasksDir, entry.name))
|
|
294
295
|
}));
|
|
295
296
|
|
|
296
297
|
if (items.length <= 1) {
|
|
@@ -325,7 +326,7 @@ async function cleanTasks(config: any, options: CleanOptions) {
|
|
|
325
326
|
const entries = fs.readdirSync(tasksDir, { withFileTypes: true });
|
|
326
327
|
for (const entry of entries) {
|
|
327
328
|
if (entry.name === 'example') continue;
|
|
328
|
-
const itemPath =
|
|
329
|
+
const itemPath = safeJoin(tasksDir, entry.name);
|
|
329
330
|
logger.info(` Removing task: ${entry.name}...`);
|
|
330
331
|
fs.rmSync(itemPath, { recursive: true, force: true });
|
|
331
332
|
}
|