@open-code-review/cli 1.5.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +245 -210
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -16428,14 +16428,14 @@ __export(db_exports, {
16428
16428
  saveDatabase: () => saveDatabase,
16429
16429
  updateSession: () => updateSession
16430
16430
  });
16431
- import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync7, renameSync, writeFileSync as writeFileSync5 } from "node:fs";
16432
- import { dirname as dirname4, join as join10 } from "node:path";
16431
+ import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync8, renameSync, writeFileSync as writeFileSync6 } from "node:fs";
16432
+ import { dirname as dirname4, join as join11 } from "node:path";
16433
16433
  import { createRequire as createRequire2 } from "node:module";
16434
16434
  import initSqlJs from "sql.js";
16435
16435
  function locateWasm() {
16436
16436
  const require3 = createRequire2(import.meta.url);
16437
16437
  const sqlJsPath = require3.resolve("sql.js");
16438
- return join10(dirname4(sqlJsPath), "sql-wasm.wasm");
16438
+ return join11(dirname4(sqlJsPath), "sql-wasm.wasm");
16439
16439
  }
16440
16440
  function applyPragmas(db) {
16441
16441
  db.run("PRAGMA foreign_keys = ON;");
@@ -16447,7 +16447,7 @@ async function openDatabase(dbPath) {
16447
16447
  if (cached) {
16448
16448
  return cached;
16449
16449
  }
16450
- const wasmBuffer = readFileSync7(locateWasm());
16450
+ const wasmBuffer = readFileSync8(locateWasm());
16451
16451
  const wasmBinary = wasmBuffer.buffer.slice(
16452
16452
  wasmBuffer.byteOffset,
16453
16453
  wasmBuffer.byteOffset + wasmBuffer.byteLength
@@ -16456,8 +16456,8 @@ async function openDatabase(dbPath) {
16456
16456
  wasmBinary
16457
16457
  });
16458
16458
  let db;
16459
- if (existsSync8(dbPath)) {
16460
- const fileBuffer = readFileSync7(dbPath);
16459
+ if (existsSync9(dbPath)) {
16460
+ const fileBuffer = readFileSync8(dbPath);
16461
16461
  db = new SQL.Database(fileBuffer);
16462
16462
  } else {
16463
16463
  db = new SQL.Database();
@@ -16469,23 +16469,23 @@ async function openDatabase(dbPath) {
16469
16469
  function saveDatabase(db, dbPath) {
16470
16470
  const data = db.export();
16471
16471
  const dir = dirname4(dbPath);
16472
- if (!existsSync8(dir)) {
16472
+ if (!existsSync9(dir)) {
16473
16473
  mkdirSync3(dir, { recursive: true });
16474
16474
  }
16475
16475
  const tmpPath = dbPath + ".tmp";
16476
- writeFileSync5(tmpPath, Buffer.from(data));
16476
+ writeFileSync6(tmpPath, Buffer.from(data));
16477
16477
  renameSync(tmpPath, dbPath);
16478
16478
  }
16479
16479
  async function getDb(ocrDir) {
16480
- const dbPath = join10(ocrDir, "data", "ocr.db");
16480
+ const dbPath = join11(ocrDir, "data", "ocr.db");
16481
16481
  return openDatabase(dbPath);
16482
16482
  }
16483
16483
  async function ensureDatabase(ocrDir) {
16484
- const dataDir = join10(ocrDir, "data");
16485
- if (!existsSync8(dataDir)) {
16484
+ const dataDir = join11(ocrDir, "data");
16485
+ if (!existsSync9(dataDir)) {
16486
16486
  mkdirSync3(dataDir, { recursive: true });
16487
16487
  }
16488
- const dbPath = join10(dataDir, "ocr.db");
16488
+ const dbPath = join11(dataDir, "ocr.db");
16489
16489
  const db = await openDatabase(dbPath);
16490
16490
  runMigrations(db);
16491
16491
  saveDatabase(db, dbPath);
@@ -20170,19 +20170,59 @@ function parseToolsArg(toolsArg) {
20170
20170
 
20171
20171
  // src/lib/installer.ts
20172
20172
  import {
20173
- existsSync,
20173
+ existsSync as existsSync2,
20174
20174
  mkdirSync,
20175
20175
  cpSync,
20176
- writeFileSync as writeFileSync2,
20176
+ writeFileSync as writeFileSync3,
20177
20177
  readdirSync,
20178
- readFileSync as readFileSync2,
20178
+ readFileSync as readFileSync3,
20179
20179
  unlinkSync as unlinkSync2
20180
20180
  } from "node:fs";
20181
- import { join, dirname } from "node:path";
20181
+ import { join as join2, dirname } from "node:path";
20182
20182
  import { createRequire } from "node:module";
20183
+
20184
+ // src/lib/gitignore.ts
20185
+ import { existsSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
20186
+ import { join } from "node:path";
20187
+ var START_MARKER = "# OCR:START \u2014 managed by open-code-review (do not edit this block)";
20188
+ var END_MARKER = "# OCR:END";
20189
+ var MANAGED_ENTRIES = ["sessions/", "data/", "*.db-shm", "*.db-wal"];
20190
+ function buildManagedBlock() {
20191
+ return [START_MARKER, ...MANAGED_ENTRIES, END_MARKER].join("\n");
20192
+ }
20193
+ function escapeRegex(str) {
20194
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
20195
+ }
20196
+ function ensureGitignore(ocrDir) {
20197
+ const gitignorePath = join(ocrDir, ".gitignore");
20198
+ const block = buildManagedBlock();
20199
+ let content = existsSync(gitignorePath) ? readFileSync2(gitignorePath, "utf-8") : "";
20200
+ const regex2 = new RegExp(
20201
+ `${escapeRegex(START_MARKER)}[\\s\\S]*?${escapeRegex(END_MARKER)}\\n?`,
20202
+ "g"
20203
+ );
20204
+ if (regex2.test(content)) {
20205
+ content = content.replace(
20206
+ new RegExp(
20207
+ `${escapeRegex(START_MARKER)}[\\s\\S]*?${escapeRegex(END_MARKER)}\\n?`,
20208
+ "g"
20209
+ ),
20210
+ block + "\n"
20211
+ );
20212
+ } else {
20213
+ content = content.trimEnd();
20214
+ if (content.length > 0) {
20215
+ content += "\n\n";
20216
+ }
20217
+ content += block + "\n";
20218
+ }
20219
+ writeFileSync2(gitignorePath, content);
20220
+ }
20221
+
20222
+ // src/lib/installer.ts
20183
20223
  var require2 = createRequire(import.meta.url);
20184
20224
  function ensureDir(dir) {
20185
- if (!existsSync(dir)) {
20225
+ if (!existsSync2(dir)) {
20186
20226
  mkdirSync(dir, { recursive: true });
20187
20227
  }
20188
20228
  }
@@ -20191,8 +20231,8 @@ function getAgentsPackagePath() {
20191
20231
  const agentsPath = require2.resolve("@open-code-review/agents/package.json");
20192
20232
  return dirname(agentsPath);
20193
20233
  } catch {
20194
- const localPath = join(process.cwd(), "packages", "agents");
20195
- if (existsSync(localPath)) {
20234
+ const localPath = join2(process.cwd(), "packages", "agents");
20235
+ if (existsSync2(localPath)) {
20196
20236
  return localPath;
20197
20237
  }
20198
20238
  throw new Error(
@@ -20212,8 +20252,8 @@ function copyDirSafe(src, dest) {
20212
20252
  function copyFileSafe(src, dest) {
20213
20253
  try {
20214
20254
  ensureDir(dirname(dest));
20215
- const content = readFileSync2(src);
20216
- writeFileSync2(dest, content);
20255
+ const content = readFileSync3(src);
20256
+ writeFileSync3(dest, content);
20217
20257
  return true;
20218
20258
  } catch {
20219
20259
  return false;
@@ -20237,8 +20277,8 @@ function extractDescription(content) {
20237
20277
  return match?.[1]?.trim() ?? "OCR command";
20238
20278
  }
20239
20279
  function installCommandsForTool(tool, commandsSource, targetDir) {
20240
- const toolCommandsDir = join(targetDir, tool.commandsDir);
20241
- const centralCommandsDir = join(targetDir, ".ocr", "commands");
20280
+ const toolCommandsDir = join2(targetDir, tool.commandsDir);
20281
+ const centralCommandsDir = join2(targetDir, ".ocr", "commands");
20242
20282
  ensureDir(toolCommandsDir);
20243
20283
  ensureDir(centralCommandsDir);
20244
20284
  try {
@@ -20246,32 +20286,32 @@ function installCommandsForTool(tool, commandsSource, targetDir) {
20246
20286
  (f) => f.endsWith(".md")
20247
20287
  );
20248
20288
  for (const file of commandFiles) {
20249
- const srcPath = join(commandsSource, file);
20289
+ const srcPath = join2(commandsSource, file);
20250
20290
  const normalizedName = file.replace(/^ocr-/, "");
20251
- const centralPath = join(centralCommandsDir, normalizedName);
20291
+ const centralPath = join2(centralCommandsDir, normalizedName);
20252
20292
  if (!copyFileSafe(srcPath, centralPath)) {
20253
20293
  return false;
20254
20294
  }
20255
20295
  }
20256
20296
  if (tool.commandStrategy === "subdirectory") {
20257
- const ocrSubdir = join(toolCommandsDir, "ocr");
20297
+ const ocrSubdir = join2(toolCommandsDir, "ocr");
20258
20298
  ensureDir(ocrSubdir);
20259
20299
  for (const file of commandFiles) {
20260
- const srcPath = join(commandsSource, file);
20261
- const content = readFileSync2(srcPath, "utf-8");
20300
+ const srcPath = join2(commandsSource, file);
20301
+ const content = readFileSync3(srcPath, "utf-8");
20262
20302
  const description = extractDescription(content);
20263
20303
  const normalizedName = file.replace(/^ocr-/, "");
20264
20304
  const refContent = generateCommandReference(
20265
20305
  normalizedName,
20266
20306
  description
20267
20307
  );
20268
- const destPath = join(ocrSubdir, normalizedName);
20269
- writeFileSync2(destPath, refContent);
20308
+ const destPath = join2(ocrSubdir, normalizedName);
20309
+ writeFileSync3(destPath, refContent);
20270
20310
  }
20271
20311
  } else {
20272
20312
  for (const file of commandFiles) {
20273
- const srcPath = join(commandsSource, file);
20274
- const content = readFileSync2(srcPath, "utf-8");
20313
+ const srcPath = join2(commandsSource, file);
20314
+ const content = readFileSync3(srcPath, "utf-8");
20275
20315
  const description = extractDescription(content);
20276
20316
  const normalizedName = file.replace(/^ocr-/, "");
20277
20317
  const destName = `ocr-${normalizedName}`;
@@ -20279,8 +20319,8 @@ function installCommandsForTool(tool, commandsSource, targetDir) {
20279
20319
  normalizedName,
20280
20320
  description
20281
20321
  );
20282
- const destPath = join(toolCommandsDir, destName);
20283
- writeFileSync2(destPath, refContent);
20322
+ const destPath = join2(toolCommandsDir, destName);
20323
+ writeFileSync3(destPath, refContent);
20284
20324
  }
20285
20325
  }
20286
20326
  return true;
@@ -20290,39 +20330,33 @@ function installCommandsForTool(tool, commandsSource, targetDir) {
20290
20330
  }
20291
20331
  function installForTool(tool, targetDir) {
20292
20332
  const agentsPath = getAgentsPackagePath();
20293
- const ocrSkillsSource = join(agentsPath, "skills", "ocr");
20294
- const commandsSource = join(agentsPath, "commands");
20295
- const ocrDir = join(targetDir, ".ocr");
20296
- const ocrSkillsDest = join(ocrDir, "skills");
20333
+ const ocrSkillsSource = join2(agentsPath, "skills", "ocr");
20334
+ const commandsSource = join2(agentsPath, "commands");
20335
+ const ocrDir = join2(targetDir, ".ocr");
20336
+ const ocrSkillsDest = join2(ocrDir, "skills");
20297
20337
  ensureDir(ocrDir);
20298
- ensureDir(join(ocrDir, "sessions"));
20299
- const gitignoreContent = `# OCR session files
20300
- sessions/
20301
- `;
20302
- const gitignorePath = join(ocrDir, ".gitignore");
20303
- if (!existsSync(gitignorePath)) {
20304
- writeFileSync2(gitignorePath, gitignoreContent);
20305
- }
20306
- const configPath = join(ocrDir, "config.yaml");
20338
+ ensureDir(join2(ocrDir, "sessions"));
20339
+ ensureGitignore(ocrDir);
20340
+ const configPath = join2(ocrDir, "config.yaml");
20307
20341
  let existingConfig = null;
20308
- if (existsSync(configPath)) {
20342
+ if (existsSync2(configPath)) {
20309
20343
  try {
20310
- existingConfig = readFileSync2(configPath);
20344
+ existingConfig = readFileSync3(configPath);
20311
20345
  } catch {
20312
20346
  }
20313
20347
  }
20314
- const reviewersDir = join(ocrSkillsDest, "references", "reviewers");
20348
+ const reviewersDir = join2(ocrSkillsDest, "references", "reviewers");
20315
20349
  const existingReviewers = /* @__PURE__ */ new Map();
20316
20350
  const warnings = [];
20317
- if (existsSync(reviewersDir)) {
20351
+ if (existsSync2(reviewersDir)) {
20318
20352
  try {
20319
20353
  const reviewerFiles = readdirSync(reviewersDir).filter(
20320
20354
  (f) => f.endsWith(".md")
20321
20355
  );
20322
20356
  for (const file of reviewerFiles) {
20323
- const filePath = join(reviewersDir, file);
20357
+ const filePath = join2(reviewersDir, file);
20324
20358
  try {
20325
- existingReviewers.set(file, readFileSync2(filePath));
20359
+ existingReviewers.set(file, readFileSync3(filePath));
20326
20360
  } catch (err) {
20327
20361
  const msg = err instanceof Error ? err.message : "unknown error";
20328
20362
  warnings.push(`Could not read reviewer ${file}: ${msg}`);
@@ -20341,17 +20375,17 @@ sessions/
20341
20375
  error: "Failed to install OCR skills to .ocr/"
20342
20376
  };
20343
20377
  }
20344
- const configSource = join(ocrSkillsSource, "assets", "config.yaml");
20378
+ const configSource = join2(ocrSkillsSource, "assets", "config.yaml");
20345
20379
  if (existingConfig) {
20346
20380
  try {
20347
- writeFileSync2(configPath, existingConfig);
20381
+ writeFileSync3(configPath, existingConfig);
20348
20382
  } catch {
20349
20383
  }
20350
- } else if (existsSync(configSource)) {
20384
+ } else if (existsSync2(configSource)) {
20351
20385
  copyFileSafe(configSource, configPath);
20352
20386
  }
20353
- const duplicateConfig = join(ocrSkillsDest, "assets", "config.yaml");
20354
- if (existsSync(duplicateConfig)) {
20387
+ const duplicateConfig = join2(ocrSkillsDest, "assets", "config.yaml");
20388
+ if (existsSync2(duplicateConfig)) {
20355
20389
  try {
20356
20390
  unlinkSync2(duplicateConfig);
20357
20391
  } catch {
@@ -20361,7 +20395,7 @@ sessions/
20361
20395
  ensureDir(reviewersDir);
20362
20396
  for (const [file, content] of existingReviewers) {
20363
20397
  try {
20364
- writeFileSync2(join(reviewersDir, file), content);
20398
+ writeFileSync3(join2(reviewersDir, file), content);
20365
20399
  } catch (err) {
20366
20400
  const msg = err instanceof Error ? err.message : "unknown error";
20367
20401
  warnings.push(`Could not restore reviewer ${file}: ${msg}`);
@@ -20384,27 +20418,27 @@ sessions/
20384
20418
  }
20385
20419
  function detectInstalledTools(targetDir, tools) {
20386
20420
  return tools.filter((tool) => {
20387
- const configPath = join(targetDir, tool.configDir);
20421
+ const configPath = join2(targetDir, tool.configDir);
20388
20422
  if (tool.id === "github-copilot") {
20389
- const copilotInstructions = join(
20423
+ const copilotInstructions = join2(
20390
20424
  targetDir,
20391
20425
  ".github",
20392
20426
  "copilot-instructions.md"
20393
20427
  );
20394
- const copilotDir = join(targetDir, ".github", "copilot");
20395
- const copilotCommands = join(targetDir, ".github", "commands");
20396
- return existsSync(copilotInstructions) || existsSync(copilotDir) || existsSync(copilotCommands);
20428
+ const copilotDir = join2(targetDir, ".github", "copilot");
20429
+ const copilotCommands = join2(targetDir, ".github", "commands");
20430
+ return existsSync2(copilotInstructions) || existsSync2(copilotDir) || existsSync2(copilotCommands);
20397
20431
  }
20398
- return existsSync(configPath);
20432
+ return existsSync2(configPath);
20399
20433
  });
20400
20434
  }
20401
20435
 
20402
20436
  // src/lib/injector.ts
20403
- import { existsSync as existsSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
20404
- import { join as join2 } from "node:path";
20405
- var START_MARKER = "<!-- OCR:START -->";
20406
- var END_MARKER = "<!-- OCR:END -->";
20407
- var OCR_INSTRUCTION_BLOCK = `${START_MARKER}
20437
+ import { existsSync as existsSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
20438
+ import { join as join3 } from "node:path";
20439
+ var START_MARKER2 = "<!-- OCR:START -->";
20440
+ var END_MARKER2 = "<!-- OCR:END -->";
20441
+ var OCR_INSTRUCTION_BLOCK = `${START_MARKER2}
20408
20442
  # Open Code Review Instructions
20409
20443
 
20410
20444
  These instructions are for AI assistants handling code review in this project.
@@ -20423,12 +20457,12 @@ Use \`.ocr/skills/SKILL.md\` to learn:
20423
20457
 
20424
20458
  Keep this managed block so 'ocr init' can refresh the instructions.
20425
20459
 
20426
- ${END_MARKER}`;
20460
+ ${END_MARKER2}`;
20427
20461
  function injectOcrInstructions(filePath) {
20428
20462
  try {
20429
- let content = existsSync2(filePath) ? readFileSync3(filePath, "utf-8") : "";
20463
+ let content = existsSync3(filePath) ? readFileSync4(filePath, "utf-8") : "";
20430
20464
  const regex2 = new RegExp(
20431
- `${escapeRegex(START_MARKER)}[\\s\\S]*?${escapeRegex(END_MARKER)}\\n?`,
20465
+ `${escapeRegex2(START_MARKER2)}[\\s\\S]*?${escapeRegex2(END_MARKER2)}\\n?`,
20432
20466
  "g"
20433
20467
  );
20434
20468
  content = content.replace(regex2, "");
@@ -20437,18 +20471,18 @@ function injectOcrInstructions(filePath) {
20437
20471
  content += "\n\n";
20438
20472
  }
20439
20473
  content += OCR_INSTRUCTION_BLOCK + "\n";
20440
- writeFileSync3(filePath, content);
20474
+ writeFileSync4(filePath, content);
20441
20475
  return true;
20442
20476
  } catch {
20443
20477
  return false;
20444
20478
  }
20445
20479
  }
20446
- function escapeRegex(str) {
20480
+ function escapeRegex2(str) {
20447
20481
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
20448
20482
  }
20449
20483
  function injectIntoProjectFiles(targetDir) {
20450
- const agentsMdPath = join2(targetDir, "AGENTS.md");
20451
- const claudeMdPath = join2(targetDir, "CLAUDE.md");
20484
+ const agentsMdPath = join3(targetDir, "AGENTS.md");
20485
+ const claudeMdPath = join3(targetDir, "CLAUDE.md");
20452
20486
  const agentsMd = injectOcrInstructions(agentsMdPath);
20453
20487
  const claudeMd = injectOcrInstructions(claudeMdPath);
20454
20488
  return { agentsMd, claudeMd };
@@ -20491,19 +20525,19 @@ function printHeader() {
20491
20525
  }
20492
20526
 
20493
20527
  // src/lib/cli-config.ts
20494
- import { existsSync as existsSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
20495
- import { join as join3 } from "node:path";
20528
+ import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
20529
+ import { join as join4 } from "node:path";
20496
20530
  var CLI_CONFIG_FILE = "cli-config.json";
20497
20531
  function getCliConfigPath(targetDir) {
20498
- return join3(targetDir, ".ocr", CLI_CONFIG_FILE);
20532
+ return join4(targetDir, ".ocr", CLI_CONFIG_FILE);
20499
20533
  }
20500
20534
  function loadCliConfig(targetDir) {
20501
20535
  const configPath = getCliConfigPath(targetDir);
20502
- if (!existsSync3(configPath)) {
20536
+ if (!existsSync4(configPath)) {
20503
20537
  return null;
20504
20538
  }
20505
20539
  try {
20506
- const content = readFileSync4(configPath, "utf-8");
20540
+ const content = readFileSync5(configPath, "utf-8");
20507
20541
  return JSON.parse(content);
20508
20542
  } catch {
20509
20543
  return null;
@@ -20516,7 +20550,7 @@ function saveCliConfig(targetDir, config) {
20516
20550
  ...config,
20517
20551
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
20518
20552
  };
20519
- writeFileSync4(configPath, JSON.stringify(configWithMeta, null, 2) + "\n");
20553
+ writeFileSync5(configPath, JSON.stringify(configWithMeta, null, 2) + "\n");
20520
20554
  return true;
20521
20555
  } catch {
20522
20556
  return false;
@@ -22533,8 +22567,8 @@ function watch(paths, options = {}) {
22533
22567
  }
22534
22568
 
22535
22569
  // src/commands/progress.ts
22536
- import { existsSync as existsSync9, readdirSync as readdirSync5, statSync } from "node:fs";
22537
- import { join as join11, basename as basename7 } from "node:path";
22570
+ import { existsSync as existsSync10, readdirSync as readdirSync5, statSync } from "node:fs";
22571
+ import { join as join12, basename as basename7 } from "node:path";
22538
22572
 
22539
22573
  // ../../node_modules/.pnpm/log-update@7.0.2/node_modules/log-update/index.js
22540
22574
  import process12 from "node:process";
@@ -23402,15 +23436,15 @@ var log_update_default = logUpdate;
23402
23436
  var logUpdateStderr = createLogUpdate(process12.stderr);
23403
23437
 
23404
23438
  // src/lib/guards.ts
23405
- import { existsSync as existsSync4, mkdirSync as mkdirSync2 } from "node:fs";
23406
- import { join as join6 } from "node:path";
23439
+ import { existsSync as existsSync5, mkdirSync as mkdirSync2 } from "node:fs";
23440
+ import { join as join7 } from "node:path";
23407
23441
  function checkOcrSetup(targetDir) {
23408
- const ocrDir = join6(targetDir, ".ocr");
23409
- const skillsDir = join6(ocrDir, "skills");
23410
- const sessionsDir = join6(ocrDir, "sessions");
23411
- const hasOcrDir = existsSync4(ocrDir);
23412
- const hasSkills = existsSync4(skillsDir);
23413
- const hasSessions = existsSync4(sessionsDir);
23442
+ const ocrDir = join7(targetDir, ".ocr");
23443
+ const skillsDir = join7(ocrDir, "skills");
23444
+ const sessionsDir = join7(ocrDir, "sessions");
23445
+ const hasOcrDir = existsSync5(ocrDir);
23446
+ const hasSkills = existsSync5(skillsDir);
23447
+ const hasSessions = existsSync5(sessionsDir);
23414
23448
  return {
23415
23449
  valid: hasOcrDir && hasSkills,
23416
23450
  ocrDir,
@@ -23426,7 +23460,7 @@ function requireOcrSetup(targetDir) {
23426
23460
  console.error();
23427
23461
  console.error(source_default.red.bold(" \u2717 OCR is not set up in this directory"));
23428
23462
  console.error();
23429
- if (!existsSync4(status.ocrDir)) {
23463
+ if (!existsSync5(status.ocrDir)) {
23430
23464
  console.error(source_default.dim(" The .ocr directory was not found."));
23431
23465
  } else if (!status.hasSkills) {
23432
23466
  console.error(source_default.dim(" The .ocr/skills directory is missing."));
@@ -23446,8 +23480,8 @@ function requireOcrSetup(targetDir) {
23446
23480
  return status;
23447
23481
  }
23448
23482
  function ensureSessionsDir(targetDir) {
23449
- const sessionsDir = join6(targetDir, ".ocr", "sessions");
23450
- if (!existsSync4(sessionsDir)) {
23483
+ const sessionsDir = join7(targetDir, ".ocr", "sessions");
23484
+ if (!existsSync5(sessionsDir)) {
23451
23485
  mkdirSync2(sessionsDir, { recursive: true });
23452
23486
  }
23453
23487
  return sessionsDir;
@@ -23463,8 +23497,8 @@ function getStrategy(workflowType) {
23463
23497
  }
23464
23498
 
23465
23499
  // src/lib/progress/detector.ts
23466
- import { existsSync as existsSync5, readdirSync as readdirSync2 } from "node:fs";
23467
- import { join as join7, basename as basename4 } from "node:path";
23500
+ import { existsSync as existsSync6, readdirSync as readdirSync2 } from "node:fs";
23501
+ import { join as join8, basename as basename4 } from "node:path";
23468
23502
 
23469
23503
  // src/lib/progress/session-reader.ts
23470
23504
  init_result_mapper();
@@ -23535,8 +23569,8 @@ function detectWorkflowType(sessionPath, explicitType) {
23535
23569
  } catch {
23536
23570
  }
23537
23571
  }
23538
- const hasMapDir = existsSync5(join7(sessionPath, "map"));
23539
- const hasRoundsDir = existsSync5(join7(sessionPath, "rounds"));
23572
+ const hasMapDir = existsSync6(join8(sessionPath, "map"));
23573
+ const hasRoundsDir = existsSync6(join8(sessionPath, "rounds"));
23540
23574
  if (hasMapDir && !hasRoundsDir) {
23541
23575
  return "map";
23542
23576
  }
@@ -23592,28 +23626,28 @@ function isSessionActive(sessionPath) {
23592
23626
  }
23593
23627
  function detectActiveWorkflows(sessionPath) {
23594
23628
  const activeWorkflows = [];
23595
- const hasRoundsDir = existsSync5(join7(sessionPath, "rounds"));
23629
+ const hasRoundsDir = existsSync6(join8(sessionPath, "rounds"));
23596
23630
  if (hasRoundsDir) {
23597
- const roundsDir = join7(sessionPath, "rounds");
23598
- const rounds = existsSync5(roundsDir) ? readdirSync2(roundsDir).filter((d) => d.match(/^round-\d+$/)).sort() : [];
23631
+ const roundsDir = join8(sessionPath, "rounds");
23632
+ const rounds = existsSync6(roundsDir) ? readdirSync2(roundsDir).filter((d) => d.match(/^round-\d+$/)).sort() : [];
23599
23633
  if (rounds.length > 0) {
23600
23634
  const latestRound = rounds[rounds.length - 1];
23601
- const finalPath = join7(roundsDir, latestRound, "final.md");
23602
- if (!existsSync5(finalPath)) {
23635
+ const finalPath = join8(roundsDir, latestRound, "final.md");
23636
+ if (!existsSync6(finalPath)) {
23603
23637
  activeWorkflows.push("review");
23604
23638
  }
23605
23639
  } else {
23606
23640
  activeWorkflows.push("review");
23607
23641
  }
23608
23642
  }
23609
- const hasMapDir = existsSync5(join7(sessionPath, "map"));
23643
+ const hasMapDir = existsSync6(join8(sessionPath, "map"));
23610
23644
  if (hasMapDir) {
23611
- const runsDir = join7(sessionPath, "map", "runs");
23612
- const runs = existsSync5(runsDir) ? readdirSync2(runsDir).filter((d) => d.match(/^run-\d+$/)).sort() : [];
23645
+ const runsDir = join8(sessionPath, "map", "runs");
23646
+ const runs = existsSync6(runsDir) ? readdirSync2(runsDir).filter((d) => d.match(/^run-\d+$/)).sort() : [];
23613
23647
  if (runs.length > 0) {
23614
23648
  const latestRun = runs[runs.length - 1];
23615
- const mapPath = join7(runsDir, latestRun, "map.md");
23616
- if (!existsSync5(mapPath)) {
23649
+ const mapPath = join8(runsDir, latestRun, "map.md");
23650
+ if (!existsSync6(mapPath)) {
23617
23651
  activeWorkflows.push("map");
23618
23652
  }
23619
23653
  } else {
@@ -23692,8 +23726,8 @@ function padLines(lines) {
23692
23726
  }
23693
23727
 
23694
23728
  // src/lib/progress/review-strategy.ts
23695
- import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync5 } from "node:fs";
23696
- import { join as join8, basename as basename5 } from "node:path";
23729
+ import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync6 } from "node:fs";
23730
+ import { join as join9, basename as basename5 } from "node:path";
23697
23731
  var REVIEW_PHASES = [
23698
23732
  { key: "context", label: "Context Discovery" },
23699
23733
  { key: "change-context", label: "Change Context" },
@@ -23705,10 +23739,10 @@ var REVIEW_PHASES = [
23705
23739
  { key: "complete", label: "Complete" }
23706
23740
  ];
23707
23741
  function countFindings(filePath) {
23708
- if (!existsSync6(filePath)) {
23742
+ if (!existsSync7(filePath)) {
23709
23743
  return 0;
23710
23744
  }
23711
- const content = readFileSync5(filePath, "utf-8");
23745
+ const content = readFileSync6(filePath, "utf-8");
23712
23746
  const findingMatches = content.match(/^##\s+(Finding|Issue|Suggestion)/gm);
23713
23747
  return findingMatches?.length ?? 0;
23714
23748
  }
@@ -23722,7 +23756,7 @@ function formatReviewerName(filename) {
23722
23756
  return base.charAt(0).toUpperCase() + base.slice(1);
23723
23757
  }
23724
23758
  function deriveRoundsFromFilesystem(roundsDir) {
23725
- if (!existsSync6(roundsDir)) {
23759
+ if (!existsSync7(roundsDir)) {
23726
23760
  return [];
23727
23761
  }
23728
23762
  const roundDirs = readdirSync3(roundsDir).filter((d) => d.match(/^round-\d+$/)).sort((a, b) => {
@@ -23732,17 +23766,17 @@ function deriveRoundsFromFilesystem(roundsDir) {
23732
23766
  });
23733
23767
  return roundDirs.map((dir) => {
23734
23768
  const roundNum = parseInt(dir.replace("round-", ""));
23735
- const roundPath = join8(roundsDir, dir);
23736
- const reviewsPath = join8(roundPath, "reviews");
23737
- const finalPath = join8(roundPath, "final.md");
23769
+ const roundPath = join9(roundsDir, dir);
23770
+ const reviewsPath = join9(roundPath, "reviews");
23771
+ const finalPath = join9(roundPath, "final.md");
23738
23772
  const reviewers = [];
23739
- if (existsSync6(reviewsPath)) {
23773
+ if (existsSync7(reviewsPath)) {
23740
23774
  const files = readdirSync3(reviewsPath).filter((f) => f.endsWith(".md"));
23741
23775
  reviewers.push(...files.map((f) => f.replace(".md", "")));
23742
23776
  }
23743
23777
  return {
23744
23778
  round: roundNum,
23745
- isComplete: existsSync6(finalPath),
23779
+ isComplete: existsSync7(finalPath),
23746
23780
  reviewers
23747
23781
  };
23748
23782
  });
@@ -23771,19 +23805,19 @@ var ReviewProgressStrategy = class {
23771
23805
  parseFromState(session, state, sessionPath, preservedStartTime) {
23772
23806
  const effectiveStartTime = state.round_started_at ?? state.started_at;
23773
23807
  const startTime = preservedStartTime ?? (effectiveStartTime ? new Date(effectiveStartTime).getTime() : Date.now());
23774
- const roundsDir = join8(sessionPath, "rounds");
23808
+ const roundsDir = join9(sessionPath, "rounds");
23775
23809
  const rounds = deriveRoundsFromFilesystem(roundsDir);
23776
23810
  const highestExistingRound = rounds.length > 0 ? Math.max(...rounds.map((r) => r.round)) : 1;
23777
23811
  const stateRound = state.current_round ?? 1;
23778
23812
  const currentRound = Math.min(stateRound, highestExistingRound);
23779
- const currentRoundDir = join8(roundsDir, `round-${currentRound}`);
23780
- const reviewsDir = join8(currentRoundDir, "reviews");
23813
+ const currentRoundDir = join9(roundsDir, `round-${currentRound}`);
23814
+ const reviewsDir = join9(currentRoundDir, "reviews");
23781
23815
  const reviewers = [];
23782
- if (existsSync6(reviewsDir)) {
23816
+ if (existsSync7(reviewsDir)) {
23783
23817
  const entries = readdirSync3(reviewsDir);
23784
23818
  const reviewFiles = entries.filter((f) => f.endsWith(".md"));
23785
23819
  for (const file of reviewFiles) {
23786
- const reviewPath = join8(reviewsDir, file);
23820
+ const reviewPath = join9(reviewsDir, file);
23787
23821
  const findings = countFindings(reviewPath);
23788
23822
  reviewers.push({
23789
23823
  name: file.replace(".md", ""),
@@ -23793,14 +23827,14 @@ var ReviewProgressStrategy = class {
23793
23827
  });
23794
23828
  }
23795
23829
  }
23796
- const contextComplete = existsSync6(
23797
- join8(sessionPath, "discovered-standards.md")
23830
+ const contextComplete = existsSync7(
23831
+ join9(sessionPath, "discovered-standards.md")
23798
23832
  );
23799
- const changeContextComplete = existsSync6(join8(sessionPath, "context.md"));
23833
+ const changeContextComplete = existsSync7(join9(sessionPath, "context.md"));
23800
23834
  const analysisComplete = changeContextComplete;
23801
23835
  const reviewsComplete = state.phase_number > 4;
23802
- const discourseComplete = existsSync6(join8(currentRoundDir, "discourse.md"));
23803
- const synthesisComplete = existsSync6(join8(currentRoundDir, "final.md"));
23836
+ const discourseComplete = existsSync7(join9(currentRoundDir, "discourse.md"));
23837
+ const synthesisComplete = existsSync7(join9(currentRoundDir, "final.md"));
23804
23838
  return {
23805
23839
  workflowType: "review",
23806
23840
  session,
@@ -23932,8 +23966,8 @@ var ReviewProgressStrategy = class {
23932
23966
  var reviewStrategy = new ReviewProgressStrategy();
23933
23967
 
23934
23968
  // src/lib/progress/map-strategy.ts
23935
- import { existsSync as existsSync7, readdirSync as readdirSync4, readFileSync as readFileSync6 } from "node:fs";
23936
- import { join as join9, basename as basename6 } from "node:path";
23969
+ import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync7 } from "node:fs";
23970
+ import { join as join10, basename as basename6 } from "node:path";
23937
23971
  var MAP_PHASES = [
23938
23972
  { key: "map-context", label: "Context Discovery" },
23939
23973
  { key: "topology", label: "Topology Analysis" },
@@ -23943,8 +23977,8 @@ var MAP_PHASES = [
23943
23977
  { key: "complete", label: "Complete" }
23944
23978
  ];
23945
23979
  function deriveRunsFromFilesystem(mapDir) {
23946
- const runsDir = join9(mapDir, "runs");
23947
- if (!existsSync7(runsDir)) {
23980
+ const runsDir = join10(mapDir, "runs");
23981
+ if (!existsSync8(runsDir)) {
23948
23982
  return [];
23949
23983
  }
23950
23984
  const runDirs = readdirSync4(runsDir).filter((d) => d.match(/^run-\d+$/)).sort((a, b) => {
@@ -23954,12 +23988,12 @@ function deriveRunsFromFilesystem(mapDir) {
23954
23988
  });
23955
23989
  return runDirs.map((dir) => {
23956
23990
  const runNum = parseInt(dir.replace("run-", ""));
23957
- const runPath = join9(runsDir, dir);
23958
- const mapPath = join9(runPath, "map.md");
23991
+ const runPath = join10(runsDir, dir);
23992
+ const mapPath = join10(runPath, "map.md");
23959
23993
  let fileCount = 0;
23960
- const topologyPath = join9(runPath, "topology.md");
23961
- if (existsSync7(topologyPath)) {
23962
- const content = readFileSync6(topologyPath, "utf-8");
23994
+ const topologyPath = join10(runPath, "topology.md");
23995
+ if (existsSync8(topologyPath)) {
23996
+ const content = readFileSync7(topologyPath, "utf-8");
23963
23997
  const fileListMatch = content.match(
23964
23998
  /## Canonical File List[\s\S]*?```([\s\S]*?)```/
23965
23999
  );
@@ -23969,7 +24003,7 @@ function deriveRunsFromFilesystem(mapDir) {
23969
24003
  }
23970
24004
  return {
23971
24005
  run: runNum,
23972
- isComplete: existsSync7(mapPath),
24006
+ isComplete: existsSync8(mapPath),
23973
24007
  fileCount
23974
24008
  };
23975
24009
  });
@@ -24001,24 +24035,24 @@ var MapProgressStrategy = class {
24001
24035
  parseFromState(session, state, sessionPath, preservedStartTime) {
24002
24036
  const effectiveStartTime = state.map_started_at ?? state.started_at;
24003
24037
  const startTime = preservedStartTime ?? (effectiveStartTime ? new Date(effectiveStartTime).getTime() : Date.now());
24004
- const mapDir = join9(sessionPath, "map");
24038
+ const mapDir = join10(sessionPath, "map");
24005
24039
  const runs = deriveRunsFromFilesystem(mapDir);
24006
24040
  const highestExistingRun = runs.length > 0 ? Math.max(...runs.map((r) => r.run)) : 1;
24007
24041
  const stateRun = state.current_map_run ?? 1;
24008
24042
  const currentRun = Math.min(stateRun, highestExistingRun);
24009
- const currentRunDir = join9(mapDir, "runs", `run-${currentRun}`);
24010
- const contextComplete = existsSync7(
24011
- join9(sessionPath, "discovered-standards.md")
24043
+ const currentRunDir = join10(mapDir, "runs", `run-${currentRun}`);
24044
+ const contextComplete = existsSync8(
24045
+ join10(sessionPath, "discovered-standards.md")
24012
24046
  );
24013
- const topologyComplete = existsSync7(join9(currentRunDir, "topology.md"));
24014
- const flowAnalysisComplete = existsSync7(
24015
- join9(currentRunDir, "flow-analysis.md")
24047
+ const topologyComplete = existsSync8(join10(currentRunDir, "topology.md"));
24048
+ const flowAnalysisComplete = existsSync8(
24049
+ join10(currentRunDir, "flow-analysis.md")
24016
24050
  );
24017
- const requirementsMappingComplete = existsSync7(
24018
- join9(currentRunDir, "requirements-mapping.md")
24051
+ const requirementsMappingComplete = existsSync8(
24052
+ join10(currentRunDir, "requirements-mapping.md")
24019
24053
  );
24020
- const synthesisComplete = existsSync7(join9(currentRunDir, "map.md"));
24021
- const hasRequirements = existsSync7(join9(sessionPath, "requirements.md"));
24054
+ const synthesisComplete = existsSync8(join10(currentRunDir, "map.md"));
24055
+ const hasRequirements = existsSync8(join10(sessionPath, "requirements.md"));
24022
24056
  const flowAnalysts = flowAnalysisComplete ? [
24023
24057
  {
24024
24058
  name: "flow-analyst",
@@ -24170,15 +24204,15 @@ function debounce(fn, delay) {
24170
24204
  };
24171
24205
  }
24172
24206
  function findLatestActiveSession(sessionsDir) {
24173
- if (!existsSync9(sessionsDir)) {
24207
+ if (!existsSync10(sessionsDir)) {
24174
24208
  return null;
24175
24209
  }
24176
24210
  const sessions = readdirSync5(sessionsDir).filter((name) => {
24177
- const sessionPath = join11(sessionsDir, name);
24211
+ const sessionPath = join12(sessionsDir, name);
24178
24212
  return statSync(sessionPath).isDirectory();
24179
24213
  }).sort().reverse();
24180
24214
  for (const session of sessions) {
24181
- const sessionPath = join11(sessionsDir, session);
24215
+ const sessionPath = join12(sessionsDir, session);
24182
24216
  if (isSessionActive(sessionPath)) {
24183
24217
  return session;
24184
24218
  }
@@ -24193,8 +24227,8 @@ function getStrategyForSession(sessionPath, explicitWorkflow) {
24193
24227
  return getStrategy(workflowType) ?? null;
24194
24228
  }
24195
24229
  async function initProgressDb(ocrDir) {
24196
- const dbPath = join11(ocrDir, "data", "ocr.db");
24197
- if (!existsSync9(dbPath)) {
24230
+ const dbPath = join12(ocrDir, "data", "ocr.db");
24231
+ if (!existsSync10(dbPath)) {
24198
24232
  return;
24199
24233
  }
24200
24234
  try {
@@ -24219,11 +24253,11 @@ var progressCommand = new Command("progress").description("Watch real-time progr
24219
24253
  const targetDir = process.cwd();
24220
24254
  requireOcrSetup(targetDir);
24221
24255
  const sessionsDir = ensureSessionsDir(targetDir);
24222
- const ocrDir = join11(targetDir, ".ocr");
24256
+ const ocrDir = join12(targetDir, ".ocr");
24223
24257
  await initProgressDb(ocrDir);
24224
24258
  if (options.session) {
24225
- const sessionPath = join11(sessionsDir, options.session);
24226
- if (!existsSync9(sessionPath)) {
24259
+ const sessionPath = join12(sessionsDir, options.session);
24260
+ if (!existsSync10(sessionPath)) {
24227
24261
  console.error(source_default.red(`Session not found: ${options.session}`));
24228
24262
  process.exit(1);
24229
24263
  }
@@ -24284,7 +24318,7 @@ var progressCommand = new Command("progress").description("Watch real-time progr
24284
24318
  return;
24285
24319
  }
24286
24320
  let currentSession = findLatestActiveSession(sessionsDir);
24287
- let currentSessionPath = currentSession ? join11(sessionsDir, currentSession) : null;
24321
+ let currentSessionPath = currentSession ? join12(sessionsDir, currentSession) : null;
24288
24322
  let sessionWatcher = null;
24289
24323
  const preservedStartTimes = {
24290
24324
  review: void 0,
@@ -24292,11 +24326,11 @@ var progressCommand = new Command("progress").description("Watch real-time progr
24292
24326
  };
24293
24327
  let currentStrategy = null;
24294
24328
  const updateDisplayImpl = () => {
24295
- if (!currentSessionPath || !existsSync9(currentSessionPath) || !isSessionActive(currentSessionPath)) {
24329
+ if (!currentSessionPath || !existsSync10(currentSessionPath) || !isSessionActive(currentSessionPath)) {
24296
24330
  const latestActive = findLatestActiveSession(sessionsDir);
24297
24331
  if (latestActive && latestActive !== currentSession) {
24298
24332
  currentSession = latestActive;
24299
- currentSessionPath = join11(sessionsDir, latestActive);
24333
+ currentSessionPath = join12(sessionsDir, latestActive);
24300
24334
  preservedStartTimes.review = void 0;
24301
24335
  preservedStartTimes.map = void 0;
24302
24336
  currentStrategy = null;
@@ -24309,7 +24343,7 @@ var progressCommand = new Command("progress").description("Watch real-time progr
24309
24343
  currentStrategy = null;
24310
24344
  }
24311
24345
  }
24312
- if (currentSessionPath && existsSync9(currentSessionPath)) {
24346
+ if (currentSessionPath && existsSync10(currentSessionPath)) {
24313
24347
  if (!options.workflow) {
24314
24348
  const activeWorkflows = detectActiveWorkflows(currentSessionPath);
24315
24349
  if (activeWorkflows.length > 1) {
@@ -24363,15 +24397,15 @@ var progressCommand = new Command("progress").description("Watch real-time progr
24363
24397
  watchSession(currentSessionPath);
24364
24398
  }
24365
24399
  const timerInterval = setInterval(updateDisplay, 1e3);
24366
- const watchDir = existsSync9(ocrDir) ? ocrDir : targetDir;
24400
+ const watchDir = existsSync10(ocrDir) ? ocrDir : targetDir;
24367
24401
  const dirWatcher = watch(watchDir, {
24368
24402
  persistent: true,
24369
24403
  ignoreInitial: true,
24370
24404
  depth: 3
24371
24405
  });
24372
24406
  dirWatcher.on("addDir", (dirPath) => {
24373
- const parentDir = join11(dirPath, "..");
24374
- const isDirectChild = parentDir.endsWith("sessions") || parentDir.endsWith(join11(".ocr", "sessions"));
24407
+ const parentDir = join12(dirPath, "..");
24408
+ const isDirectChild = parentDir.endsWith("sessions") || parentDir.endsWith(join12(".ocr", "sessions"));
24375
24409
  if (isDirectChild && !dirPath.endsWith("sessions")) {
24376
24410
  const newSession = basename7(dirPath);
24377
24411
  currentSession = newSession;
@@ -24473,27 +24507,27 @@ function renderCombinedProgress(sessionPath, preservedStartTimes, ocrDir) {
24473
24507
  }
24474
24508
 
24475
24509
  // src/commands/state.ts
24476
- import { existsSync as existsSync11, mkdirSync as mkdirSync4 } from "node:fs";
24477
- import { join as join13 } from "node:path";
24510
+ import { existsSync as existsSync12, mkdirSync as mkdirSync4 } from "node:fs";
24511
+ import { join as join14 } from "node:path";
24478
24512
 
24479
24513
  // src/lib/state/index.ts
24480
24514
  init_db();
24481
- import { existsSync as existsSync10, readdirSync as readdirSync6, statSync as statSync2 } from "node:fs";
24482
- import { join as join12 } from "node:path";
24515
+ import { existsSync as existsSync11, readdirSync as readdirSync6, statSync as statSync2 } from "node:fs";
24516
+ import { join as join13 } from "node:path";
24483
24517
  async function stateInit(params) {
24484
24518
  const { sessionId, branch, workflowType, sessionDir, ocrDir } = params;
24485
24519
  const db = await ensureDatabase(ocrDir);
24486
- const dbPath = join12(ocrDir, "data", "ocr.db");
24520
+ const dbPath = join13(ocrDir, "data", "ocr.db");
24487
24521
  const existing = getSession(db, sessionId);
24488
24522
  if (existing) {
24489
- const roundsDir = join12(sessionDir, "rounds");
24523
+ const roundsDir = join13(sessionDir, "rounds");
24490
24524
  let nextRound = 1;
24491
- if (existsSync10(roundsDir)) {
24525
+ if (existsSync11(roundsDir)) {
24492
24526
  const roundDirs = readdirSync6(roundsDir).filter((d) => /^round-\d+$/.test(d)).map((d) => parseInt(d.replace("round-", ""), 10)).sort((a, b) => a - b);
24493
24527
  if (roundDirs.length > 0) {
24494
24528
  const highest = roundDirs[roundDirs.length - 1];
24495
- const hasFinal = existsSync10(
24496
- join12(roundsDir, `round-${highest}`, "final.md")
24529
+ const hasFinal = existsSync11(
24530
+ join13(roundsDir, `round-${highest}`, "final.md")
24497
24531
  );
24498
24532
  nextRound = hasFinal ? highest + 1 : highest;
24499
24533
  }
@@ -24537,7 +24571,7 @@ async function stateInit(params) {
24537
24571
  async function stateTransition(params) {
24538
24572
  const { sessionId, phase, phaseNumber, round, mapRun, ocrDir } = params;
24539
24573
  const db = await ensureDatabase(ocrDir);
24540
- const dbPath = join12(ocrDir, "data", "ocr.db");
24574
+ const dbPath = join13(ocrDir, "data", "ocr.db");
24541
24575
  const existing = getSession(db, sessionId);
24542
24576
  if (!existing) {
24543
24577
  throw new Error(`Session not found: ${sessionId}`);
@@ -24570,7 +24604,7 @@ async function stateTransition(params) {
24570
24604
  async function stateClose(params) {
24571
24605
  const { sessionId, ocrDir } = params;
24572
24606
  const db = await ensureDatabase(ocrDir);
24573
- const dbPath = join12(ocrDir, "data", "ocr.db");
24607
+ const dbPath = join13(ocrDir, "data", "ocr.db");
24574
24608
  const existing = getSession(db, sessionId);
24575
24609
  if (!existing) {
24576
24610
  throw new Error(`Session not found: ${sessionId}`);
@@ -24637,24 +24671,24 @@ async function resolveActiveSession(ocrDir) {
24637
24671
  }
24638
24672
  async function stateSync(ocrDir) {
24639
24673
  const db = await ensureDatabase(ocrDir);
24640
- const dbPath = join12(ocrDir, "data", "ocr.db");
24641
- const sessionsRoot = join12(ocrDir, "sessions");
24642
- if (!existsSync10(sessionsRoot)) {
24674
+ const dbPath = join13(ocrDir, "data", "ocr.db");
24675
+ const sessionsRoot = join13(ocrDir, "sessions");
24676
+ if (!existsSync11(sessionsRoot)) {
24643
24677
  return 0;
24644
24678
  }
24645
24679
  const entries = readdirSync6(sessionsRoot).filter((name) => {
24646
- const fullPath = join12(sessionsRoot, name);
24680
+ const fullPath = join13(sessionsRoot, name);
24647
24681
  return statSync2(fullPath).isDirectory();
24648
24682
  });
24649
24683
  let synced = 0;
24650
24684
  for (const dirName of entries) {
24651
- const dirPath = join12(sessionsRoot, dirName);
24685
+ const dirPath = join13(sessionsRoot, dirName);
24652
24686
  const existing = getSession(db, dirName);
24653
24687
  if (existing) {
24654
24688
  continue;
24655
24689
  }
24656
- const hasRoundsDir = existsSync10(join12(dirPath, "rounds"));
24657
- const hasMapDir = existsSync10(join12(dirPath, "map"));
24690
+ const hasRoundsDir = existsSync11(join13(dirPath, "rounds"));
24691
+ const hasMapDir = existsSync11(join13(dirPath, "map"));
24658
24692
  const workflowType = hasMapDir && !hasRoundsDir ? "map" : "review";
24659
24693
  const branchMatch = dirName.match(/^\d{4}-\d{2}-\d{2}-(.+)$/);
24660
24694
  const branch = branchMatch?.[1] ?? dirName;
@@ -24699,9 +24733,9 @@ var initSubcommand = new Command("init").description("Initialize a new OCR sessi
24699
24733
  async (options) => {
24700
24734
  const targetDir = process.cwd();
24701
24735
  requireOcrSetup(targetDir);
24702
- const ocrDir = join13(targetDir, ".ocr");
24703
- const sessionDir = options.sessionDir ?? join13(ocrDir, "sessions", options.sessionId);
24704
- if (!existsSync11(sessionDir)) {
24736
+ const ocrDir = join14(targetDir, ".ocr");
24737
+ const sessionDir = options.sessionDir ?? join14(ocrDir, "sessions", options.sessionId);
24738
+ if (!existsSync12(sessionDir)) {
24705
24739
  mkdirSync4(sessionDir, { recursive: true });
24706
24740
  }
24707
24741
  try {
@@ -24727,7 +24761,7 @@ var transitionSubcommand = new Command("transition").description("Transition ses
24727
24761
  async (options) => {
24728
24762
  const targetDir = process.cwd();
24729
24763
  requireOcrSetup(targetDir);
24730
- const ocrDir = join13(targetDir, ".ocr");
24764
+ const ocrDir = join14(targetDir, ".ocr");
24731
24765
  try {
24732
24766
  const sessionId = options.sessionId ?? (await resolveActiveSession(ocrDir)).id;
24733
24767
  await stateTransition({
@@ -24754,7 +24788,7 @@ var transitionSubcommand = new Command("transition").description("Transition ses
24754
24788
  var closeSubcommand = new Command("close").description("Close a session").option("--session-id <id>", "Session ID (auto-detects latest active if omitted)").action(async (options) => {
24755
24789
  const targetDir = process.cwd();
24756
24790
  requireOcrSetup(targetDir);
24757
- const ocrDir = join13(targetDir, ".ocr");
24791
+ const ocrDir = join14(targetDir, ".ocr");
24758
24792
  try {
24759
24793
  const sessionId = options.sessionId ?? (await resolveActiveSession(ocrDir)).id;
24760
24794
  await stateClose({
@@ -24774,7 +24808,7 @@ var closeSubcommand = new Command("close").description("Close a session").option
24774
24808
  var showSubcommand = new Command("show").description("Show current session state").option("--session-id <id>", "Session ID (defaults to latest active)").option("--json", "Output as JSON").action(async (options) => {
24775
24809
  const targetDir = process.cwd();
24776
24810
  requireOcrSetup(targetDir);
24777
- const ocrDir = join13(targetDir, ".ocr");
24811
+ const ocrDir = join14(targetDir, ".ocr");
24778
24812
  try {
24779
24813
  const result = await stateShow(ocrDir, options.sessionId);
24780
24814
  if (!result) {
@@ -24843,7 +24877,7 @@ var showSubcommand = new Command("show").description("Show current session state
24843
24877
  var syncSubcommand = new Command("sync").description("Rebuild session state from filesystem artifacts").action(async () => {
24844
24878
  const targetDir = process.cwd();
24845
24879
  requireOcrSetup(targetDir);
24846
- const ocrDir = join13(targetDir, ".ocr");
24880
+ const ocrDir = join14(targetDir, ".ocr");
24847
24881
  try {
24848
24882
  const synced = await stateSync(ocrDir);
24849
24883
  console.log(`Synced ${synced} session${synced !== 1 ? "s" : ""} from filesystem.`);
@@ -24859,16 +24893,16 @@ var syncSubcommand = new Command("sync").description("Rebuild session state from
24859
24893
  var stateCommand = new Command("state").description("Manage OCR session state").addCommand(initSubcommand).addCommand(transitionSubcommand).addCommand(closeSubcommand).addCommand(showSubcommand).addCommand(syncSubcommand);
24860
24894
 
24861
24895
  // src/commands/update.ts
24862
- import { existsSync as existsSync12 } from "node:fs";
24863
- import { join as join14 } from "node:path";
24896
+ import { existsSync as existsSync13 } from "node:fs";
24897
+ import { join as join15 } from "node:path";
24864
24898
  function detectConfiguredTools(targetDir) {
24865
24899
  return AI_TOOLS.filter((tool) => {
24866
24900
  if (tool.commandStrategy === "subdirectory") {
24867
- const ocrDir = join14(targetDir, tool.commandsDir, "ocr");
24868
- return existsSync12(ocrDir);
24901
+ const ocrDir = join15(targetDir, tool.commandsDir, "ocr");
24902
+ return existsSync13(ocrDir);
24869
24903
  } else {
24870
- const reviewCmd = join14(targetDir, tool.commandsDir, "ocr-review.md");
24871
- return existsSync12(reviewCmd);
24904
+ const reviewCmd = join15(targetDir, tool.commandsDir, "ocr-review.md");
24905
+ return existsSync13(reviewCmd);
24872
24906
  }
24873
24907
  });
24874
24908
  }
@@ -24942,6 +24976,7 @@ var updateCommand = new Command("update").description("Update OCR assets after p
24942
24976
  const result = installForTool(tool, targetDir);
24943
24977
  results.push(result);
24944
24978
  }
24979
+ ensureGitignore(join15(targetDir, ".ocr"));
24945
24980
  spinner.stop();
24946
24981
  const successful = results.filter((r) => r.success);
24947
24982
  const failed = results.filter((r) => !r.success);
@@ -24977,10 +25012,10 @@ var updateCommand = new Command("update").description("Update OCR assets after p
24977
25012
  if (updateInject) {
24978
25013
  if (options.dryRun) {
24979
25014
  console.log(source_default.dim(" Would update:"));
24980
- if (existsSync12(join14(targetDir, "AGENTS.md"))) {
25015
+ if (existsSync13(join15(targetDir, "AGENTS.md"))) {
24981
25016
  console.log(source_default.dim(" \u2022 AGENTS.md (OCR managed block)"));
24982
25017
  }
24983
- if (existsSync12(join14(targetDir, "CLAUDE.md"))) {
25018
+ if (existsSync13(join15(targetDir, "CLAUDE.md"))) {
24984
25019
  console.log(source_default.dim(" \u2022 CLAUDE.md (OCR managed block)"));
24985
25020
  }
24986
25021
  console.log();
@@ -25011,14 +25046,14 @@ var updateCommand = new Command("update").description("Update OCR assets after p
25011
25046
  });
25012
25047
 
25013
25048
  // src/commands/dashboard.ts
25014
- import { existsSync as existsSync13 } from "node:fs";
25015
- import { join as join15, dirname as dirname5 } from "node:path";
25049
+ import { existsSync as existsSync14 } from "node:fs";
25050
+ import { join as join16, dirname as dirname5 } from "node:path";
25016
25051
  import { fileURLToPath } from "node:url";
25017
25052
  init_db();
25018
25053
  var __filename = fileURLToPath(import.meta.url);
25019
25054
  var __dirname = dirname5(__filename);
25020
25055
  function resolveServerPath() {
25021
- return join15(__dirname, "dashboard", "server.js");
25056
+ return join16(__dirname, "dashboard", "server.js");
25022
25057
  }
25023
25058
  var dashboardCommand = new Command("dashboard").description("Start the OCR dashboard web interface").option("-p, --port <port>", "Port to run the server on", "4173").option("--no-open", "Don't open the browser automatically").action(
25024
25059
  async (options) => {
@@ -25029,7 +25064,7 @@ var dashboardCommand = new Command("dashboard").description("Start the OCR dashb
25029
25064
  console.error(source_default.red(`Error: Invalid port "${options.port}". Must be 1-65535.`));
25030
25065
  process.exit(1);
25031
25066
  }
25032
- const ocrDir = join15(targetDir, ".ocr");
25067
+ const ocrDir = join16(targetDir, ".ocr");
25033
25068
  try {
25034
25069
  await ensureDatabase(ocrDir);
25035
25070
  closeAllDatabases();
@@ -25043,7 +25078,7 @@ var dashboardCommand = new Command("dashboard").description("Start the OCR dashb
25043
25078
  process.exit(1);
25044
25079
  }
25045
25080
  const serverPath = resolveServerPath();
25046
- if (!existsSync13(serverPath)) {
25081
+ if (!existsSync14(serverPath)) {
25047
25082
  console.error(source_default.red("Error: Dashboard server bundle not found."));
25048
25083
  console.error(
25049
25084
  source_default.dim(` Expected at: ${serverPath}`)
@@ -25077,8 +25112,8 @@ var dashboardCommand = new Command("dashboard").description("Start the OCR dashb
25077
25112
  );
25078
25113
 
25079
25114
  // src/commands/doctor.ts
25080
- import { existsSync as existsSync14 } from "node:fs";
25081
- import { join as join16 } from "node:path";
25115
+ import { existsSync as existsSync15 } from "node:fs";
25116
+ import { join as join17 } from "node:path";
25082
25117
  var doctorCommand = new Command("doctor").description("Check OCR installation and verify all dependencies").action(() => {
25083
25118
  printHeader();
25084
25119
  const targetDir = process.cwd();
@@ -25092,10 +25127,10 @@ var doctorCommand = new Command("doctor").description("Check OCR installation an
25092
25127
  console.log(source_default.bold(" OCR Installation"));
25093
25128
  console.log();
25094
25129
  const ocrStatus = checkOcrSetup(targetDir);
25095
- const configPath = join16(targetDir, ".ocr", "config.yaml");
25096
- const dbPath = join16(targetDir, ".ocr", "data", "ocr.db");
25097
- const hasConfig = existsSync14(configPath);
25098
- const hasDb = existsSync14(dbPath);
25130
+ const configPath = join17(targetDir, ".ocr", "config.yaml");
25131
+ const dbPath = join17(targetDir, ".ocr", "data", "ocr.db");
25132
+ const hasConfig = existsSync15(configPath);
25133
+ const hasDb = existsSync15(dbPath);
25099
25134
  const ocrChecks = [
25100
25135
  { label: ".ocr/skills/", ok: ocrStatus.hasSkills },
25101
25136
  { label: ".ocr/sessions/", ok: ocrStatus.hasSessions },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-code-review/cli",
3
- "version": "1.5.0",
3
+ "version": "1.5.1",
4
4
  "description": "CLI for Open Code Review - Multi-environment setup and progress tracking",
5
5
  "type": "module",
6
6
  "bin": {
@@ -50,7 +50,7 @@
50
50
  "ora": "^8.1.1",
51
51
  "socket.io": "^4.8",
52
52
  "sql.js": "^1.14.1",
53
- "@open-code-review/agents": "1.5.0"
53
+ "@open-code-review/agents": "1.5.1"
54
54
  },
55
55
  "publishConfig": {
56
56
  "access": "public"