@open-code-review/cli 1.9.0 → 1.10.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.
- package/dist/dashboard/server.js +426 -214
- package/dist/index.js +290 -123
- package/dist/lib/db/index.js +128 -17
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -16307,6 +16307,14 @@ var init_migrations = __esm({
|
|
|
16307
16307
|
sql: `
|
|
16308
16308
|
ALTER TABLE map_runs ADD COLUMN source TEXT DEFAULT NULL;
|
|
16309
16309
|
ALTER TABLE map_runs ADD COLUMN section_count INTEGER DEFAULT 0;
|
|
16310
|
+
`
|
|
16311
|
+
},
|
|
16312
|
+
{
|
|
16313
|
+
version: 9,
|
|
16314
|
+
description: "Add uid column to command_executions for JSONL-backed recovery",
|
|
16315
|
+
sql: `
|
|
16316
|
+
ALTER TABLE command_executions ADD COLUMN uid TEXT;
|
|
16317
|
+
CREATE UNIQUE INDEX idx_command_executions_uid ON command_executions(uid);
|
|
16310
16318
|
`
|
|
16311
16319
|
}
|
|
16312
16320
|
];
|
|
@@ -16428,14 +16436,121 @@ var init_queries = __esm({
|
|
|
16428
16436
|
}
|
|
16429
16437
|
});
|
|
16430
16438
|
|
|
16439
|
+
// src/lib/db/command-log.ts
|
|
16440
|
+
import { appendFileSync, existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync8, renameSync, writeFileSync as writeFileSync6 } from "node:fs";
|
|
16441
|
+
import { dirname as dirname4, join as join11 } from "node:path";
|
|
16442
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
16443
|
+
function generateCommandUid() {
|
|
16444
|
+
return randomUUID2();
|
|
16445
|
+
}
|
|
16446
|
+
function cacheDir(ocrDir) {
|
|
16447
|
+
return join11(ocrDir, "data", CACHE_DIR);
|
|
16448
|
+
}
|
|
16449
|
+
function commandLogPath(ocrDir) {
|
|
16450
|
+
return join11(cacheDir(ocrDir), FILENAME);
|
|
16451
|
+
}
|
|
16452
|
+
function appendCommandLog(ocrDir, entry) {
|
|
16453
|
+
try {
|
|
16454
|
+
const filePath = commandLogPath(ocrDir);
|
|
16455
|
+
const dir = dirname4(filePath);
|
|
16456
|
+
if (!existsSync9(dir)) mkdirSync3(dir, { recursive: true });
|
|
16457
|
+
const line = JSON.stringify(entry) + "\n";
|
|
16458
|
+
appendFileSync(filePath, line, { encoding: "utf-8" });
|
|
16459
|
+
if (approxLineCount >= 0) approxLineCount++;
|
|
16460
|
+
rotateIfNeeded(filePath);
|
|
16461
|
+
} catch {
|
|
16462
|
+
}
|
|
16463
|
+
}
|
|
16464
|
+
function readCommandLog(ocrDir) {
|
|
16465
|
+
const filePath = commandLogPath(ocrDir);
|
|
16466
|
+
if (!existsSync9(filePath)) return [];
|
|
16467
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
16468
|
+
const entries = [];
|
|
16469
|
+
for (const line of content.split("\n")) {
|
|
16470
|
+
if (!line.trim()) continue;
|
|
16471
|
+
try {
|
|
16472
|
+
entries.push(JSON.parse(line));
|
|
16473
|
+
} catch {
|
|
16474
|
+
}
|
|
16475
|
+
}
|
|
16476
|
+
return entries;
|
|
16477
|
+
}
|
|
16478
|
+
function replayCommandLog(db, ocrDir) {
|
|
16479
|
+
const entries = readCommandLog(ocrDir);
|
|
16480
|
+
if (entries.length === 0) return 0;
|
|
16481
|
+
const latest = /* @__PURE__ */ new Map();
|
|
16482
|
+
for (const entry of entries) {
|
|
16483
|
+
if (!entry.uid || !entry.command || !entry.started_at) continue;
|
|
16484
|
+
const existing = latest.get(entry.uid);
|
|
16485
|
+
if (!existing || entry.event !== "start") {
|
|
16486
|
+
latest.set(entry.uid, entry);
|
|
16487
|
+
}
|
|
16488
|
+
}
|
|
16489
|
+
let imported = 0;
|
|
16490
|
+
for (const entry of latest.values()) {
|
|
16491
|
+
if (entry.event === "start" && !entry.finished_at) continue;
|
|
16492
|
+
const existing = db.exec(
|
|
16493
|
+
"SELECT COUNT(*) as c FROM command_executions WHERE uid = ?",
|
|
16494
|
+
[entry.uid]
|
|
16495
|
+
);
|
|
16496
|
+
if ((existing[0]?.values[0]?.[0] ?? 0) > 0) continue;
|
|
16497
|
+
db.run(
|
|
16498
|
+
`INSERT INTO command_executions
|
|
16499
|
+
(uid, command, args, exit_code, started_at, finished_at, pid, is_detached)
|
|
16500
|
+
VALUES (?, ?, ?, ?, ?, ?, NULL, ?)`,
|
|
16501
|
+
[
|
|
16502
|
+
entry.uid,
|
|
16503
|
+
entry.command,
|
|
16504
|
+
entry.args,
|
|
16505
|
+
entry.exit_code,
|
|
16506
|
+
entry.started_at,
|
|
16507
|
+
entry.finished_at,
|
|
16508
|
+
entry.is_detached
|
|
16509
|
+
]
|
|
16510
|
+
);
|
|
16511
|
+
imported++;
|
|
16512
|
+
}
|
|
16513
|
+
return imported;
|
|
16514
|
+
}
|
|
16515
|
+
function rotateIfNeeded(filePath) {
|
|
16516
|
+
try {
|
|
16517
|
+
if (approxLineCount >= 0 && approxLineCount <= MAX_LINES) return;
|
|
16518
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
16519
|
+
const lines = content.split("\n").filter((l) => l.trim());
|
|
16520
|
+
approxLineCount = lines.length;
|
|
16521
|
+
if (approxLineCount <= MAX_LINES) return;
|
|
16522
|
+
const kept = lines.slice(lines.length - KEEP_LINES);
|
|
16523
|
+
const tmpPath = `${filePath}.${process.pid}.tmp`;
|
|
16524
|
+
writeFileSync6(tmpPath, kept.join("\n") + "\n", { encoding: "utf-8" });
|
|
16525
|
+
renameSync(tmpPath, filePath);
|
|
16526
|
+
approxLineCount = KEEP_LINES;
|
|
16527
|
+
} catch {
|
|
16528
|
+
}
|
|
16529
|
+
}
|
|
16530
|
+
var CACHE_DIR, FILENAME, MAX_LINES, KEEP_LINES, approxLineCount;
|
|
16531
|
+
var init_command_log = __esm({
|
|
16532
|
+
"src/lib/db/command-log.ts"() {
|
|
16533
|
+
"use strict";
|
|
16534
|
+
CACHE_DIR = ".cache";
|
|
16535
|
+
FILENAME = "command-history.jsonl";
|
|
16536
|
+
MAX_LINES = 5e3;
|
|
16537
|
+
KEEP_LINES = 4e3;
|
|
16538
|
+
approxLineCount = -1;
|
|
16539
|
+
}
|
|
16540
|
+
});
|
|
16541
|
+
|
|
16431
16542
|
// src/lib/db/index.ts
|
|
16432
16543
|
var db_exports = {};
|
|
16433
16544
|
__export(db_exports, {
|
|
16434
16545
|
MIGRATIONS: () => MIGRATIONS,
|
|
16546
|
+
appendCommandLog: () => appendCommandLog,
|
|
16435
16547
|
applyPragmas: () => applyPragmas,
|
|
16548
|
+
cacheDir: () => cacheDir,
|
|
16436
16549
|
closeAllDatabases: () => closeAllDatabases,
|
|
16437
16550
|
closeDatabase: () => closeDatabase,
|
|
16551
|
+
commandLogPath: () => commandLogPath,
|
|
16438
16552
|
ensureDatabase: () => ensureDatabase,
|
|
16553
|
+
generateCommandUid: () => generateCommandUid,
|
|
16439
16554
|
getAllSessions: () => getAllSessions,
|
|
16440
16555
|
getDb: () => getDb,
|
|
16441
16556
|
getEventsForSession: () => getEventsForSession,
|
|
@@ -16446,20 +16561,22 @@ __export(db_exports, {
|
|
|
16446
16561
|
insertSession: () => insertSession,
|
|
16447
16562
|
locateWasm: () => locateWasm,
|
|
16448
16563
|
openDatabase: () => openDatabase,
|
|
16564
|
+
readCommandLog: () => readCommandLog,
|
|
16565
|
+
replayCommandLog: () => replayCommandLog,
|
|
16449
16566
|
resultToRow: () => resultToRow,
|
|
16450
16567
|
resultToRows: () => resultToRows,
|
|
16451
16568
|
runMigrations: () => runMigrations,
|
|
16452
16569
|
saveDatabase: () => saveDatabase,
|
|
16453
16570
|
updateSession: () => updateSession
|
|
16454
16571
|
});
|
|
16455
|
-
import { existsSync as
|
|
16456
|
-
import { dirname as
|
|
16572
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync as renameSync2, writeFileSync as writeFileSync7 } from "node:fs";
|
|
16573
|
+
import { dirname as dirname5, join as join12 } from "node:path";
|
|
16457
16574
|
import { createRequire as createRequire2 } from "node:module";
|
|
16458
16575
|
import initSqlJs from "sql.js";
|
|
16459
16576
|
function locateWasm() {
|
|
16460
16577
|
const require3 = createRequire2(import.meta.url);
|
|
16461
16578
|
const sqlJsPath = require3.resolve("sql.js");
|
|
16462
|
-
return
|
|
16579
|
+
return join12(dirname5(sqlJsPath), "sql-wasm.wasm");
|
|
16463
16580
|
}
|
|
16464
16581
|
function applyPragmas(db) {
|
|
16465
16582
|
db.run("PRAGMA foreign_keys = ON;");
|
|
@@ -16471,7 +16588,7 @@ async function openDatabase(dbPath) {
|
|
|
16471
16588
|
if (cached) {
|
|
16472
16589
|
return cached;
|
|
16473
16590
|
}
|
|
16474
|
-
const wasmBuffer =
|
|
16591
|
+
const wasmBuffer = readFileSync9(locateWasm());
|
|
16475
16592
|
const wasmBinary = wasmBuffer.buffer.slice(
|
|
16476
16593
|
wasmBuffer.byteOffset,
|
|
16477
16594
|
wasmBuffer.byteOffset + wasmBuffer.byteLength
|
|
@@ -16480,8 +16597,8 @@ async function openDatabase(dbPath) {
|
|
|
16480
16597
|
wasmBinary
|
|
16481
16598
|
});
|
|
16482
16599
|
let db;
|
|
16483
|
-
if (
|
|
16484
|
-
const fileBuffer =
|
|
16600
|
+
if (existsSync10(dbPath)) {
|
|
16601
|
+
const fileBuffer = readFileSync9(dbPath);
|
|
16485
16602
|
db = new SQL.Database(fileBuffer);
|
|
16486
16603
|
} else {
|
|
16487
16604
|
db = new SQL.Database();
|
|
@@ -16492,24 +16609,24 @@ async function openDatabase(dbPath) {
|
|
|
16492
16609
|
}
|
|
16493
16610
|
function saveDatabase(db, dbPath) {
|
|
16494
16611
|
const data = db.export();
|
|
16495
|
-
const dir =
|
|
16496
|
-
if (!
|
|
16497
|
-
|
|
16612
|
+
const dir = dirname5(dbPath);
|
|
16613
|
+
if (!existsSync10(dir)) {
|
|
16614
|
+
mkdirSync4(dir, { recursive: true });
|
|
16498
16615
|
}
|
|
16499
|
-
const tmpPath = dbPath
|
|
16500
|
-
|
|
16501
|
-
|
|
16616
|
+
const tmpPath = `${dbPath}.${process.pid}.tmp`;
|
|
16617
|
+
writeFileSync7(tmpPath, Buffer.from(data));
|
|
16618
|
+
renameSync2(tmpPath, dbPath);
|
|
16502
16619
|
}
|
|
16503
16620
|
async function getDb(ocrDir) {
|
|
16504
|
-
const dbPath =
|
|
16621
|
+
const dbPath = join12(ocrDir, "data", "ocr.db");
|
|
16505
16622
|
return openDatabase(dbPath);
|
|
16506
16623
|
}
|
|
16507
16624
|
async function ensureDatabase(ocrDir) {
|
|
16508
|
-
const dataDir =
|
|
16509
|
-
if (!
|
|
16510
|
-
|
|
16625
|
+
const dataDir = join12(ocrDir, "data");
|
|
16626
|
+
if (!existsSync10(dataDir)) {
|
|
16627
|
+
mkdirSync4(dataDir, { recursive: true });
|
|
16511
16628
|
}
|
|
16512
|
-
const dbPath =
|
|
16629
|
+
const dbPath = join12(dataDir, "ocr.db");
|
|
16513
16630
|
const db = await openDatabase(dbPath);
|
|
16514
16631
|
runMigrations(db);
|
|
16515
16632
|
saveDatabase(db, dbPath);
|
|
@@ -16536,6 +16653,7 @@ var init_db = __esm({
|
|
|
16536
16653
|
init_queries();
|
|
16537
16654
|
init_migrations();
|
|
16538
16655
|
init_result_mapper();
|
|
16656
|
+
init_command_log();
|
|
16539
16657
|
connections = /* @__PURE__ */ new Map();
|
|
16540
16658
|
}
|
|
16541
16659
|
});
|
|
@@ -20776,7 +20894,7 @@ ${hint}
|
|
|
20776
20894
|
}
|
|
20777
20895
|
|
|
20778
20896
|
// src/lib/version.ts
|
|
20779
|
-
var CLI_VERSION = true ? "1.
|
|
20897
|
+
var CLI_VERSION = true ? "1.10.1" : createRequire(import.meta.url)("../../package.json").version;
|
|
20780
20898
|
|
|
20781
20899
|
// src/lib/deps.ts
|
|
20782
20900
|
import { execFileSync } from "node:child_process";
|
|
@@ -21816,9 +21934,9 @@ var NodeFsHandler = class {
|
|
|
21816
21934
|
if (this.fsw.closed) {
|
|
21817
21935
|
return;
|
|
21818
21936
|
}
|
|
21819
|
-
const
|
|
21937
|
+
const dirname7 = sysPath.dirname(file);
|
|
21820
21938
|
const basename8 = sysPath.basename(file);
|
|
21821
|
-
const parent = this.fsw._getWatchedDir(
|
|
21939
|
+
const parent = this.fsw._getWatchedDir(dirname7);
|
|
21822
21940
|
let prevStats = stats;
|
|
21823
21941
|
if (parent.has(basename8))
|
|
21824
21942
|
return;
|
|
@@ -21845,7 +21963,7 @@ var NodeFsHandler = class {
|
|
|
21845
21963
|
prevStats = newStats2;
|
|
21846
21964
|
}
|
|
21847
21965
|
} catch (error) {
|
|
21848
|
-
this.fsw._remove(
|
|
21966
|
+
this.fsw._remove(dirname7, basename8);
|
|
21849
21967
|
}
|
|
21850
21968
|
} else if (parent.has(basename8)) {
|
|
21851
21969
|
const at = newStats.atimeMs;
|
|
@@ -22778,8 +22896,8 @@ function watch(paths, options = {}) {
|
|
|
22778
22896
|
}
|
|
22779
22897
|
|
|
22780
22898
|
// src/commands/progress.ts
|
|
22781
|
-
import { existsSync as
|
|
22782
|
-
import { join as
|
|
22899
|
+
import { existsSync as existsSync11, readdirSync as readdirSync5, statSync } from "node:fs";
|
|
22900
|
+
import { join as join13, basename as basename7 } from "node:path";
|
|
22783
22901
|
|
|
22784
22902
|
// ../../node_modules/.pnpm/log-update@7.0.2/node_modules/log-update/index.js
|
|
22785
22903
|
import process12 from "node:process";
|
|
@@ -24415,15 +24533,15 @@ function debounce(fn, delay) {
|
|
|
24415
24533
|
};
|
|
24416
24534
|
}
|
|
24417
24535
|
function findLatestActiveSession(sessionsDir) {
|
|
24418
|
-
if (!
|
|
24536
|
+
if (!existsSync11(sessionsDir)) {
|
|
24419
24537
|
return null;
|
|
24420
24538
|
}
|
|
24421
24539
|
const sessions = readdirSync5(sessionsDir).filter((name) => {
|
|
24422
|
-
const sessionPath =
|
|
24540
|
+
const sessionPath = join13(sessionsDir, name);
|
|
24423
24541
|
return statSync(sessionPath).isDirectory();
|
|
24424
24542
|
}).sort().reverse();
|
|
24425
24543
|
for (const session of sessions) {
|
|
24426
|
-
const sessionPath =
|
|
24544
|
+
const sessionPath = join13(sessionsDir, session);
|
|
24427
24545
|
if (isSessionActive(sessionPath)) {
|
|
24428
24546
|
return session;
|
|
24429
24547
|
}
|
|
@@ -24438,8 +24556,8 @@ function getStrategyForSession(sessionPath, explicitWorkflow) {
|
|
|
24438
24556
|
return getStrategy(workflowType) ?? null;
|
|
24439
24557
|
}
|
|
24440
24558
|
async function initProgressDb(ocrDir) {
|
|
24441
|
-
const dbPath =
|
|
24442
|
-
if (!
|
|
24559
|
+
const dbPath = join13(ocrDir, "data", "ocr.db");
|
|
24560
|
+
if (!existsSync11(dbPath)) {
|
|
24443
24561
|
return;
|
|
24444
24562
|
}
|
|
24445
24563
|
try {
|
|
@@ -24464,11 +24582,11 @@ var progressCommand = new Command("progress").description("Watch real-time progr
|
|
|
24464
24582
|
const targetDir = process.cwd();
|
|
24465
24583
|
requireOcrSetup(targetDir);
|
|
24466
24584
|
const sessionsDir = ensureSessionsDir(targetDir);
|
|
24467
|
-
const ocrDir =
|
|
24585
|
+
const ocrDir = join13(targetDir, ".ocr");
|
|
24468
24586
|
await initProgressDb(ocrDir);
|
|
24469
24587
|
if (options.session) {
|
|
24470
|
-
const sessionPath =
|
|
24471
|
-
if (!
|
|
24588
|
+
const sessionPath = join13(sessionsDir, options.session);
|
|
24589
|
+
if (!existsSync11(sessionPath)) {
|
|
24472
24590
|
console.error(source_default.red(`Session not found: ${options.session}`));
|
|
24473
24591
|
process.exit(1);
|
|
24474
24592
|
}
|
|
@@ -24529,7 +24647,7 @@ var progressCommand = new Command("progress").description("Watch real-time progr
|
|
|
24529
24647
|
return;
|
|
24530
24648
|
}
|
|
24531
24649
|
let currentSession = findLatestActiveSession(sessionsDir);
|
|
24532
|
-
let currentSessionPath = currentSession ?
|
|
24650
|
+
let currentSessionPath = currentSession ? join13(sessionsDir, currentSession) : null;
|
|
24533
24651
|
let sessionWatcher = null;
|
|
24534
24652
|
const preservedStartTimes = {
|
|
24535
24653
|
review: void 0,
|
|
@@ -24537,11 +24655,11 @@ var progressCommand = new Command("progress").description("Watch real-time progr
|
|
|
24537
24655
|
};
|
|
24538
24656
|
let currentStrategy = null;
|
|
24539
24657
|
const updateDisplayImpl = () => {
|
|
24540
|
-
if (!currentSessionPath || !
|
|
24658
|
+
if (!currentSessionPath || !existsSync11(currentSessionPath) || !isSessionActive(currentSessionPath)) {
|
|
24541
24659
|
const latestActive = findLatestActiveSession(sessionsDir);
|
|
24542
24660
|
if (latestActive && latestActive !== currentSession) {
|
|
24543
24661
|
currentSession = latestActive;
|
|
24544
|
-
currentSessionPath =
|
|
24662
|
+
currentSessionPath = join13(sessionsDir, latestActive);
|
|
24545
24663
|
preservedStartTimes.review = void 0;
|
|
24546
24664
|
preservedStartTimes.map = void 0;
|
|
24547
24665
|
currentStrategy = null;
|
|
@@ -24554,7 +24672,7 @@ var progressCommand = new Command("progress").description("Watch real-time progr
|
|
|
24554
24672
|
currentStrategy = null;
|
|
24555
24673
|
}
|
|
24556
24674
|
}
|
|
24557
|
-
if (currentSessionPath &&
|
|
24675
|
+
if (currentSessionPath && existsSync11(currentSessionPath)) {
|
|
24558
24676
|
if (!options.workflow) {
|
|
24559
24677
|
const activeWorkflows = detectActiveWorkflows(currentSessionPath);
|
|
24560
24678
|
if (activeWorkflows.length > 1) {
|
|
@@ -24608,15 +24726,15 @@ var progressCommand = new Command("progress").description("Watch real-time progr
|
|
|
24608
24726
|
watchSession(currentSessionPath);
|
|
24609
24727
|
}
|
|
24610
24728
|
const timerInterval = setInterval(updateDisplay, 1e3);
|
|
24611
|
-
const watchDir =
|
|
24729
|
+
const watchDir = existsSync11(ocrDir) ? ocrDir : targetDir;
|
|
24612
24730
|
const dirWatcher = watch(watchDir, {
|
|
24613
24731
|
persistent: true,
|
|
24614
24732
|
ignoreInitial: true,
|
|
24615
24733
|
depth: 3
|
|
24616
24734
|
});
|
|
24617
24735
|
dirWatcher.on("addDir", (dirPath) => {
|
|
24618
|
-
const parentDir =
|
|
24619
|
-
const isDirectChild = parentDir.endsWith("sessions") || parentDir.endsWith(
|
|
24736
|
+
const parentDir = join13(dirPath, "..");
|
|
24737
|
+
const isDirectChild = parentDir.endsWith("sessions") || parentDir.endsWith(join13(".ocr", "sessions"));
|
|
24620
24738
|
if (isDirectChild && !dirPath.endsWith("sessions")) {
|
|
24621
24739
|
const newSession = basename7(dirPath);
|
|
24622
24740
|
currentSession = newSession;
|
|
@@ -24718,34 +24836,47 @@ function renderCombinedProgress(sessionPath, preservedStartTimes, ocrDir) {
|
|
|
24718
24836
|
}
|
|
24719
24837
|
|
|
24720
24838
|
// src/commands/state.ts
|
|
24721
|
-
import { existsSync as
|
|
24722
|
-
import { join as
|
|
24839
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6 } from "node:fs";
|
|
24840
|
+
import { join as join15 } from "node:path";
|
|
24723
24841
|
|
|
24724
24842
|
// src/lib/state/index.ts
|
|
24725
24843
|
init_db();
|
|
24726
24844
|
import {
|
|
24727
|
-
existsSync as
|
|
24728
|
-
mkdirSync as
|
|
24845
|
+
existsSync as existsSync12,
|
|
24846
|
+
mkdirSync as mkdirSync5,
|
|
24729
24847
|
readdirSync as readdirSync6,
|
|
24730
|
-
readFileSync as
|
|
24848
|
+
readFileSync as readFileSync10,
|
|
24731
24849
|
statSync as statSync2,
|
|
24732
|
-
writeFileSync as
|
|
24850
|
+
writeFileSync as writeFileSync8
|
|
24733
24851
|
} from "node:fs";
|
|
24734
|
-
import { join as
|
|
24852
|
+
import { join as join14 } from "node:path";
|
|
24853
|
+
function hasArtifacts(dir) {
|
|
24854
|
+
try {
|
|
24855
|
+
for (const entry of readdirSync6(dir, { withFileTypes: true })) {
|
|
24856
|
+
if (entry.isDirectory()) {
|
|
24857
|
+
if (hasArtifacts(join14(dir, entry.name))) return true;
|
|
24858
|
+
} else if (/\.(md|json)$/.test(entry.name)) {
|
|
24859
|
+
return true;
|
|
24860
|
+
}
|
|
24861
|
+
}
|
|
24862
|
+
} catch {
|
|
24863
|
+
}
|
|
24864
|
+
return false;
|
|
24865
|
+
}
|
|
24735
24866
|
async function stateInit(params) {
|
|
24736
24867
|
const { sessionId, branch, workflowType, sessionDir, ocrDir } = params;
|
|
24737
24868
|
const db = await ensureDatabase(ocrDir);
|
|
24738
|
-
const dbPath =
|
|
24869
|
+
const dbPath = join14(ocrDir, "data", "ocr.db");
|
|
24739
24870
|
const existing = getSession(db, sessionId);
|
|
24740
24871
|
if (existing) {
|
|
24741
|
-
const roundsDir =
|
|
24872
|
+
const roundsDir = join14(sessionDir, "rounds");
|
|
24742
24873
|
let nextRound = 1;
|
|
24743
|
-
if (
|
|
24874
|
+
if (existsSync12(roundsDir)) {
|
|
24744
24875
|
const roundDirs = readdirSync6(roundsDir).filter((d) => /^round-\d+$/.test(d)).map((d) => parseInt(d.replace("round-", ""), 10)).sort((a, b) => a - b);
|
|
24745
24876
|
if (roundDirs.length > 0) {
|
|
24746
24877
|
const highest = roundDirs[roundDirs.length - 1];
|
|
24747
|
-
const hasFinal =
|
|
24748
|
-
|
|
24878
|
+
const hasFinal = existsSync12(
|
|
24879
|
+
join14(roundsDir, `round-${highest}`, "final.md")
|
|
24749
24880
|
);
|
|
24750
24881
|
nextRound = hasFinal ? highest + 1 : highest;
|
|
24751
24882
|
}
|
|
@@ -24789,7 +24920,7 @@ async function stateInit(params) {
|
|
|
24789
24920
|
async function stateTransition(params) {
|
|
24790
24921
|
const { sessionId, phase, phaseNumber, round, mapRun, ocrDir } = params;
|
|
24791
24922
|
const db = await ensureDatabase(ocrDir);
|
|
24792
|
-
const dbPath =
|
|
24923
|
+
const dbPath = join14(ocrDir, "data", "ocr.db");
|
|
24793
24924
|
const existing = getSession(db, sessionId);
|
|
24794
24925
|
if (!existing) {
|
|
24795
24926
|
throw new Error(`Session not found: ${sessionId}`);
|
|
@@ -24822,7 +24953,7 @@ async function stateTransition(params) {
|
|
|
24822
24953
|
async function stateClose(params) {
|
|
24823
24954
|
const { sessionId, ocrDir } = params;
|
|
24824
24955
|
const db = await ensureDatabase(ocrDir);
|
|
24825
|
-
const dbPath =
|
|
24956
|
+
const dbPath = join14(ocrDir, "data", "ocr.db");
|
|
24826
24957
|
const existing = getSession(db, sessionId);
|
|
24827
24958
|
if (!existing) {
|
|
24828
24959
|
throw new Error(`Session not found: ${sessionId}`);
|
|
@@ -24889,10 +25020,10 @@ async function resolveActiveSession(ocrDir) {
|
|
|
24889
25020
|
}
|
|
24890
25021
|
function readJsonFromSource(params) {
|
|
24891
25022
|
if (params.source === "file") {
|
|
24892
|
-
if (!
|
|
25023
|
+
if (!existsSync12(params.filePath)) {
|
|
24893
25024
|
throw new Error(`File not found: ${params.filePath}`);
|
|
24894
25025
|
}
|
|
24895
|
-
return
|
|
25026
|
+
return readFileSync10(params.filePath, "utf-8");
|
|
24896
25027
|
}
|
|
24897
25028
|
return params.data;
|
|
24898
25029
|
}
|
|
@@ -25026,7 +25157,7 @@ function computeRoundCounts(meta) {
|
|
|
25026
25157
|
async function stateRoundComplete(params) {
|
|
25027
25158
|
const { ocrDir } = params;
|
|
25028
25159
|
const db = await ensureDatabase(ocrDir);
|
|
25029
|
-
const dbPath =
|
|
25160
|
+
const dbPath = join14(ocrDir, "data", "ocr.db");
|
|
25030
25161
|
const rawJsonString = readJsonFromSource(params);
|
|
25031
25162
|
const label = params.source === "file" ? params.filePath : "stdin";
|
|
25032
25163
|
const raw = parseRawJson(rawJsonString, label);
|
|
@@ -25036,10 +25167,10 @@ async function stateRoundComplete(params) {
|
|
|
25036
25167
|
const roundNumber = params.round ?? session.current_round;
|
|
25037
25168
|
let metaPath;
|
|
25038
25169
|
if (params.source === "stdin") {
|
|
25039
|
-
const roundDir =
|
|
25040
|
-
|
|
25041
|
-
metaPath =
|
|
25042
|
-
|
|
25170
|
+
const roundDir = join14(session.session_dir, "rounds", `round-${roundNumber}`);
|
|
25171
|
+
mkdirSync5(roundDir, { recursive: true });
|
|
25172
|
+
metaPath = join14(roundDir, "round-meta.json");
|
|
25173
|
+
writeFileSync8(metaPath, JSON.stringify(meta, null, 2));
|
|
25043
25174
|
}
|
|
25044
25175
|
insertEvent(db, {
|
|
25045
25176
|
session_id: session.id,
|
|
@@ -25120,7 +25251,7 @@ function computeMapCounts(meta) {
|
|
|
25120
25251
|
async function stateMapComplete(params) {
|
|
25121
25252
|
const { ocrDir } = params;
|
|
25122
25253
|
const db = await ensureDatabase(ocrDir);
|
|
25123
|
-
const dbPath =
|
|
25254
|
+
const dbPath = join14(ocrDir, "data", "ocr.db");
|
|
25124
25255
|
const rawJsonString = readJsonFromSource(params);
|
|
25125
25256
|
const label = params.source === "file" ? params.filePath : "stdin";
|
|
25126
25257
|
const raw = parseRawJson(rawJsonString, label);
|
|
@@ -25130,10 +25261,10 @@ async function stateMapComplete(params) {
|
|
|
25130
25261
|
const mapRunNumber = params.mapRun ?? session.current_map_run;
|
|
25131
25262
|
let metaPath;
|
|
25132
25263
|
if (params.source === "stdin") {
|
|
25133
|
-
const runDir =
|
|
25134
|
-
|
|
25135
|
-
metaPath =
|
|
25136
|
-
|
|
25264
|
+
const runDir = join14(session.session_dir, "map", "runs", `run-${mapRunNumber}`);
|
|
25265
|
+
mkdirSync5(runDir, { recursive: true });
|
|
25266
|
+
metaPath = join14(runDir, "map-meta.json");
|
|
25267
|
+
writeFileSync8(metaPath, JSON.stringify(meta, null, 2));
|
|
25137
25268
|
}
|
|
25138
25269
|
insertEvent(db, {
|
|
25139
25270
|
session_id: session.id,
|
|
@@ -25152,41 +25283,65 @@ async function stateMapComplete(params) {
|
|
|
25152
25283
|
}
|
|
25153
25284
|
async function stateSync(ocrDir) {
|
|
25154
25285
|
const db = await ensureDatabase(ocrDir);
|
|
25155
|
-
const dbPath =
|
|
25156
|
-
const sessionsRoot =
|
|
25157
|
-
if (!
|
|
25286
|
+
const dbPath = join14(ocrDir, "data", "ocr.db");
|
|
25287
|
+
const sessionsRoot = join14(ocrDir, "sessions");
|
|
25288
|
+
if (!existsSync12(sessionsRoot)) {
|
|
25158
25289
|
return 0;
|
|
25159
25290
|
}
|
|
25160
25291
|
const entries = readdirSync6(sessionsRoot).filter((name) => {
|
|
25161
|
-
const fullPath =
|
|
25292
|
+
const fullPath = join14(sessionsRoot, name);
|
|
25162
25293
|
return statSync2(fullPath).isDirectory();
|
|
25163
25294
|
});
|
|
25164
25295
|
let synced = 0;
|
|
25165
25296
|
for (const dirName of entries) {
|
|
25166
|
-
const dirPath =
|
|
25297
|
+
const dirPath = join14(sessionsRoot, dirName);
|
|
25167
25298
|
const existing = getSession(db, dirName);
|
|
25168
25299
|
if (existing) {
|
|
25169
25300
|
continue;
|
|
25170
25301
|
}
|
|
25171
|
-
|
|
25172
|
-
|
|
25302
|
+
if (!hasArtifacts(dirPath)) {
|
|
25303
|
+
continue;
|
|
25304
|
+
}
|
|
25305
|
+
const hasRoundsDir = existsSync12(join14(dirPath, "rounds"));
|
|
25306
|
+
const hasMapDir = existsSync12(join14(dirPath, "map"));
|
|
25173
25307
|
const workflowType = hasMapDir && !hasRoundsDir ? "map" : "review";
|
|
25174
25308
|
const branchMatch = dirName.match(/^\d{4}-\d{2}-\d{2}-(.+)$/);
|
|
25175
25309
|
const branch = branchMatch?.[1] ?? dirName;
|
|
25310
|
+
let inferredPhase = "context";
|
|
25311
|
+
if (workflowType === "review") {
|
|
25312
|
+
const roundsDir = join14(dirPath, "rounds");
|
|
25313
|
+
if (existsSync12(roundsDir)) {
|
|
25314
|
+
const roundDirs = readdirSync6(roundsDir).filter((d) => /^round-\d+$/.test(d)).sort((a, b) => parseInt(a.replace(/^\D+-/, ""), 10) - parseInt(b.replace(/^\D+-/, ""), 10));
|
|
25315
|
+
const latestRound = roundDirs[roundDirs.length - 1];
|
|
25316
|
+
if (latestRound && existsSync12(join14(roundsDir, latestRound, "final.md"))) {
|
|
25317
|
+
inferredPhase = "complete";
|
|
25318
|
+
}
|
|
25319
|
+
}
|
|
25320
|
+
} else if (workflowType === "map") {
|
|
25321
|
+
const runsDir = join14(dirPath, "map", "runs");
|
|
25322
|
+
if (existsSync12(runsDir)) {
|
|
25323
|
+
const runDirs = readdirSync6(runsDir).filter((d) => /^run-\d+$/.test(d)).sort((a, b) => parseInt(a.replace(/^\D+-/, ""), 10) - parseInt(b.replace(/^\D+-/, ""), 10));
|
|
25324
|
+
const latestRun = runDirs[runDirs.length - 1];
|
|
25325
|
+
if (latestRun && existsSync12(join14(runsDir, latestRun, "map.md"))) {
|
|
25326
|
+
inferredPhase = "complete";
|
|
25327
|
+
}
|
|
25328
|
+
}
|
|
25329
|
+
}
|
|
25176
25330
|
insertSession(db, {
|
|
25177
25331
|
id: dirName,
|
|
25178
25332
|
branch,
|
|
25179
25333
|
workflow_type: workflowType,
|
|
25180
|
-
current_phase:
|
|
25334
|
+
current_phase: inferredPhase,
|
|
25181
25335
|
phase_number: 1,
|
|
25182
25336
|
current_round: 1,
|
|
25183
25337
|
current_map_run: 1,
|
|
25184
25338
|
session_dir: dirPath
|
|
25185
25339
|
});
|
|
25340
|
+
updateSession(db, dirName, { status: "closed" });
|
|
25186
25341
|
insertEvent(db, {
|
|
25187
25342
|
session_id: dirName,
|
|
25188
25343
|
event_type: "session_synced",
|
|
25189
|
-
phase:
|
|
25344
|
+
phase: inferredPhase,
|
|
25190
25345
|
phase_number: 1,
|
|
25191
25346
|
metadata: JSON.stringify({ source: "filesystem_backfill" })
|
|
25192
25347
|
});
|
|
@@ -25199,6 +25354,8 @@ async function stateSync(ocrDir) {
|
|
|
25199
25354
|
}
|
|
25200
25355
|
|
|
25201
25356
|
// src/commands/state.ts
|
|
25357
|
+
init_command_log();
|
|
25358
|
+
init_db();
|
|
25202
25359
|
async function readStdin() {
|
|
25203
25360
|
const chunks = [];
|
|
25204
25361
|
for await (const chunk of process.stdin) {
|
|
@@ -25225,10 +25382,10 @@ var initSubcommand = new Command("init").description("Initialize a new OCR sessi
|
|
|
25225
25382
|
async (options) => {
|
|
25226
25383
|
const targetDir = process.cwd();
|
|
25227
25384
|
requireOcrSetup(targetDir);
|
|
25228
|
-
const ocrDir =
|
|
25229
|
-
const sessionDir = options.sessionDir ??
|
|
25230
|
-
if (!
|
|
25231
|
-
|
|
25385
|
+
const ocrDir = join15(targetDir, ".ocr");
|
|
25386
|
+
const sessionDir = options.sessionDir ?? join15(ocrDir, "sessions", options.sessionId);
|
|
25387
|
+
if (!existsSync13(sessionDir)) {
|
|
25388
|
+
mkdirSync6(sessionDir, { recursive: true });
|
|
25232
25389
|
}
|
|
25233
25390
|
try {
|
|
25234
25391
|
const sessionId = await stateInit({
|
|
@@ -25253,7 +25410,7 @@ var transitionSubcommand = new Command("transition").description("Transition ses
|
|
|
25253
25410
|
async (options) => {
|
|
25254
25411
|
const targetDir = process.cwd();
|
|
25255
25412
|
requireOcrSetup(targetDir);
|
|
25256
|
-
const ocrDir =
|
|
25413
|
+
const ocrDir = join15(targetDir, ".ocr");
|
|
25257
25414
|
const VALID_PHASES = /* @__PURE__ */ new Set([
|
|
25258
25415
|
"context",
|
|
25259
25416
|
"change-context",
|
|
@@ -25297,7 +25454,7 @@ var transitionSubcommand = new Command("transition").description("Transition ses
|
|
|
25297
25454
|
var closeSubcommand = new Command("close").description("Close a session").option("--session-id <id>", "Session ID (auto-detects latest active if omitted)").action(async (options) => {
|
|
25298
25455
|
const targetDir = process.cwd();
|
|
25299
25456
|
requireOcrSetup(targetDir);
|
|
25300
|
-
const ocrDir =
|
|
25457
|
+
const ocrDir = join15(targetDir, ".ocr");
|
|
25301
25458
|
try {
|
|
25302
25459
|
const sessionId = options.sessionId ?? (await resolveActiveSession(ocrDir)).id;
|
|
25303
25460
|
await stateClose({
|
|
@@ -25317,7 +25474,7 @@ var closeSubcommand = new Command("close").description("Close a session").option
|
|
|
25317
25474
|
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) => {
|
|
25318
25475
|
const targetDir = process.cwd();
|
|
25319
25476
|
requireOcrSetup(targetDir);
|
|
25320
|
-
const ocrDir =
|
|
25477
|
+
const ocrDir = join15(targetDir, ".ocr");
|
|
25321
25478
|
try {
|
|
25322
25479
|
const result = await stateShow(ocrDir, options.sessionId);
|
|
25323
25480
|
if (!result) {
|
|
@@ -25386,10 +25543,20 @@ var showSubcommand = new Command("show").description("Show current session state
|
|
|
25386
25543
|
var syncSubcommand = new Command("sync").description("Rebuild session state from filesystem artifacts").action(async () => {
|
|
25387
25544
|
const targetDir = process.cwd();
|
|
25388
25545
|
requireOcrSetup(targetDir);
|
|
25389
|
-
const ocrDir =
|
|
25546
|
+
const ocrDir = join15(targetDir, ".ocr");
|
|
25390
25547
|
try {
|
|
25391
25548
|
const synced = await stateSync(ocrDir);
|
|
25392
25549
|
console.log(`Synced ${synced} session${synced !== 1 ? "s" : ""} from filesystem.`);
|
|
25550
|
+
const db = await getDb(ocrDir);
|
|
25551
|
+
const countResult = db.exec("SELECT COUNT(*) as c FROM command_executions");
|
|
25552
|
+
const totalCmds = countResult[0]?.values[0]?.[0] ?? 0;
|
|
25553
|
+
if (totalCmds === 0) {
|
|
25554
|
+
const recovered = replayCommandLog(db, ocrDir);
|
|
25555
|
+
if (recovered > 0) {
|
|
25556
|
+
saveDatabase(db, join15(ocrDir, "data", "ocr.db"));
|
|
25557
|
+
console.log(`Recovered ${recovered} command${recovered !== 1 ? "s" : ""} from backup log.`);
|
|
25558
|
+
}
|
|
25559
|
+
}
|
|
25393
25560
|
} catch (error) {
|
|
25394
25561
|
console.error(
|
|
25395
25562
|
source_default.red(
|
|
@@ -25403,7 +25570,7 @@ var roundCompleteSubcommand = new Command("round-complete").description("Import
|
|
|
25403
25570
|
async (options) => {
|
|
25404
25571
|
const targetDir = process.cwd();
|
|
25405
25572
|
requireOcrSetup(targetDir);
|
|
25406
|
-
const ocrDir =
|
|
25573
|
+
const ocrDir = join15(targetDir, ".ocr");
|
|
25407
25574
|
if (!options.file && !options.stdin) {
|
|
25408
25575
|
console.error(source_default.red("Error: Provide either --file <path> or --stdin"));
|
|
25409
25576
|
process.exit(1);
|
|
@@ -25452,7 +25619,7 @@ var mapCompleteSubcommand = new Command("map-complete").description("Import stru
|
|
|
25452
25619
|
async (options) => {
|
|
25453
25620
|
const targetDir = process.cwd();
|
|
25454
25621
|
requireOcrSetup(targetDir);
|
|
25455
|
-
const ocrDir =
|
|
25622
|
+
const ocrDir = join15(targetDir, ".ocr");
|
|
25456
25623
|
if (!options.file && !options.stdin) {
|
|
25457
25624
|
console.error(source_default.red("Error: Provide either --file <path> or --stdin"));
|
|
25458
25625
|
process.exit(1);
|
|
@@ -25500,16 +25667,16 @@ var mapCompleteSubcommand = new Command("map-complete").description("Import stru
|
|
|
25500
25667
|
var stateCommand = new Command("state").description("Manage OCR session state").addCommand(initSubcommand).addCommand(transitionSubcommand).addCommand(closeSubcommand).addCommand(showSubcommand).addCommand(syncSubcommand).addCommand(roundCompleteSubcommand).addCommand(mapCompleteSubcommand);
|
|
25501
25668
|
|
|
25502
25669
|
// src/commands/update.ts
|
|
25503
|
-
import { existsSync as
|
|
25504
|
-
import { join as
|
|
25670
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
25671
|
+
import { join as join16 } from "node:path";
|
|
25505
25672
|
function detectConfiguredTools(targetDir) {
|
|
25506
25673
|
return AI_TOOLS.filter((tool) => {
|
|
25507
25674
|
if (tool.commandStrategy === "subdirectory") {
|
|
25508
|
-
const ocrDir =
|
|
25509
|
-
return
|
|
25675
|
+
const ocrDir = join16(targetDir, tool.commandsDir, "ocr");
|
|
25676
|
+
return existsSync14(ocrDir);
|
|
25510
25677
|
} else {
|
|
25511
|
-
const reviewCmd =
|
|
25512
|
-
return
|
|
25678
|
+
const reviewCmd = join16(targetDir, tool.commandsDir, "ocr-review.md");
|
|
25679
|
+
return existsSync14(reviewCmd);
|
|
25513
25680
|
}
|
|
25514
25681
|
});
|
|
25515
25682
|
}
|
|
@@ -25583,7 +25750,7 @@ var updateCommand = new Command("update").description("Update OCR assets after p
|
|
|
25583
25750
|
const result = installForTool(tool, targetDir);
|
|
25584
25751
|
results.push(result);
|
|
25585
25752
|
}
|
|
25586
|
-
ensureGitignore(
|
|
25753
|
+
ensureGitignore(join16(targetDir, ".ocr"));
|
|
25587
25754
|
spinner.stop();
|
|
25588
25755
|
const successful = results.filter((r) => r.success);
|
|
25589
25756
|
const failed = results.filter((r) => !r.success);
|
|
@@ -25619,10 +25786,10 @@ var updateCommand = new Command("update").description("Update OCR assets after p
|
|
|
25619
25786
|
if (updateInject) {
|
|
25620
25787
|
if (options.dryRun) {
|
|
25621
25788
|
console.log(source_default.dim(" Would update:"));
|
|
25622
|
-
if (
|
|
25789
|
+
if (existsSync14(join16(targetDir, "AGENTS.md"))) {
|
|
25623
25790
|
console.log(source_default.dim(" \u2022 AGENTS.md (OCR managed block)"));
|
|
25624
25791
|
}
|
|
25625
|
-
if (
|
|
25792
|
+
if (existsSync14(join16(targetDir, "CLAUDE.md"))) {
|
|
25626
25793
|
console.log(source_default.dim(" \u2022 CLAUDE.md (OCR managed block)"));
|
|
25627
25794
|
}
|
|
25628
25795
|
console.log();
|
|
@@ -25654,14 +25821,14 @@ var updateCommand = new Command("update").description("Update OCR assets after p
|
|
|
25654
25821
|
});
|
|
25655
25822
|
|
|
25656
25823
|
// src/commands/dashboard.ts
|
|
25657
|
-
import { existsSync as
|
|
25658
|
-
import { join as
|
|
25824
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
25825
|
+
import { join as join17, dirname as dirname6 } from "node:path";
|
|
25659
25826
|
import { fileURLToPath } from "node:url";
|
|
25660
25827
|
init_db();
|
|
25661
25828
|
var __filename = fileURLToPath(import.meta.url);
|
|
25662
|
-
var __dirname =
|
|
25829
|
+
var __dirname = dirname6(__filename);
|
|
25663
25830
|
function resolveServerPath() {
|
|
25664
|
-
return
|
|
25831
|
+
return join17(__dirname, "dashboard", "server.js");
|
|
25665
25832
|
}
|
|
25666
25833
|
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(
|
|
25667
25834
|
async (options) => {
|
|
@@ -25672,7 +25839,7 @@ var dashboardCommand = new Command("dashboard").description("Start the OCR dashb
|
|
|
25672
25839
|
console.error(source_default.red(`Error: Invalid port "${options.port}". Must be 1-65535.`));
|
|
25673
25840
|
process.exit(1);
|
|
25674
25841
|
}
|
|
25675
|
-
const ocrDir =
|
|
25842
|
+
const ocrDir = join17(targetDir, ".ocr");
|
|
25676
25843
|
try {
|
|
25677
25844
|
await ensureDatabase(ocrDir);
|
|
25678
25845
|
closeAllDatabases();
|
|
@@ -25686,7 +25853,7 @@ var dashboardCommand = new Command("dashboard").description("Start the OCR dashb
|
|
|
25686
25853
|
process.exit(1);
|
|
25687
25854
|
}
|
|
25688
25855
|
const serverPath = resolveServerPath();
|
|
25689
|
-
if (!
|
|
25856
|
+
if (!existsSync15(serverPath)) {
|
|
25690
25857
|
console.error(source_default.red("Error: Dashboard server bundle not found."));
|
|
25691
25858
|
console.error(
|
|
25692
25859
|
source_default.dim(` Expected at: ${serverPath}`)
|
|
@@ -25720,8 +25887,8 @@ var dashboardCommand = new Command("dashboard").description("Start the OCR dashb
|
|
|
25720
25887
|
);
|
|
25721
25888
|
|
|
25722
25889
|
// src/commands/doctor.ts
|
|
25723
|
-
import { existsSync as
|
|
25724
|
-
import { join as
|
|
25890
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
25891
|
+
import { join as join18 } from "node:path";
|
|
25725
25892
|
var doctorCommand = new Command("doctor").description("Check OCR installation and verify all dependencies").action(() => {
|
|
25726
25893
|
printHeader();
|
|
25727
25894
|
const targetDir = process.cwd();
|
|
@@ -25735,10 +25902,10 @@ var doctorCommand = new Command("doctor").description("Check OCR installation an
|
|
|
25735
25902
|
console.log(source_default.bold(" OCR Installation"));
|
|
25736
25903
|
console.log();
|
|
25737
25904
|
const ocrStatus = checkOcrSetup(targetDir);
|
|
25738
|
-
const configPath =
|
|
25739
|
-
const dbPath =
|
|
25740
|
-
const hasConfig =
|
|
25741
|
-
const hasDb =
|
|
25905
|
+
const configPath = join18(targetDir, ".ocr", "config.yaml");
|
|
25906
|
+
const dbPath = join18(targetDir, ".ocr", "data", "ocr.db");
|
|
25907
|
+
const hasConfig = existsSync16(configPath);
|
|
25908
|
+
const hasDb = existsSync16(dbPath);
|
|
25742
25909
|
const ocrChecks = [
|
|
25743
25910
|
{ label: ".ocr/skills/", ok: ocrStatus.hasSkills },
|
|
25744
25911
|
{ label: ".ocr/sessions/", ok: ocrStatus.hasSessions },
|
|
@@ -25812,8 +25979,8 @@ var doctorCommand = new Command("doctor").description("Check OCR installation an
|
|
|
25812
25979
|
});
|
|
25813
25980
|
|
|
25814
25981
|
// src/commands/reviewers.ts
|
|
25815
|
-
import { writeFileSync as
|
|
25816
|
-
import { join as
|
|
25982
|
+
import { writeFileSync as writeFileSync9, renameSync as renameSync3 } from "node:fs";
|
|
25983
|
+
import { join as join19 } from "node:path";
|
|
25817
25984
|
async function readStdin2() {
|
|
25818
25985
|
const chunks = [];
|
|
25819
25986
|
for await (const chunk of process.stdin) {
|
|
@@ -25876,20 +26043,20 @@ function validateReviewersMeta(data) {
|
|
|
25876
26043
|
var syncSubcommand2 = new Command("sync").description("Sync reviewers-meta.json from reviewer markdown files or structured JSON").option("--stdin", "Read reviewers JSON from stdin (for AI-invoked sync)").action(async (options) => {
|
|
25877
26044
|
const targetDir = process.cwd();
|
|
25878
26045
|
requireOcrSetup(targetDir);
|
|
25879
|
-
const ocrDir =
|
|
26046
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
25880
26047
|
if (!options.stdin) {
|
|
25881
26048
|
try {
|
|
25882
|
-
const reviewersDir =
|
|
25883
|
-
const configPath =
|
|
26049
|
+
const reviewersDir = join19(ocrDir, "skills", "references", "reviewers");
|
|
26050
|
+
const configPath = join19(ocrDir, "config.yaml");
|
|
25884
26051
|
const meta = generateReviewersMeta(reviewersDir, configPath);
|
|
25885
26052
|
if (!meta || meta.reviewers.length === 0) {
|
|
25886
26053
|
console.error(source_default.yellow("No reviewer files found in .ocr/skills/references/reviewers/"));
|
|
25887
26054
|
process.exit(1);
|
|
25888
26055
|
}
|
|
25889
|
-
const metaPath =
|
|
26056
|
+
const metaPath = join19(ocrDir, "reviewers-meta.json");
|
|
25890
26057
|
const tmpPath = metaPath + ".tmp";
|
|
25891
|
-
|
|
25892
|
-
|
|
26058
|
+
writeFileSync9(tmpPath, JSON.stringify(meta, null, 2) + "\n");
|
|
26059
|
+
renameSync3(tmpPath, metaPath);
|
|
25893
26060
|
const tierCounts = meta.reviewers.reduce(
|
|
25894
26061
|
(acc, r) => {
|
|
25895
26062
|
acc[r.tier] = (acc[r.tier] ?? 0) + 1;
|
|
@@ -25916,10 +26083,10 @@ var syncSubcommand2 = new Command("sync").description("Sync reviewers-meta.json
|
|
|
25916
26083
|
throw new Error("Invalid JSON on stdin");
|
|
25917
26084
|
}
|
|
25918
26085
|
const meta = validateReviewersMeta(parsed);
|
|
25919
|
-
const metaPath =
|
|
26086
|
+
const metaPath = join19(ocrDir, "reviewers-meta.json");
|
|
25920
26087
|
const tmpPath = metaPath + ".tmp";
|
|
25921
|
-
|
|
25922
|
-
|
|
26088
|
+
writeFileSync9(tmpPath, JSON.stringify(meta, null, 2) + "\n");
|
|
26089
|
+
renameSync3(tmpPath, metaPath);
|
|
25923
26090
|
const tierCounts = meta.reviewers.reduce(
|
|
25924
26091
|
(acc, r) => {
|
|
25925
26092
|
acc[r.tier] = (acc[r.tier] ?? 0) + 1;
|
|
@@ -25944,25 +26111,25 @@ var reviewersCommand = new Command("reviewers").description("Manage OCR reviewer
|
|
|
25944
26111
|
|
|
25945
26112
|
// src/lib/update-check.ts
|
|
25946
26113
|
import { homedir } from "node:os";
|
|
25947
|
-
import { join as
|
|
25948
|
-
import { readFileSync as
|
|
26114
|
+
import { join as join20 } from "node:path";
|
|
26115
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync10, mkdirSync as mkdirSync7 } from "node:fs";
|
|
25949
26116
|
var PACKAGE_NAME = "@open-code-review/cli";
|
|
25950
26117
|
var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
25951
|
-
var
|
|
25952
|
-
var CACHE_FILE =
|
|
26118
|
+
var CACHE_DIR2 = join20(homedir(), ".ocr");
|
|
26119
|
+
var CACHE_FILE = join20(CACHE_DIR2, "update-check.json");
|
|
25953
26120
|
var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
|
|
25954
26121
|
var FETCH_TIMEOUT_MS = 3e3;
|
|
25955
26122
|
function readCache(cacheFile) {
|
|
25956
26123
|
try {
|
|
25957
|
-
return JSON.parse(
|
|
26124
|
+
return JSON.parse(readFileSync11(cacheFile, "utf-8"));
|
|
25958
26125
|
} catch {
|
|
25959
26126
|
return null;
|
|
25960
26127
|
}
|
|
25961
26128
|
}
|
|
25962
26129
|
function writeCache(cacheFile, cache) {
|
|
25963
26130
|
try {
|
|
25964
|
-
|
|
25965
|
-
|
|
26131
|
+
mkdirSync7(join20(cacheFile, ".."), { recursive: true });
|
|
26132
|
+
writeFileSync10(cacheFile, JSON.stringify(cache));
|
|
25966
26133
|
} catch {
|
|
25967
26134
|
}
|
|
25968
26135
|
}
|
|
@@ -25982,7 +26149,7 @@ async function checkForUpdate(currentVersion, options) {
|
|
|
25982
26149
|
if (process.env.CI || process.env.OCR_NO_UPDATE_CHECK) {
|
|
25983
26150
|
return null;
|
|
25984
26151
|
}
|
|
25985
|
-
const cacheFile =
|
|
26152
|
+
const cacheFile = join20(options?.cacheDir ?? CACHE_DIR2, "update-check.json");
|
|
25986
26153
|
try {
|
|
25987
26154
|
const cache = readCache(cacheFile);
|
|
25988
26155
|
if (cache && Date.now() - cache.lastCheck < CHECK_INTERVAL_MS) {
|