@ulpi/cli 0.1.1 → 0.1.3
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/dist/auth-KQCJ43U2.js +118 -0
- package/dist/{chunk-Q4HIY43N.js → chunk-2VYFVYJL.js} +67 -24
- package/dist/{chunk-DBMUNBNB.js → chunk-5J6NLQUN.js} +149 -19
- package/dist/{chunk-4KRVDKGB.js → chunk-F7OXF7Z3.js} +1 -1
- package/dist/chunk-G6SVZ4Q5.js +122 -0
- package/dist/{chunk-NNUWU6CV.js → chunk-JGBXM5NC.js} +42 -0
- package/dist/{chunk-6JCMYYBT.js → chunk-PDR55ZNW.js} +247 -112
- package/dist/{chunk-247GVVKK.js → chunk-ZLYRPD7I.js} +18 -16
- package/dist/ci-QM57ZCBW.js +367 -0
- package/dist/{codemap-RRJIDBQ5.js → codemap-RKSD4MIE.js} +49 -17
- package/dist/{dist-LZKZFPVX.js → dist-CB5D5LMO.js} +6 -3
- package/dist/{dist-7LHZ65GC.js → dist-CS2VKNYS.js} +5 -4
- package/dist/{dist-R5F4MX3I.js → dist-GJYT2OQV.js} +11 -4
- package/dist/{dist-RJGCUS3L.js → dist-QAU3LGJN.js} +3 -1
- package/dist/{dist-W7K4WPAF.js → dist-UKMCJBB2.js} +42 -14
- package/dist/{dist-R5ZJ4LX5.js → dist-YA2BWZB2.js} +1 -1
- package/dist/{history-Q2LDADFW.js → history-NFNA4HE5.js} +13 -7
- package/dist/index.js +50 -21
- package/dist/{init-AY5C2ZAS.js → init-6CH4HV5T.js} +2 -2
- package/dist/{memory-J3G24QHS.js → memory-Y6OZTXJ2.js} +231 -22
- package/dist/{server-MOYPE4SM-N7SE2AN7.js → server-USLHY6GH-AEOJC5ST.js} +2 -2
- package/dist/skills/ulpi-generate-guardian/SKILL.md +246 -7
- package/dist/skills/ulpi-generate-guardian/references/framework-rules.md +161 -4
- package/dist/skills/ulpi-generate-guardian/references/language-rules.md +13 -18
- package/dist/{ui-L7UAWXDY.js → ui-OWXZ3YSR.js} +3 -3
- package/dist/ui.html +112 -112
- package/dist/{update-DJ227LL3.js → update-WUITQX4Z.js} +1 -1
- package/dist/{version-checker-M37KI7DY.js → version-checker-SMAYSN7Y.js} +1 -1
- package/package.json +31 -28
- package/LICENSE +0 -21
|
@@ -42,7 +42,7 @@ var TAG_QUERIES = {
|
|
|
42
42
|
(comment)* @doc
|
|
43
43
|
.
|
|
44
44
|
[
|
|
45
|
-
(
|
|
45
|
+
(function_expression
|
|
46
46
|
name: (identifier) @name.definition.function)
|
|
47
47
|
(function_declaration
|
|
48
48
|
name: (identifier) @name.definition.function)
|
|
@@ -59,7 +59,7 @@ var TAG_QUERIES = {
|
|
|
59
59
|
(lexical_declaration
|
|
60
60
|
(variable_declarator
|
|
61
61
|
name: (identifier) @name.definition.function
|
|
62
|
-
value: [(arrow_function) (
|
|
62
|
+
value: [(arrow_function) (function_expression)]) @definition.function)
|
|
63
63
|
)
|
|
64
64
|
|
|
65
65
|
(
|
|
@@ -68,7 +68,7 @@ var TAG_QUERIES = {
|
|
|
68
68
|
(variable_declaration
|
|
69
69
|
(variable_declarator
|
|
70
70
|
name: (identifier) @name.definition.function
|
|
71
|
-
value: [(arrow_function) (
|
|
71
|
+
value: [(arrow_function) (function_expression)]) @definition.function)
|
|
72
72
|
)
|
|
73
73
|
|
|
74
74
|
(assignment_expression
|
|
@@ -77,12 +77,12 @@ var TAG_QUERIES = {
|
|
|
77
77
|
(member_expression
|
|
78
78
|
property: (property_identifier) @name.definition.function)
|
|
79
79
|
]
|
|
80
|
-
right: [(arrow_function) (
|
|
80
|
+
right: [(arrow_function) (function_expression)]
|
|
81
81
|
) @definition.function
|
|
82
82
|
|
|
83
83
|
(pair
|
|
84
84
|
key: (property_identifier) @name.definition.function
|
|
85
|
-
value: [(arrow_function) (
|
|
85
|
+
value: [(arrow_function) (function_expression)]) @definition.function
|
|
86
86
|
|
|
87
87
|
(
|
|
88
88
|
(call_expression
|
|
@@ -127,7 +127,7 @@ var TAG_QUERIES = {
|
|
|
127
127
|
(comment)* @doc
|
|
128
128
|
.
|
|
129
129
|
[
|
|
130
|
-
(
|
|
130
|
+
(function_expression
|
|
131
131
|
name: (identifier) @name.definition.function)
|
|
132
132
|
(function_declaration
|
|
133
133
|
name: (identifier) @name.definition.function)
|
|
@@ -144,7 +144,7 @@ var TAG_QUERIES = {
|
|
|
144
144
|
(lexical_declaration
|
|
145
145
|
(variable_declarator
|
|
146
146
|
name: (identifier) @name.definition.function
|
|
147
|
-
value: [(arrow_function) (
|
|
147
|
+
value: [(arrow_function) (function_expression)]) @definition.function)
|
|
148
148
|
)
|
|
149
149
|
|
|
150
150
|
(
|
|
@@ -153,7 +153,7 @@ var TAG_QUERIES = {
|
|
|
153
153
|
(variable_declaration
|
|
154
154
|
(variable_declarator
|
|
155
155
|
name: (identifier) @name.definition.function
|
|
156
|
-
value: [(arrow_function) (
|
|
156
|
+
value: [(arrow_function) (function_expression)]) @definition.function)
|
|
157
157
|
)
|
|
158
158
|
|
|
159
159
|
(assignment_expression
|
|
@@ -162,12 +162,12 @@ var TAG_QUERIES = {
|
|
|
162
162
|
(member_expression
|
|
163
163
|
property: (property_identifier) @name.definition.function)
|
|
164
164
|
]
|
|
165
|
-
right: [(arrow_function) (
|
|
165
|
+
right: [(arrow_function) (function_expression)]
|
|
166
166
|
) @definition.function
|
|
167
167
|
|
|
168
168
|
(pair
|
|
169
169
|
key: (property_identifier) @name.definition.function
|
|
170
|
-
value: [(arrow_function) (
|
|
170
|
+
value: [(arrow_function) (function_expression)]) @definition.function
|
|
171
171
|
|
|
172
172
|
(
|
|
173
173
|
(call_expression
|
|
@@ -256,7 +256,7 @@ var TAG_QUERIES = {
|
|
|
256
256
|
(comment)* @doc
|
|
257
257
|
.
|
|
258
258
|
[
|
|
259
|
-
(
|
|
259
|
+
(function_expression
|
|
260
260
|
name: (identifier) @name.definition.function)
|
|
261
261
|
(function_declaration
|
|
262
262
|
name: (identifier) @name.definition.function)
|
|
@@ -273,7 +273,7 @@ var TAG_QUERIES = {
|
|
|
273
273
|
(lexical_declaration
|
|
274
274
|
(variable_declarator
|
|
275
275
|
name: (identifier) @name.definition.function
|
|
276
|
-
value: [(arrow_function) (
|
|
276
|
+
value: [(arrow_function) (function_expression)]) @definition.function)
|
|
277
277
|
)
|
|
278
278
|
|
|
279
279
|
(
|
|
@@ -282,7 +282,7 @@ var TAG_QUERIES = {
|
|
|
282
282
|
(variable_declaration
|
|
283
283
|
(variable_declarator
|
|
284
284
|
name: (identifier) @name.definition.function
|
|
285
|
-
value: [(arrow_function) (
|
|
285
|
+
value: [(arrow_function) (function_expression)]) @definition.function)
|
|
286
286
|
)
|
|
287
287
|
|
|
288
288
|
(assignment_expression
|
|
@@ -291,12 +291,12 @@ var TAG_QUERIES = {
|
|
|
291
291
|
(member_expression
|
|
292
292
|
property: (property_identifier) @name.definition.function)
|
|
293
293
|
]
|
|
294
|
-
right: [(arrow_function) (
|
|
294
|
+
right: [(arrow_function) (function_expression)]
|
|
295
295
|
) @definition.function
|
|
296
296
|
|
|
297
297
|
(pair
|
|
298
298
|
key: (property_identifier) @name.definition.function
|
|
299
|
-
value: [(arrow_function) (
|
|
299
|
+
value: [(arrow_function) (function_expression)]) @definition.function
|
|
300
300
|
|
|
301
301
|
(
|
|
302
302
|
(call_expression
|
|
@@ -1693,7 +1693,9 @@ function extractTagsFromTree(createQuery, rootNode, filePath, lang) {
|
|
|
1693
1693
|
let query;
|
|
1694
1694
|
try {
|
|
1695
1695
|
query = createQuery(querySource);
|
|
1696
|
-
} catch {
|
|
1696
|
+
} catch (err) {
|
|
1697
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1698
|
+
console.error(`[depgraph] Query compilation failed for ${lang} (${filePath}): ${msg}`);
|
|
1697
1699
|
return [];
|
|
1698
1700
|
}
|
|
1699
1701
|
try {
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildPrompt
|
|
3
|
+
} from "./chunk-G6SVZ4Q5.js";
|
|
4
|
+
import {
|
|
5
|
+
external_exports
|
|
6
|
+
} from "./chunk-KIKPIH6N.js";
|
|
7
|
+
import "./chunk-4VNS5WPM.js";
|
|
8
|
+
|
|
9
|
+
// src/commands/ci.ts
|
|
10
|
+
import * as fs from "fs";
|
|
11
|
+
import * as path from "path";
|
|
12
|
+
import { spawn, execFileSync } from "child_process";
|
|
13
|
+
import chalk from "chalk";
|
|
14
|
+
|
|
15
|
+
// ../../packages/contracts-ci/dist/index.js
|
|
16
|
+
var CiCommandTypeSchema = external_exports.enum(["run", "cancel", "fork", "status"]);
|
|
17
|
+
var CiCommandSchema = external_exports.object({
|
|
18
|
+
type: CiCommandTypeSchema,
|
|
19
|
+
instruction: external_exports.string().optional(),
|
|
20
|
+
prNumber: external_exports.number().int().positive(),
|
|
21
|
+
repoFullName: external_exports.string(),
|
|
22
|
+
// "org/repo"
|
|
23
|
+
commentId: external_exports.number().int().positive(),
|
|
24
|
+
commentAuthor: external_exports.string(),
|
|
25
|
+
forkName: external_exports.string().optional()
|
|
26
|
+
});
|
|
27
|
+
var JobStatusSchema = external_exports.enum([
|
|
28
|
+
"queued",
|
|
29
|
+
"provisioning",
|
|
30
|
+
"running",
|
|
31
|
+
"completing",
|
|
32
|
+
"completed",
|
|
33
|
+
"failed",
|
|
34
|
+
"cancelled",
|
|
35
|
+
"timed_out"
|
|
36
|
+
]);
|
|
37
|
+
var JobConfigSchema = external_exports.object({
|
|
38
|
+
repoUrl: external_exports.string().url(),
|
|
39
|
+
ref: external_exports.string(),
|
|
40
|
+
baseBranch: external_exports.string(),
|
|
41
|
+
prNumber: external_exports.number().int().positive(),
|
|
42
|
+
repoFullName: external_exports.string(),
|
|
43
|
+
instruction: external_exports.string(),
|
|
44
|
+
jiraContext: external_exports.string().optional(),
|
|
45
|
+
timeoutMinutes: external_exports.number().int().positive().default(30),
|
|
46
|
+
envVars: external_exports.record(external_exports.string()).optional()
|
|
47
|
+
});
|
|
48
|
+
var JobResultSchema = external_exports.object({
|
|
49
|
+
jobId: external_exports.string(),
|
|
50
|
+
status: JobStatusSchema,
|
|
51
|
+
exitCode: external_exports.number().int().optional(),
|
|
52
|
+
diff: external_exports.string().optional(),
|
|
53
|
+
testOutput: external_exports.string().optional(),
|
|
54
|
+
summary: external_exports.string().optional(),
|
|
55
|
+
filesChanged: external_exports.array(external_exports.string()),
|
|
56
|
+
sessionEvents: external_exports.number().int().default(0),
|
|
57
|
+
durationMs: external_exports.number().int(),
|
|
58
|
+
error: external_exports.string().optional()
|
|
59
|
+
});
|
|
60
|
+
var JobSchema = external_exports.object({
|
|
61
|
+
id: external_exports.string(),
|
|
62
|
+
config: JobConfigSchema,
|
|
63
|
+
status: JobStatusSchema,
|
|
64
|
+
result: JobResultSchema.optional(),
|
|
65
|
+
containerId: external_exports.string().optional(),
|
|
66
|
+
workspaceDir: external_exports.string().optional(),
|
|
67
|
+
parentJobId: external_exports.string().optional(),
|
|
68
|
+
createdAt: external_exports.string().datetime(),
|
|
69
|
+
startedAt: external_exports.string().datetime().optional(),
|
|
70
|
+
completedAt: external_exports.string().datetime().optional(),
|
|
71
|
+
cancelledBy: external_exports.string().optional(),
|
|
72
|
+
commentId: external_exports.number().int().positive(),
|
|
73
|
+
commentAuthor: external_exports.string()
|
|
74
|
+
});
|
|
75
|
+
var GitHubAppAuthSchema = external_exports.object({
|
|
76
|
+
appId: external_exports.string(),
|
|
77
|
+
privateKeyPath: external_exports.string(),
|
|
78
|
+
webhookSecret: external_exports.string(),
|
|
79
|
+
installationId: external_exports.number().int().positive().optional()
|
|
80
|
+
});
|
|
81
|
+
var GitHubAuthConfigSchema = external_exports.discriminatedUnion("mode", [
|
|
82
|
+
external_exports.object({ mode: external_exports.literal("app"), config: GitHubAppAuthSchema }),
|
|
83
|
+
external_exports.object({ mode: external_exports.literal("pat"), token: external_exports.string() })
|
|
84
|
+
]);
|
|
85
|
+
var JiraConfigSchema = external_exports.object({
|
|
86
|
+
baseUrl: external_exports.string().url(),
|
|
87
|
+
email: external_exports.string().email(),
|
|
88
|
+
apiToken: external_exports.string(),
|
|
89
|
+
defaultProject: external_exports.string().optional()
|
|
90
|
+
});
|
|
91
|
+
var DockerConfigSchema = external_exports.object({
|
|
92
|
+
image: external_exports.string(),
|
|
93
|
+
network: external_exports.string().optional(),
|
|
94
|
+
memoryLimit: external_exports.string().optional(),
|
|
95
|
+
// e.g. "4g"
|
|
96
|
+
cpuLimit: external_exports.number().positive().optional(),
|
|
97
|
+
// e.g. 2.0
|
|
98
|
+
volumeBaseDir: external_exports.string()
|
|
99
|
+
});
|
|
100
|
+
var SecurityConfigSchema = external_exports.object({
|
|
101
|
+
requireWriteAccess: external_exports.boolean().default(true),
|
|
102
|
+
allowedRepos: external_exports.array(external_exports.string()).optional(),
|
|
103
|
+
allowedAuthors: external_exports.array(external_exports.string()).optional(),
|
|
104
|
+
allowedOrgs: external_exports.array(external_exports.string()).optional(),
|
|
105
|
+
apiToken: external_exports.string(),
|
|
106
|
+
rateLimitWebhook: external_exports.number().int().positive().default(60),
|
|
107
|
+
rateLimitApi: external_exports.number().int().positive().default(200)
|
|
108
|
+
});
|
|
109
|
+
var OrchestratorConfigSchema = external_exports.object({
|
|
110
|
+
github: GitHubAuthConfigSchema,
|
|
111
|
+
jira: JiraConfigSchema.optional(),
|
|
112
|
+
docker: DockerConfigSchema,
|
|
113
|
+
jobs: external_exports.object({
|
|
114
|
+
maxConcurrent: external_exports.number().int().positive().default(3),
|
|
115
|
+
timeoutMinutes: external_exports.number().int().positive().default(30),
|
|
116
|
+
retainCompletedHours: external_exports.number().int().positive().default(72)
|
|
117
|
+
}),
|
|
118
|
+
security: SecurityConfigSchema,
|
|
119
|
+
port: external_exports.number().int().positive().default(3e3),
|
|
120
|
+
host: external_exports.string().default("0.0.0.0")
|
|
121
|
+
});
|
|
122
|
+
var ClaudeCredentialsSchema = external_exports.object({
|
|
123
|
+
blob: external_exports.string(),
|
|
124
|
+
// base64-encoded credentials directory contents
|
|
125
|
+
createdAt: external_exports.string().datetime(),
|
|
126
|
+
expiresAt: external_exports.string().datetime().optional()
|
|
127
|
+
});
|
|
128
|
+
var WorkerInputSchema = external_exports.object({
|
|
129
|
+
jobId: external_exports.string(),
|
|
130
|
+
config: JobConfigSchema,
|
|
131
|
+
claudeModel: external_exports.string().optional()
|
|
132
|
+
});
|
|
133
|
+
var WorkerOutputSchema = external_exports.object({
|
|
134
|
+
jobId: external_exports.string(),
|
|
135
|
+
result: JobResultSchema
|
|
136
|
+
});
|
|
137
|
+
var WorkerProgressSchema = external_exports.object({
|
|
138
|
+
phase: external_exports.string(),
|
|
139
|
+
message: external_exports.string(),
|
|
140
|
+
timestamp: external_exports.string().datetime()
|
|
141
|
+
});
|
|
142
|
+
var JiraTicketSchema = external_exports.object({
|
|
143
|
+
key: external_exports.string(),
|
|
144
|
+
// e.g. "ABC-123"
|
|
145
|
+
summary: external_exports.string(),
|
|
146
|
+
description: external_exports.string().optional(),
|
|
147
|
+
status: external_exports.string(),
|
|
148
|
+
assignee: external_exports.string().optional(),
|
|
149
|
+
priority: external_exports.string().optional(),
|
|
150
|
+
labels: external_exports.array(external_exports.string()),
|
|
151
|
+
acceptanceCriteria: external_exports.string().optional()
|
|
152
|
+
});
|
|
153
|
+
var JiraReferenceSchema = external_exports.object({
|
|
154
|
+
key: external_exports.string(),
|
|
155
|
+
url: external_exports.string().url()
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// src/commands/ci.ts
|
|
159
|
+
async function runCi(args, projectDir) {
|
|
160
|
+
const subcommand = args[0];
|
|
161
|
+
switch (subcommand) {
|
|
162
|
+
case "run":
|
|
163
|
+
return runCiJob(args.slice(1));
|
|
164
|
+
default:
|
|
165
|
+
console.log(`
|
|
166
|
+
${chalk.bold("ulpi ci")} \u2014 CI/PR worker mode
|
|
167
|
+
|
|
168
|
+
Usage: ulpi ci <command>
|
|
169
|
+
|
|
170
|
+
Commands:
|
|
171
|
+
run Execute a CI job (used inside worker containers)
|
|
172
|
+
|
|
173
|
+
Options:
|
|
174
|
+
--job-id <id> Job identifier
|
|
175
|
+
--config <json> Job config (JSON string or from ULPI_JOB_CONFIG env)
|
|
176
|
+
--output <path> Output file path for results
|
|
177
|
+
--model <model> Claude model to use (default: claude-sonnet-4-20250514)
|
|
178
|
+
`.trim());
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async function runCiJob(args) {
|
|
182
|
+
let jobId = "";
|
|
183
|
+
let configJson = "";
|
|
184
|
+
let outputPath = "";
|
|
185
|
+
let model = "claude-sonnet-4-20250514";
|
|
186
|
+
for (let i = 0; i < args.length; i++) {
|
|
187
|
+
switch (args[i]) {
|
|
188
|
+
case "--job-id":
|
|
189
|
+
jobId = args[++i] ?? "";
|
|
190
|
+
break;
|
|
191
|
+
case "--config":
|
|
192
|
+
configJson = args[++i] ?? "";
|
|
193
|
+
break;
|
|
194
|
+
case "--output":
|
|
195
|
+
outputPath = args[++i] ?? "";
|
|
196
|
+
break;
|
|
197
|
+
case "--model":
|
|
198
|
+
model = args[++i] ?? model;
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
jobId = jobId || process.env.ULPI_JOB_ID || "";
|
|
203
|
+
configJson = configJson || process.env.ULPI_JOB_CONFIG || "";
|
|
204
|
+
outputPath = outputPath || "/workspace/.ulpi-ci/output.json";
|
|
205
|
+
if (!jobId) {
|
|
206
|
+
console.error(chalk.red("Error: --job-id is required"));
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
if (!configJson) {
|
|
210
|
+
console.error(chalk.red("Error: --config is required (or set ULPI_JOB_CONFIG env)"));
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|
|
213
|
+
let rawConfig;
|
|
214
|
+
try {
|
|
215
|
+
rawConfig = JSON.parse(configJson);
|
|
216
|
+
} catch {
|
|
217
|
+
console.error(chalk.red("Error: Invalid JSON in --config"));
|
|
218
|
+
process.exit(1);
|
|
219
|
+
}
|
|
220
|
+
const parseResult = JobConfigSchema.safeParse(rawConfig);
|
|
221
|
+
if (!parseResult.success) {
|
|
222
|
+
console.error(chalk.red("Error: Invalid job config:"));
|
|
223
|
+
console.error(parseResult.error.format());
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
const config = parseResult.data;
|
|
227
|
+
const startTime = Date.now();
|
|
228
|
+
console.log(chalk.blue(`[ulpi-ci] Job ${jobId} starting`));
|
|
229
|
+
console.log(chalk.blue(`[ulpi-ci] Instruction: ${config.instruction}`));
|
|
230
|
+
console.log(chalk.blue(`[ulpi-ci] Repo: ${config.repoFullName} PR#${config.prNumber}`));
|
|
231
|
+
const guardsPath = path.join(process.cwd(), ".ulpi", "guards.yml");
|
|
232
|
+
const hasGuards = fs.existsSync(guardsPath);
|
|
233
|
+
if (hasGuards) {
|
|
234
|
+
console.log(chalk.blue("[ulpi-ci] guards.yml found \u2014 rules will be enforced"));
|
|
235
|
+
}
|
|
236
|
+
const prompt = buildPrompt(config, {});
|
|
237
|
+
const claudePath = findClaudeBinary();
|
|
238
|
+
if (!claudePath) {
|
|
239
|
+
console.error(chalk.red("Error: claude binary not found in PATH"));
|
|
240
|
+
writeOutput(outputPath, {
|
|
241
|
+
jobId,
|
|
242
|
+
status: "failed",
|
|
243
|
+
filesChanged: [],
|
|
244
|
+
sessionEvents: 0,
|
|
245
|
+
durationMs: Date.now() - startTime,
|
|
246
|
+
error: "claude binary not found"
|
|
247
|
+
});
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|
|
250
|
+
console.log(chalk.blue(`[ulpi-ci] Using claude at: ${claudePath}`));
|
|
251
|
+
const claudeArgs = [
|
|
252
|
+
"--print",
|
|
253
|
+
"--model",
|
|
254
|
+
model
|
|
255
|
+
];
|
|
256
|
+
console.log(chalk.blue("[ulpi-ci] Spawning Claude Code..."));
|
|
257
|
+
const result = await spawnClaude(claudePath, claudeArgs, prompt, config.timeoutMinutes * 60 * 1e3);
|
|
258
|
+
const baseBranch = config.baseBranch;
|
|
259
|
+
let diff = "";
|
|
260
|
+
let filesChanged = [];
|
|
261
|
+
try {
|
|
262
|
+
diff = execFileSync("git", ["diff", `origin/${baseBranch}...HEAD`], {
|
|
263
|
+
cwd: process.cwd(),
|
|
264
|
+
encoding: "utf-8",
|
|
265
|
+
timeout: 3e4,
|
|
266
|
+
maxBuffer: 10 * 1024 * 1024
|
|
267
|
+
});
|
|
268
|
+
} catch {
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
const output = execFileSync("git", ["diff", "--name-only", `origin/${baseBranch}...HEAD`], {
|
|
272
|
+
cwd: process.cwd(),
|
|
273
|
+
encoding: "utf-8",
|
|
274
|
+
timeout: 3e4
|
|
275
|
+
});
|
|
276
|
+
filesChanged = output.trim().split("\n").filter(Boolean);
|
|
277
|
+
} catch {
|
|
278
|
+
}
|
|
279
|
+
const jobResult = {
|
|
280
|
+
jobId,
|
|
281
|
+
status: result.exitCode === 0 ? "completed" : "failed",
|
|
282
|
+
exitCode: result.exitCode,
|
|
283
|
+
diff: diff || void 0,
|
|
284
|
+
summary: result.output.slice(0, 5e3) || void 0,
|
|
285
|
+
filesChanged,
|
|
286
|
+
sessionEvents: 0,
|
|
287
|
+
durationMs: Date.now() - startTime,
|
|
288
|
+
error: result.exitCode !== 0 ? `Claude exited with code ${result.exitCode}` : void 0
|
|
289
|
+
};
|
|
290
|
+
writeOutput(outputPath, jobResult);
|
|
291
|
+
console.log(chalk.blue(`[ulpi-ci] Job ${jobId} ${jobResult.status} in ${formatDuration(jobResult.durationMs)}`));
|
|
292
|
+
console.log(chalk.blue(`[ulpi-ci] Files changed: ${filesChanged.length}`));
|
|
293
|
+
process.exit(result.exitCode === 0 ? 0 : 1);
|
|
294
|
+
}
|
|
295
|
+
function findClaudeBinary() {
|
|
296
|
+
try {
|
|
297
|
+
const result = execFileSync("which", ["claude"], { encoding: "utf-8", timeout: 5e3 });
|
|
298
|
+
return result.trim();
|
|
299
|
+
} catch {
|
|
300
|
+
}
|
|
301
|
+
const commonPaths = ["/usr/local/bin/claude", "/usr/bin/claude"];
|
|
302
|
+
for (const p of commonPaths) {
|
|
303
|
+
if (fs.existsSync(p)) return p;
|
|
304
|
+
}
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
function spawnClaude(claudePath, args, prompt, timeoutMs) {
|
|
308
|
+
return new Promise((resolve) => {
|
|
309
|
+
const proc = spawn(claudePath, args, {
|
|
310
|
+
cwd: process.cwd(),
|
|
311
|
+
env: process.env,
|
|
312
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
313
|
+
});
|
|
314
|
+
let stdout = "";
|
|
315
|
+
let stderr = "";
|
|
316
|
+
proc.stdout.on("data", (data) => {
|
|
317
|
+
const text = data.toString();
|
|
318
|
+
stdout += text;
|
|
319
|
+
process.stdout.write(text);
|
|
320
|
+
});
|
|
321
|
+
proc.stderr.on("data", (data) => {
|
|
322
|
+
const text = data.toString();
|
|
323
|
+
stderr += text;
|
|
324
|
+
process.stderr.write(text);
|
|
325
|
+
});
|
|
326
|
+
proc.stdin.write(prompt);
|
|
327
|
+
proc.stdin.end();
|
|
328
|
+
const timer = setTimeout(() => {
|
|
329
|
+
console.log(chalk.yellow("[ulpi-ci] Timeout reached, killing Claude process..."));
|
|
330
|
+
proc.kill("SIGTERM");
|
|
331
|
+
setTimeout(() => {
|
|
332
|
+
if (!proc.killed) proc.kill("SIGKILL");
|
|
333
|
+
}, 1e4);
|
|
334
|
+
}, timeoutMs);
|
|
335
|
+
proc.on("close", (code) => {
|
|
336
|
+
clearTimeout(timer);
|
|
337
|
+
resolve({ exitCode: code ?? 1, output: stdout });
|
|
338
|
+
});
|
|
339
|
+
const onSigterm = () => {
|
|
340
|
+
console.log(chalk.yellow("[ulpi-ci] Received SIGTERM, stopping Claude..."));
|
|
341
|
+
proc.kill("SIGTERM");
|
|
342
|
+
};
|
|
343
|
+
process.on("SIGTERM", onSigterm);
|
|
344
|
+
proc.on("close", () => {
|
|
345
|
+
process.removeListener("SIGTERM", onSigterm);
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
function writeOutput(outputPath, result) {
|
|
350
|
+
try {
|
|
351
|
+
const dir = path.dirname(outputPath);
|
|
352
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
353
|
+
fs.writeFileSync(outputPath, JSON.stringify({ jobId: result.jobId, result }, null, 2), "utf-8");
|
|
354
|
+
} catch (err) {
|
|
355
|
+
console.error(chalk.red(`Error writing output: ${err instanceof Error ? err.message : String(err)}`));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
function formatDuration(ms) {
|
|
359
|
+
const seconds = Math.floor(ms / 1e3);
|
|
360
|
+
if (seconds < 60) return `${seconds}s`;
|
|
361
|
+
const minutes = Math.floor(seconds / 60);
|
|
362
|
+
const remainingSeconds = seconds % 60;
|
|
363
|
+
return `${minutes}m ${remainingSeconds}s`;
|
|
364
|
+
}
|
|
365
|
+
export {
|
|
366
|
+
runCi
|
|
367
|
+
};
|
|
@@ -38,6 +38,8 @@ async function runCodemap(args, projectDir) {
|
|
|
38
38
|
return await cyclesSubcommand(projectDir);
|
|
39
39
|
case "coupling":
|
|
40
40
|
return await couplingSubcommand(args.slice(1), projectDir);
|
|
41
|
+
case "depgraph":
|
|
42
|
+
return await depgraphSubcommand(projectDir);
|
|
41
43
|
default:
|
|
42
44
|
console.log(`
|
|
43
45
|
Usage: ulpi codemap <subcommand>
|
|
@@ -59,6 +61,7 @@ Subcommands:
|
|
|
59
61
|
rank [--limit N] Show top-ranked files by PageRank
|
|
60
62
|
cycles Detect circular dependencies
|
|
61
63
|
coupling [path] Show coupling metrics for files
|
|
64
|
+
depgraph Rebuild dependency graph (without re-embedding)
|
|
62
65
|
`.trim());
|
|
63
66
|
}
|
|
64
67
|
}
|
|
@@ -66,7 +69,7 @@ async function initSubcommand(projectDir) {
|
|
|
66
69
|
console.log(chalk.bold("\nCodeMap \u2014 Index Project\n"));
|
|
67
70
|
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
68
71
|
const branch = getCurrentBranch(projectDir);
|
|
69
|
-
const { runInitPipeline, loadCodemapConfig } = await import("./dist-
|
|
72
|
+
const { runInitPipeline, loadCodemapConfig } = await import("./dist-CB5D5LMO.js");
|
|
70
73
|
const config = loadCodemapConfig(projectDir);
|
|
71
74
|
if (config.embedding.provider === "openai") {
|
|
72
75
|
const { resolveApiKey } = await import("./dist-RKOGLK7R.js");
|
|
@@ -128,7 +131,7 @@ async function searchSubcommand(args, projectDir) {
|
|
|
128
131
|
const noDocs = args.includes("--no-docs");
|
|
129
132
|
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
130
133
|
const branch = getCurrentBranch(projectDir);
|
|
131
|
-
const { searchCode, getCodemapStatus } = await import("./dist-
|
|
134
|
+
const { searchCode, getCodemapStatus } = await import("./dist-CB5D5LMO.js");
|
|
132
135
|
const status = getCodemapStatus(projectDir, branch);
|
|
133
136
|
if (!status.initialized) {
|
|
134
137
|
console.log(chalk.red("Error: CodeMap index not initialized."));
|
|
@@ -174,7 +177,7 @@ CodeMap Search \u2014 "${query}"
|
|
|
174
177
|
async function statusSubcommand(projectDir) {
|
|
175
178
|
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
176
179
|
const branch = getCurrentBranch(projectDir);
|
|
177
|
-
const { getCodemapStatus } = await import("./dist-
|
|
180
|
+
const { getCodemapStatus } = await import("./dist-CB5D5LMO.js");
|
|
178
181
|
const status = getCodemapStatus(projectDir, branch);
|
|
179
182
|
console.log(chalk.bold("\nCodeMap Status\n"));
|
|
180
183
|
if (!status.initialized) {
|
|
@@ -205,15 +208,44 @@ async function reindexSubcommand(projectDir) {
|
|
|
205
208
|
console.log(chalk.bold("\nCodeMap \u2014 Re-index Project\n"));
|
|
206
209
|
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
207
210
|
const branch = getCurrentBranch(projectDir);
|
|
208
|
-
const { getCodemapStatus } = await import("./dist-
|
|
211
|
+
const { getCodemapStatus } = await import("./dist-CB5D5LMO.js");
|
|
209
212
|
const status = getCodemapStatus(projectDir, branch);
|
|
210
213
|
if (!status.initialized) {
|
|
211
214
|
console.log(chalk.yellow("Index not initialized. Running init instead..."));
|
|
212
215
|
}
|
|
213
216
|
return initSubcommand(projectDir);
|
|
214
217
|
}
|
|
218
|
+
async function depgraphSubcommand(projectDir) {
|
|
219
|
+
console.log(chalk.bold("\nCodeMap \u2014 Rebuild Dependency Graph\n"));
|
|
220
|
+
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
221
|
+
const branch = getCurrentBranch(projectDir);
|
|
222
|
+
const { getCodemapStatus, rebuildDepgraph } = await import("./dist-CB5D5LMO.js");
|
|
223
|
+
const status = getCodemapStatus(projectDir, branch);
|
|
224
|
+
if (!status.initialized) {
|
|
225
|
+
console.log(chalk.red("Error: CodeMap index not initialized. Run 'ulpi codemap init' first."));
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
const ora = (await import("ora")).default;
|
|
229
|
+
const spinner = ora("Rebuilding dependency graph...").start();
|
|
230
|
+
try {
|
|
231
|
+
const result = await rebuildDepgraph(projectDir, (progress) => {
|
|
232
|
+
spinner.text = progress.message;
|
|
233
|
+
}, branch);
|
|
234
|
+
spinner.succeed(`Dependency graph rebuilt in ${(result.durationMs / 1e3).toFixed(1)}s`);
|
|
235
|
+
console.log(` Files tagged: ${result.taggedFiles}/${result.totalFiles}`);
|
|
236
|
+
console.log(` Nodes: ${result.nodeCount}`);
|
|
237
|
+
console.log(` Edges: ${result.edgeCount}`);
|
|
238
|
+
console.log(` Definitions: ${result.definitionCount}`);
|
|
239
|
+
console.log(` References: ${result.referenceCount}`);
|
|
240
|
+
console.log(` Cycles: ${result.cycleCount}`);
|
|
241
|
+
} catch (err) {
|
|
242
|
+
spinner.fail("Dependency graph rebuild failed");
|
|
243
|
+
console.log(chalk.red(err instanceof Error ? err.message : String(err)));
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
215
247
|
async function configSubcommand(args, projectDir) {
|
|
216
|
-
const { loadCodemapConfig, saveCodemapConfig } = await import("./dist-
|
|
248
|
+
const { loadCodemapConfig, saveCodemapConfig } = await import("./dist-CB5D5LMO.js");
|
|
217
249
|
const config = loadCodemapConfig(projectDir);
|
|
218
250
|
if (args.length === 0) {
|
|
219
251
|
console.log(chalk.bold("\nCodeMap Configuration\n"));
|
|
@@ -286,7 +318,7 @@ async function watchSubcommand(projectDir) {
|
|
|
286
318
|
console.log(chalk.bold("\nCodeMap \u2014 Watch Mode\n"));
|
|
287
319
|
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
288
320
|
const branch = getCurrentBranch(projectDir);
|
|
289
|
-
const { getCodemapStatus, CodemapWatcher } = await import("./dist-
|
|
321
|
+
const { getCodemapStatus, CodemapWatcher } = await import("./dist-CB5D5LMO.js");
|
|
290
322
|
const status = getCodemapStatus(projectDir, branch);
|
|
291
323
|
if (!status.initialized) {
|
|
292
324
|
console.log(chalk.yellow("Index not initialized. Running init first..."));
|
|
@@ -317,7 +349,7 @@ async function exportSubcommand(projectDir) {
|
|
|
317
349
|
console.log(chalk.bold("\nCodeMap \u2014 Export Index\n"));
|
|
318
350
|
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
319
351
|
const branch = getCurrentBranch(projectDir);
|
|
320
|
-
const { exportIndex } = await import("./dist-
|
|
352
|
+
const { exportIndex } = await import("./dist-CB5D5LMO.js");
|
|
321
353
|
try {
|
|
322
354
|
const result = await exportIndex(projectDir, branch);
|
|
323
355
|
console.log(chalk.green("\u2713 Export complete"));
|
|
@@ -336,7 +368,7 @@ async function importSubcommand(projectDir) {
|
|
|
336
368
|
console.log(chalk.bold("\nCodeMap \u2014 Import Index\n"));
|
|
337
369
|
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
338
370
|
const branch = getCurrentBranch(projectDir);
|
|
339
|
-
const { importIndex } = await import("./dist-
|
|
371
|
+
const { importIndex } = await import("./dist-CB5D5LMO.js");
|
|
340
372
|
try {
|
|
341
373
|
const result = await importIndex(projectDir, branch);
|
|
342
374
|
if (!result.success) {
|
|
@@ -360,7 +392,7 @@ async function importSubcommand(projectDir) {
|
|
|
360
392
|
async function serveSubcommand(projectDir) {
|
|
361
393
|
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
362
394
|
const branch = getCurrentBranch(projectDir);
|
|
363
|
-
const { getCodemapStatus } = await import("./dist-
|
|
395
|
+
const { getCodemapStatus } = await import("./dist-CB5D5LMO.js");
|
|
364
396
|
const status = getCodemapStatus(projectDir, branch);
|
|
365
397
|
if (!status.initialized) {
|
|
366
398
|
console.error(chalk.red("Error: CodeMap index not initialized. Run 'ulpi codemap init' first."));
|
|
@@ -369,11 +401,11 @@ async function serveSubcommand(projectDir) {
|
|
|
369
401
|
console.error(chalk.dim("[codemap-mcp] Starting MCP server..."));
|
|
370
402
|
console.error(chalk.dim(`[codemap-mcp] Project: ${projectDir}`));
|
|
371
403
|
console.error(chalk.dim(`[codemap-mcp] Index: ${status.totalFiles} files, ${status.totalChunks} chunks`));
|
|
372
|
-
const { startMcpServer } = await import("./dist-
|
|
404
|
+
const { startMcpServer } = await import("./dist-UKMCJBB2.js");
|
|
373
405
|
await startMcpServer({ projectDir, branch });
|
|
374
406
|
}
|
|
375
407
|
async function evalSubcommand(args, projectDir) {
|
|
376
|
-
const { runEvalHarness } = await import("./dist-
|
|
408
|
+
const { runEvalHarness } = await import("./dist-CB5D5LMO.js");
|
|
377
409
|
const path = await import("path");
|
|
378
410
|
const datasetIdx = args.indexOf("--dataset");
|
|
379
411
|
let datasetPath;
|
|
@@ -416,7 +448,7 @@ async function evalSubcommand(args, projectDir) {
|
|
|
416
448
|
}
|
|
417
449
|
async function migrateIndexSubcommand(projectDir) {
|
|
418
450
|
console.log(chalk.bold("\nCodeMap \u2014 Migrate Legacy Index\n"));
|
|
419
|
-
const { migrateFromLegacy } = await import("./dist-
|
|
451
|
+
const { migrateFromLegacy } = await import("./dist-CB5D5LMO.js");
|
|
420
452
|
try {
|
|
421
453
|
const result = await migrateFromLegacy(projectDir);
|
|
422
454
|
if (!result.migrated) {
|
|
@@ -444,7 +476,7 @@ async function depsSubcommand(args, projectDir) {
|
|
|
444
476
|
const maxDepth = depthIdx >= 0 ? parseInt(args[depthIdx + 1], 10) || 5 : 5;
|
|
445
477
|
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
446
478
|
const branch = getCurrentBranch(projectDir);
|
|
447
|
-
const { loadGraph, getOutgoingEdges, getTransitiveDeps } = await import("./dist-
|
|
479
|
+
const { loadGraph, getOutgoingEdges, getTransitiveDeps } = await import("./dist-YA2BWZB2.js");
|
|
448
480
|
const graph = loadGraph(projectDir, branch);
|
|
449
481
|
if (!graph) {
|
|
450
482
|
console.log(chalk.yellow("No dependency graph found. Run 'ulpi codemap init' first."));
|
|
@@ -495,7 +527,7 @@ async function dependentsSubcommand(args, projectDir) {
|
|
|
495
527
|
const maxDepth = depthIdx >= 0 ? parseInt(args[depthIdx + 1], 10) || 5 : 5;
|
|
496
528
|
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
497
529
|
const branch = getCurrentBranch(projectDir);
|
|
498
|
-
const { loadGraph, getIncomingEdges, getTransitiveRdeps } = await import("./dist-
|
|
530
|
+
const { loadGraph, getIncomingEdges, getTransitiveRdeps } = await import("./dist-YA2BWZB2.js");
|
|
499
531
|
const graph = loadGraph(projectDir, branch);
|
|
500
532
|
if (!graph) {
|
|
501
533
|
console.log(chalk.yellow("No dependency graph found. Run 'ulpi codemap init' first."));
|
|
@@ -540,7 +572,7 @@ async function rankSubcommand(args, projectDir) {
|
|
|
540
572
|
const limit = limitIdx >= 0 ? parseInt(args[limitIdx + 1], 10) || 20 : 20;
|
|
541
573
|
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
542
574
|
const branch = getCurrentBranch(projectDir);
|
|
543
|
-
const { loadPageRank, loadGraph } = await import("./dist-
|
|
575
|
+
const { loadPageRank, loadGraph } = await import("./dist-YA2BWZB2.js");
|
|
544
576
|
const result = loadPageRank(projectDir, branch);
|
|
545
577
|
if (!result) {
|
|
546
578
|
console.log(chalk.yellow("No PageRank data found. Run 'ulpi codemap init' first."));
|
|
@@ -572,7 +604,7 @@ Top ${sorted.length} files by PageRank
|
|
|
572
604
|
async function cyclesSubcommand(projectDir) {
|
|
573
605
|
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
574
606
|
const branch = getCurrentBranch(projectDir);
|
|
575
|
-
const { loadMetrics, loadGraph, detectCycles } = await import("./dist-
|
|
607
|
+
const { loadMetrics, loadGraph, detectCycles } = await import("./dist-YA2BWZB2.js");
|
|
576
608
|
let cycles;
|
|
577
609
|
const metrics = loadMetrics(projectDir, branch);
|
|
578
610
|
if (metrics) {
|
|
@@ -605,7 +637,7 @@ async function couplingSubcommand(args, projectDir) {
|
|
|
605
637
|
const modulePath = args.filter((a) => !a.startsWith("--"))[0] || "";
|
|
606
638
|
const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
|
|
607
639
|
const branch = getCurrentBranch(projectDir);
|
|
608
|
-
const { loadGraph, computeCoupling } = await import("./dist-
|
|
640
|
+
const { loadGraph, computeCoupling } = await import("./dist-YA2BWZB2.js");
|
|
609
641
|
const graph = loadGraph(projectDir, branch);
|
|
610
642
|
if (!graph) {
|
|
611
643
|
console.log(chalk.yellow("No dependency graph found. Run 'ulpi codemap init' first."));
|