@ulpi/cli 0.1.2 → 0.1.4

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.
@@ -0,0 +1,370 @@
1
+ import {
2
+ buildPrompt
3
+ } from "./chunk-B55DDP24.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
+ // Host path — used for Docker bind mounts
100
+ localVolumeBaseDir: external_exports.string().optional()
101
+ // Container-local path — used for fs ops (defaults to volumeBaseDir)
102
+ });
103
+ var SecurityConfigSchema = external_exports.object({
104
+ requireWriteAccess: external_exports.boolean().default(true),
105
+ allowedRepos: external_exports.array(external_exports.string()).optional(),
106
+ allowedAuthors: external_exports.array(external_exports.string()).optional(),
107
+ allowedOrgs: external_exports.array(external_exports.string()).optional(),
108
+ apiToken: external_exports.string(),
109
+ rateLimitWebhook: external_exports.number().int().positive().default(60),
110
+ rateLimitApi: external_exports.number().int().positive().default(200)
111
+ });
112
+ var OrchestratorConfigSchema = external_exports.object({
113
+ github: GitHubAuthConfigSchema,
114
+ jira: JiraConfigSchema.optional(),
115
+ docker: DockerConfigSchema,
116
+ jobs: external_exports.object({
117
+ maxConcurrent: external_exports.number().int().positive().default(3),
118
+ timeoutMinutes: external_exports.number().int().positive().default(30),
119
+ retainCompletedHours: external_exports.number().int().positive().default(72)
120
+ }),
121
+ security: SecurityConfigSchema,
122
+ port: external_exports.number().int().positive().default(3e3),
123
+ host: external_exports.string().default("0.0.0.0")
124
+ });
125
+ var ClaudeCredentialsSchema = external_exports.object({
126
+ blob: external_exports.string(),
127
+ // base64-encoded credentials directory contents
128
+ createdAt: external_exports.string().datetime(),
129
+ expiresAt: external_exports.string().datetime().optional()
130
+ });
131
+ var WorkerInputSchema = external_exports.object({
132
+ jobId: external_exports.string(),
133
+ config: JobConfigSchema,
134
+ claudeModel: external_exports.string().optional()
135
+ });
136
+ var WorkerOutputSchema = external_exports.object({
137
+ jobId: external_exports.string(),
138
+ result: JobResultSchema
139
+ });
140
+ var WorkerProgressSchema = external_exports.object({
141
+ phase: external_exports.string(),
142
+ message: external_exports.string(),
143
+ timestamp: external_exports.string().datetime()
144
+ });
145
+ var JiraTicketSchema = external_exports.object({
146
+ key: external_exports.string(),
147
+ // e.g. "ABC-123"
148
+ summary: external_exports.string(),
149
+ description: external_exports.string().optional(),
150
+ status: external_exports.string(),
151
+ assignee: external_exports.string().optional(),
152
+ priority: external_exports.string().optional(),
153
+ labels: external_exports.array(external_exports.string()),
154
+ acceptanceCriteria: external_exports.string().optional()
155
+ });
156
+ var JiraReferenceSchema = external_exports.object({
157
+ key: external_exports.string(),
158
+ url: external_exports.string().url()
159
+ });
160
+
161
+ // src/commands/ci.ts
162
+ async function runCi(args, projectDir) {
163
+ const subcommand = args[0];
164
+ switch (subcommand) {
165
+ case "run":
166
+ return runCiJob(args.slice(1));
167
+ default:
168
+ console.log(`
169
+ ${chalk.bold("ulpi ci")} \u2014 CI/PR worker mode
170
+
171
+ Usage: ulpi ci <command>
172
+
173
+ Commands:
174
+ run Execute a CI job (used inside worker containers)
175
+
176
+ Options:
177
+ --job-id <id> Job identifier
178
+ --config <json> Job config (JSON string or from ULPI_JOB_CONFIG env)
179
+ --output <path> Output file path for results
180
+ --model <model> Claude model to use (default: claude-sonnet-4-20250514)
181
+ `.trim());
182
+ }
183
+ }
184
+ async function runCiJob(args) {
185
+ let jobId = "";
186
+ let configJson = "";
187
+ let outputPath = "";
188
+ let model = "claude-sonnet-4-20250514";
189
+ for (let i = 0; i < args.length; i++) {
190
+ switch (args[i]) {
191
+ case "--job-id":
192
+ jobId = args[++i] ?? "";
193
+ break;
194
+ case "--config":
195
+ configJson = args[++i] ?? "";
196
+ break;
197
+ case "--output":
198
+ outputPath = args[++i] ?? "";
199
+ break;
200
+ case "--model":
201
+ model = args[++i] ?? model;
202
+ break;
203
+ }
204
+ }
205
+ jobId = jobId || process.env.ULPI_JOB_ID || "";
206
+ configJson = configJson || process.env.ULPI_JOB_CONFIG || "";
207
+ outputPath = outputPath || "/workspace/.ulpi-ci/output.json";
208
+ if (!jobId) {
209
+ console.error(chalk.red("Error: --job-id is required"));
210
+ process.exit(1);
211
+ }
212
+ if (!configJson) {
213
+ console.error(chalk.red("Error: --config is required (or set ULPI_JOB_CONFIG env)"));
214
+ process.exit(1);
215
+ }
216
+ let rawConfig;
217
+ try {
218
+ rawConfig = JSON.parse(configJson);
219
+ } catch {
220
+ console.error(chalk.red("Error: Invalid JSON in --config"));
221
+ process.exit(1);
222
+ }
223
+ const parseResult = JobConfigSchema.safeParse(rawConfig);
224
+ if (!parseResult.success) {
225
+ console.error(chalk.red("Error: Invalid job config:"));
226
+ console.error(parseResult.error.format());
227
+ process.exit(1);
228
+ }
229
+ const config = parseResult.data;
230
+ const startTime = Date.now();
231
+ console.log(chalk.blue(`[ulpi-ci] Job ${jobId} starting`));
232
+ console.log(chalk.blue(`[ulpi-ci] Instruction: ${config.instruction}`));
233
+ console.log(chalk.blue(`[ulpi-ci] Repo: ${config.repoFullName} PR#${config.prNumber}`));
234
+ const guardsPath = path.join(process.cwd(), ".ulpi", "guards.yml");
235
+ const hasGuards = fs.existsSync(guardsPath);
236
+ if (hasGuards) {
237
+ console.log(chalk.blue("[ulpi-ci] guards.yml found \u2014 rules will be enforced"));
238
+ }
239
+ const prompt = buildPrompt(config, {});
240
+ const claudePath = findClaudeBinary();
241
+ if (!claudePath) {
242
+ console.error(chalk.red("Error: claude binary not found in PATH"));
243
+ writeOutput(outputPath, {
244
+ jobId,
245
+ status: "failed",
246
+ filesChanged: [],
247
+ sessionEvents: 0,
248
+ durationMs: Date.now() - startTime,
249
+ error: "claude binary not found"
250
+ });
251
+ process.exit(1);
252
+ }
253
+ console.log(chalk.blue(`[ulpi-ci] Using claude at: ${claudePath}`));
254
+ const claudeArgs = [
255
+ "--print",
256
+ "--model",
257
+ model
258
+ ];
259
+ console.log(chalk.blue("[ulpi-ci] Spawning Claude Code..."));
260
+ const result = await spawnClaude(claudePath, claudeArgs, prompt, config.timeoutMinutes * 60 * 1e3);
261
+ const baseBranch = config.baseBranch;
262
+ let diff = "";
263
+ let filesChanged = [];
264
+ try {
265
+ diff = execFileSync("git", ["diff", `origin/${baseBranch}...HEAD`], {
266
+ cwd: process.cwd(),
267
+ encoding: "utf-8",
268
+ timeout: 3e4,
269
+ maxBuffer: 10 * 1024 * 1024
270
+ });
271
+ } catch {
272
+ }
273
+ try {
274
+ const output = execFileSync("git", ["diff", "--name-only", `origin/${baseBranch}...HEAD`], {
275
+ cwd: process.cwd(),
276
+ encoding: "utf-8",
277
+ timeout: 3e4
278
+ });
279
+ filesChanged = output.trim().split("\n").filter(Boolean);
280
+ } catch {
281
+ }
282
+ const jobResult = {
283
+ jobId,
284
+ status: result.exitCode === 0 ? "completed" : "failed",
285
+ exitCode: result.exitCode,
286
+ diff: diff || void 0,
287
+ summary: result.output.slice(0, 5e3) || void 0,
288
+ filesChanged,
289
+ sessionEvents: 0,
290
+ durationMs: Date.now() - startTime,
291
+ error: result.exitCode !== 0 ? `Claude exited with code ${result.exitCode}` : void 0
292
+ };
293
+ writeOutput(outputPath, jobResult);
294
+ console.log(chalk.blue(`[ulpi-ci] Job ${jobId} ${jobResult.status} in ${formatDuration(jobResult.durationMs)}`));
295
+ console.log(chalk.blue(`[ulpi-ci] Files changed: ${filesChanged.length}`));
296
+ process.exit(result.exitCode === 0 ? 0 : 1);
297
+ }
298
+ function findClaudeBinary() {
299
+ try {
300
+ const result = execFileSync("which", ["claude"], { encoding: "utf-8", timeout: 5e3 });
301
+ return result.trim();
302
+ } catch {
303
+ }
304
+ const commonPaths = ["/usr/local/bin/claude", "/usr/bin/claude"];
305
+ for (const p of commonPaths) {
306
+ if (fs.existsSync(p)) return p;
307
+ }
308
+ return null;
309
+ }
310
+ function spawnClaude(claudePath, args, prompt, timeoutMs) {
311
+ return new Promise((resolve) => {
312
+ const proc = spawn(claudePath, args, {
313
+ cwd: process.cwd(),
314
+ env: process.env,
315
+ stdio: ["pipe", "pipe", "pipe"]
316
+ });
317
+ let stdout = "";
318
+ let stderr = "";
319
+ proc.stdout.on("data", (data) => {
320
+ const text = data.toString();
321
+ stdout += text;
322
+ process.stdout.write(text);
323
+ });
324
+ proc.stderr.on("data", (data) => {
325
+ const text = data.toString();
326
+ stderr += text;
327
+ process.stderr.write(text);
328
+ });
329
+ proc.stdin.write(prompt);
330
+ proc.stdin.end();
331
+ const timer = setTimeout(() => {
332
+ console.log(chalk.yellow("[ulpi-ci] Timeout reached, killing Claude process..."));
333
+ proc.kill("SIGTERM");
334
+ setTimeout(() => {
335
+ if (!proc.killed) proc.kill("SIGKILL");
336
+ }, 1e4);
337
+ }, timeoutMs);
338
+ proc.on("close", (code) => {
339
+ clearTimeout(timer);
340
+ resolve({ exitCode: code ?? 1, output: stdout });
341
+ });
342
+ const onSigterm = () => {
343
+ console.log(chalk.yellow("[ulpi-ci] Received SIGTERM, stopping Claude..."));
344
+ proc.kill("SIGTERM");
345
+ };
346
+ process.on("SIGTERM", onSigterm);
347
+ proc.on("close", () => {
348
+ process.removeListener("SIGTERM", onSigterm);
349
+ });
350
+ });
351
+ }
352
+ function writeOutput(outputPath, result) {
353
+ try {
354
+ const dir = path.dirname(outputPath);
355
+ fs.mkdirSync(dir, { recursive: true });
356
+ fs.writeFileSync(outputPath, JSON.stringify({ jobId: result.jobId, result }, null, 2), "utf-8");
357
+ } catch (err) {
358
+ console.error(chalk.red(`Error writing output: ${err instanceof Error ? err.message : String(err)}`));
359
+ }
360
+ }
361
+ function formatDuration(ms) {
362
+ const seconds = Math.floor(ms / 1e3);
363
+ if (seconds < 60) return `${seconds}s`;
364
+ const minutes = Math.floor(seconds / 60);
365
+ const remainingSeconds = seconds % 60;
366
+ return `${minutes}m ${remainingSeconds}s`;
367
+ }
368
+ export {
369
+ runCi
370
+ };
@@ -69,7 +69,7 @@ async function initSubcommand(projectDir) {
69
69
  console.log(chalk.bold("\nCodeMap \u2014 Index Project\n"));
70
70
  const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
71
71
  const branch = getCurrentBranch(projectDir);
72
- const { runInitPipeline, loadCodemapConfig } = await import("./dist-MFFX7TZW.js");
72
+ const { runInitPipeline, loadCodemapConfig } = await import("./dist-CB5D5LMO.js");
73
73
  const config = loadCodemapConfig(projectDir);
74
74
  if (config.embedding.provider === "openai") {
75
75
  const { resolveApiKey } = await import("./dist-RKOGLK7R.js");
@@ -131,7 +131,7 @@ async function searchSubcommand(args, projectDir) {
131
131
  const noDocs = args.includes("--no-docs");
132
132
  const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
133
133
  const branch = getCurrentBranch(projectDir);
134
- const { searchCode, getCodemapStatus } = await import("./dist-MFFX7TZW.js");
134
+ const { searchCode, getCodemapStatus } = await import("./dist-CB5D5LMO.js");
135
135
  const status = getCodemapStatus(projectDir, branch);
136
136
  if (!status.initialized) {
137
137
  console.log(chalk.red("Error: CodeMap index not initialized."));
@@ -177,7 +177,7 @@ CodeMap Search \u2014 "${query}"
177
177
  async function statusSubcommand(projectDir) {
178
178
  const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
179
179
  const branch = getCurrentBranch(projectDir);
180
- const { getCodemapStatus } = await import("./dist-MFFX7TZW.js");
180
+ const { getCodemapStatus } = await import("./dist-CB5D5LMO.js");
181
181
  const status = getCodemapStatus(projectDir, branch);
182
182
  console.log(chalk.bold("\nCodeMap Status\n"));
183
183
  if (!status.initialized) {
@@ -208,7 +208,7 @@ async function reindexSubcommand(projectDir) {
208
208
  console.log(chalk.bold("\nCodeMap \u2014 Re-index Project\n"));
209
209
  const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
210
210
  const branch = getCurrentBranch(projectDir);
211
- const { getCodemapStatus } = await import("./dist-MFFX7TZW.js");
211
+ const { getCodemapStatus } = await import("./dist-CB5D5LMO.js");
212
212
  const status = getCodemapStatus(projectDir, branch);
213
213
  if (!status.initialized) {
214
214
  console.log(chalk.yellow("Index not initialized. Running init instead..."));
@@ -219,7 +219,7 @@ async function depgraphSubcommand(projectDir) {
219
219
  console.log(chalk.bold("\nCodeMap \u2014 Rebuild Dependency Graph\n"));
220
220
  const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
221
221
  const branch = getCurrentBranch(projectDir);
222
- const { getCodemapStatus, rebuildDepgraph } = await import("./dist-MFFX7TZW.js");
222
+ const { getCodemapStatus, rebuildDepgraph } = await import("./dist-CB5D5LMO.js");
223
223
  const status = getCodemapStatus(projectDir, branch);
224
224
  if (!status.initialized) {
225
225
  console.log(chalk.red("Error: CodeMap index not initialized. Run 'ulpi codemap init' first."));
@@ -245,7 +245,7 @@ async function depgraphSubcommand(projectDir) {
245
245
  }
246
246
  }
247
247
  async function configSubcommand(args, projectDir) {
248
- const { loadCodemapConfig, saveCodemapConfig } = await import("./dist-MFFX7TZW.js");
248
+ const { loadCodemapConfig, saveCodemapConfig } = await import("./dist-CB5D5LMO.js");
249
249
  const config = loadCodemapConfig(projectDir);
250
250
  if (args.length === 0) {
251
251
  console.log(chalk.bold("\nCodeMap Configuration\n"));
@@ -318,7 +318,7 @@ async function watchSubcommand(projectDir) {
318
318
  console.log(chalk.bold("\nCodeMap \u2014 Watch Mode\n"));
319
319
  const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
320
320
  const branch = getCurrentBranch(projectDir);
321
- const { getCodemapStatus, CodemapWatcher } = await import("./dist-MFFX7TZW.js");
321
+ const { getCodemapStatus, CodemapWatcher } = await import("./dist-CB5D5LMO.js");
322
322
  const status = getCodemapStatus(projectDir, branch);
323
323
  if (!status.initialized) {
324
324
  console.log(chalk.yellow("Index not initialized. Running init first..."));
@@ -349,7 +349,7 @@ async function exportSubcommand(projectDir) {
349
349
  console.log(chalk.bold("\nCodeMap \u2014 Export Index\n"));
350
350
  const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
351
351
  const branch = getCurrentBranch(projectDir);
352
- const { exportIndex } = await import("./dist-MFFX7TZW.js");
352
+ const { exportIndex } = await import("./dist-CB5D5LMO.js");
353
353
  try {
354
354
  const result = await exportIndex(projectDir, branch);
355
355
  console.log(chalk.green("\u2713 Export complete"));
@@ -368,7 +368,7 @@ async function importSubcommand(projectDir) {
368
368
  console.log(chalk.bold("\nCodeMap \u2014 Import Index\n"));
369
369
  const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
370
370
  const branch = getCurrentBranch(projectDir);
371
- const { importIndex } = await import("./dist-MFFX7TZW.js");
371
+ const { importIndex } = await import("./dist-CB5D5LMO.js");
372
372
  try {
373
373
  const result = await importIndex(projectDir, branch);
374
374
  if (!result.success) {
@@ -392,7 +392,7 @@ async function importSubcommand(projectDir) {
392
392
  async function serveSubcommand(projectDir) {
393
393
  const { getCurrentBranch } = await import("./dist-RKOGLK7R.js");
394
394
  const branch = getCurrentBranch(projectDir);
395
- const { getCodemapStatus } = await import("./dist-MFFX7TZW.js");
395
+ const { getCodemapStatus } = await import("./dist-CB5D5LMO.js");
396
396
  const status = getCodemapStatus(projectDir, branch);
397
397
  if (!status.initialized) {
398
398
  console.error(chalk.red("Error: CodeMap index not initialized. Run 'ulpi codemap init' first."));
@@ -401,11 +401,11 @@ async function serveSubcommand(projectDir) {
401
401
  console.error(chalk.dim("[codemap-mcp] Starting MCP server..."));
402
402
  console.error(chalk.dim(`[codemap-mcp] Project: ${projectDir}`));
403
403
  console.error(chalk.dim(`[codemap-mcp] Index: ${status.totalFiles} files, ${status.totalChunks} chunks`));
404
- const { startMcpServer } = await import("./dist-QYFQYSXP.js");
404
+ const { startMcpServer } = await import("./dist-UKMCJBB2.js");
405
405
  await startMcpServer({ projectDir, branch });
406
406
  }
407
407
  async function evalSubcommand(args, projectDir) {
408
- const { runEvalHarness } = await import("./dist-MFFX7TZW.js");
408
+ const { runEvalHarness } = await import("./dist-CB5D5LMO.js");
409
409
  const path = await import("path");
410
410
  const datasetIdx = args.indexOf("--dataset");
411
411
  let datasetPath;
@@ -448,7 +448,7 @@ async function evalSubcommand(args, projectDir) {
448
448
  }
449
449
  async function migrateIndexSubcommand(projectDir) {
450
450
  console.log(chalk.bold("\nCodeMap \u2014 Migrate Legacy Index\n"));
451
- const { migrateFromLegacy } = await import("./dist-MFFX7TZW.js");
451
+ const { migrateFromLegacy } = await import("./dist-CB5D5LMO.js");
452
452
  try {
453
453
  const result = await migrateFromLegacy(projectDir);
454
454
  if (!result.migrated) {
@@ -61,8 +61,8 @@ import {
61
61
  searchCode,
62
62
  searchSymbols,
63
63
  tokenize
64
- } from "./chunk-VGZLMUNO.js";
65
- import "./chunk-NNUWU6CV.js";
64
+ } from "./chunk-5J6NLQUN.js";
65
+ import "./chunk-JGBXM5NC.js";
66
66
  import "./chunk-YM2HV4IA.js";
67
67
  import "./chunk-74WVVWJ4.js";
68
68
  import "./chunk-KIKPIH6N.js";
@@ -15,9 +15,9 @@ import {
15
15
  removeEntry,
16
16
  searchMemory,
17
17
  updateEntry
18
- } from "./chunk-FNPD3V2X.js";
19
- import "./chunk-VGZLMUNO.js";
20
- import "./chunk-NNUWU6CV.js";
18
+ } from "./chunk-PDR55ZNW.js";
19
+ import "./chunk-5J6NLQUN.js";
20
+ import "./chunk-JGBXM5NC.js";
21
21
  import "./chunk-YM2HV4IA.js";
22
22
  import "./chunk-74WVVWJ4.js";
23
23
  import "./chunk-KIKPIH6N.js";
@@ -10,6 +10,7 @@ import {
10
10
  classifySession,
11
11
  classifySinglePrompt,
12
12
  classifyWindow,
13
+ clearClassifyBatchProgress,
13
14
  deduplicateMemories,
14
15
  exportMemories,
15
16
  filterSignificantEvents,
@@ -34,6 +35,7 @@ import {
34
35
  parseClassifierOutput,
35
36
  readCapturedEvents,
36
37
  readCapturedTranscript,
38
+ readClassifyBatchProgress,
37
39
  redactContent,
38
40
  reindexMemories,
39
41
  releaseMemoryLock,
@@ -45,10 +47,11 @@ import {
45
47
  searchMemory,
46
48
  toClassificationEvent,
47
49
  updateEntry,
50
+ writeClassifyBatchProgress,
48
51
  writeMemoryStats
49
- } from "./chunk-FNPD3V2X.js";
50
- import "./chunk-VGZLMUNO.js";
51
- import "./chunk-NNUWU6CV.js";
52
+ } from "./chunk-PDR55ZNW.js";
53
+ import "./chunk-5J6NLQUN.js";
54
+ import "./chunk-JGBXM5NC.js";
52
55
  import "./chunk-YM2HV4IA.js";
53
56
  import "./chunk-74WVVWJ4.js";
54
57
  import "./chunk-KIKPIH6N.js";
@@ -69,6 +72,7 @@ export {
69
72
  classifySession,
70
73
  classifySinglePrompt,
71
74
  classifyWindow,
75
+ clearClassifyBatchProgress,
72
76
  deduplicateMemories,
73
77
  exportMemories,
74
78
  filterSignificantEvents,
@@ -93,6 +97,7 @@ export {
93
97
  parseClassifierOutput,
94
98
  readCapturedEvents,
95
99
  readCapturedTranscript,
100
+ readClassifyBatchProgress,
96
101
  redactContent,
97
102
  reindexMemories,
98
103
  releaseMemoryLock,
@@ -104,5 +109,6 @@ export {
104
109
  searchMemory,
105
110
  toClassificationEvent,
106
111
  updateEntry,
112
+ writeClassifyBatchProgress,
107
113
  writeMemoryStats
108
114
  };
@@ -20,6 +20,7 @@ import {
20
20
  initHistoryBranch,
21
21
  installGitHooks,
22
22
  listBranchDir,
23
+ listBranchOnlyCommits,
23
24
  listCommitsBetween,
24
25
  listRecentCommits,
25
26
  loadActiveGuards,
@@ -39,7 +40,7 @@ import {
39
40
  withWorktree,
40
41
  writeAndStage,
41
42
  writeHistoryEntry
42
- } from "./chunk-NNUWU6CV.js";
43
+ } from "./chunk-JGBXM5NC.js";
43
44
  import "./chunk-YM2HV4IA.js";
44
45
  import "./chunk-7LXY5UVC.js";
45
46
  import "./chunk-4VNS5WPM.js";
@@ -65,6 +66,7 @@ export {
65
66
  initHistoryBranch,
66
67
  installGitHooks,
67
68
  listBranchDir,
69
+ listBranchOnlyCommits,
68
70
  listCommitsBetween,
69
71
  listRecentCommits,
70
72
  loadActiveGuards,
@@ -12,8 +12,8 @@ import {
12
12
  runInitPipeline,
13
13
  searchCode,
14
14
  searchSymbols
15
- } from "./chunk-VGZLMUNO.js";
16
- import "./chunk-NNUWU6CV.js";
15
+ } from "./chunk-5J6NLQUN.js";
16
+ import "./chunk-JGBXM5NC.js";
17
17
  import "./chunk-YM2HV4IA.js";
18
18
  import "./chunk-74WVVWJ4.js";
19
19
  import "./chunk-KIKPIH6N.js";
@@ -10,6 +10,7 @@ import {
10
10
  getCurrentHead,
11
11
  historyBranchExists,
12
12
  initHistoryBranch,
13
+ listBranchOnlyCommits,
13
14
  listRecentCommits,
14
15
  loadActiveGuards,
15
16
  readBranchMeta,
@@ -18,7 +19,7 @@ import {
18
19
  readTimeline,
19
20
  updateEntryEnrichment,
20
21
  writeHistoryEntry
21
- } from "./chunk-NNUWU6CV.js";
22
+ } from "./chunk-JGBXM5NC.js";
22
23
  import "./chunk-YM2HV4IA.js";
23
24
  import {
24
25
  DEFAULT_AI_MODEL,
@@ -415,7 +416,7 @@ async function initSubcommand(projectDir) {
415
416
  }
416
417
  const projectName = path2.basename(projectDir);
417
418
  try {
418
- initHistoryBranch(projectDir, projectName, "0.1.2");
419
+ initHistoryBranch(projectDir, projectName, "0.1.4");
419
420
  } catch (err) {
420
421
  const message = err instanceof Error ? err.message : String(err);
421
422
  console.log(chalk.red(`Error: ${message}`));
@@ -423,7 +424,7 @@ async function initSubcommand(projectDir) {
423
424
  }
424
425
  if (collectReviewPlans) {
425
426
  try {
426
- const { withWorktree, writeAndStage, commitInWorktree } = await import("./dist-RJGCUS3L.js");
427
+ const { withWorktree, writeAndStage, commitInWorktree } = await import("./dist-QAU3LGJN.js");
427
428
  const meta = readBranchMeta(projectDir);
428
429
  if (meta) {
429
430
  meta.config.collectReviewPlans = true;
@@ -446,7 +447,7 @@ async function initSubcommand(projectDir) {
446
447
  );
447
448
  if (installHooksAnswer.trim().toLowerCase() !== "n") {
448
449
  try {
449
- const { installGitHooks } = await import("./dist-RJGCUS3L.js");
450
+ const { installGitHooks } = await import("./dist-QAU3LGJN.js");
450
451
  const { getBinaryPath } = await import("./dist-RKOGLK7R.js");
451
452
  const binaryPath = getBinaryPath();
452
453
  const result = installGitHooks(projectDir, binaryPath);
@@ -531,10 +532,12 @@ async function backfillSubcommand(args, projectDir) {
531
532
  if (args[0] && !args[0].startsWith("--") && /^\d+$/.test(args[0])) {
532
533
  limit = parseInt(args[0], 10);
533
534
  }
535
+ const branchOnly = args.includes("--branch-only");
536
+ const label = branchOnly ? "branch-only commits" : `last ${limit} commits`;
534
537
  console.log(chalk.bold(`
535
- ULPI History \u2014 Backfill (last ${limit} commits)
538
+ ULPI History \u2014 Backfill (${label})
536
539
  `));
537
- const commits = listRecentCommits(projectDir, limit);
540
+ const commits = branchOnly ? listBranchOnlyCommits(projectDir, limit) : listRecentCommits(projectDir, limit);
538
541
  if (commits.length === 0) {
539
542
  console.log(chalk.yellow("No commits found."));
540
543
  return;