@open-code-review/cli 1.5.1 → 1.6.0
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/README.md +57 -127
- package/dist/dashboard/client/assets/{_basePickBy-BJKCdvle.js → _basePickBy-BGuMbEDR.js} +1 -1
- package/dist/dashboard/client/assets/{_baseUniq-L_sxIO0r.js → _baseUniq-Bx8loabg.js} +1 -1
- package/dist/dashboard/client/assets/{arc-tqAEcLt5.js → arc-DUgpt7nY.js} +1 -1
- package/dist/dashboard/client/assets/{architectureDiagram-VXUJARFQ-CrKQo6Ye.js → architectureDiagram-VXUJARFQ-D25nt6Xz.js} +1 -1
- package/dist/dashboard/client/assets/{blockDiagram-VD42YOAC-DXOc89nw.js → blockDiagram-VD42YOAC-D8PUF3h4.js} +1 -1
- package/dist/dashboard/client/assets/{c4Diagram-YG6GDRKO-Ba-jYbw0.js → c4Diagram-YG6GDRKO-lorsCz-I.js} +1 -1
- package/dist/dashboard/client/assets/channel-yW2sWou_.js +1 -0
- package/dist/dashboard/client/assets/{chunk-4BX2VUAB-D1G3HCqL.js → chunk-4BX2VUAB-8lVyfRJM.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-55IACEB6-FI7g4AjR.js → chunk-55IACEB6-C4SjgsZO.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-B4BG7PRW-DhEGFGWs.js → chunk-B4BG7PRW-BXzTPbH1.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-DI55MBZ5-Da3-6ZE4.js → chunk-DI55MBZ5-Bp7QllDt.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-FMBD7UC4-D0QLOjiy.js → chunk-FMBD7UC4-B4g9S67N.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-QN33PNHL-WkfgpbLo.js → chunk-QN33PNHL-Dyk7Hc0J.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-QZHKN3VN-Bqn0IO1w.js → chunk-QZHKN3VN-DTvkGdnm.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-TZMSLE5B-CC_K_BeL.js → chunk-TZMSLE5B-BAeZLvrI.js} +1 -1
- package/dist/dashboard/client/assets/classDiagram-2ON5EDUG-1pMX5UXO.js +1 -0
- package/dist/dashboard/client/assets/classDiagram-v2-WZHVMYZB-1pMX5UXO.js +1 -0
- package/dist/dashboard/client/assets/clone-DQwdw3YR.js +1 -0
- package/dist/dashboard/client/assets/{cose-bilkent-S5V4N54A-D8urqxIF.js → cose-bilkent-S5V4N54A--6-kzrdu.js} +1 -1
- package/dist/dashboard/client/assets/{dagre-6UL2VRFP-w2xS0ztU.js → dagre-6UL2VRFP-D10_QE2P.js} +1 -1
- package/dist/dashboard/client/assets/{diagram-PSM6KHXK-DlOtv6zO.js → diagram-PSM6KHXK-kS1x75Bl.js} +1 -1
- package/dist/dashboard/client/assets/{diagram-QEK2KX5R-EpxsVLZY.js → diagram-QEK2KX5R-D_LLCPas.js} +1 -1
- package/dist/dashboard/client/assets/{diagram-S2PKOQOG-kmITzl42.js → diagram-S2PKOQOG-Duy1t5UO.js} +1 -1
- package/dist/dashboard/client/assets/{erDiagram-Q2GNP2WA-Bvyepu_Z.js → erDiagram-Q2GNP2WA-DyQXwzLf.js} +1 -1
- package/dist/dashboard/client/assets/{flowDiagram-NV44I4VS-BokLAZN0.js → flowDiagram-NV44I4VS-D9U11XVw.js} +1 -1
- package/dist/dashboard/client/assets/{ganttDiagram-JELNMOA3-i5ZSGuTN.js → ganttDiagram-JELNMOA3-STy-TC-3.js} +1 -1
- package/dist/dashboard/client/assets/{gitGraphDiagram-V2S2FVAM-CIayQ8P9.js → gitGraphDiagram-V2S2FVAM-B04PgURg.js} +1 -1
- package/dist/dashboard/client/assets/{graph-C3ouLF2F.js → graph-AiGwnT5H.js} +1 -1
- package/dist/dashboard/client/assets/{index-icxlpW-l.js → index-BzQ3i_QR.js} +109 -107
- package/dist/dashboard/client/assets/index-CGGYXSm-.css +1 -0
- package/dist/dashboard/client/assets/{infoDiagram-HS3SLOUP-wxe8NO00.js → infoDiagram-HS3SLOUP-D4arwl6T.js} +1 -1
- package/dist/dashboard/client/assets/{journeyDiagram-XKPGCS4Q-BeHCbOFN.js → journeyDiagram-XKPGCS4Q-CsKqlKkf.js} +1 -1
- package/dist/dashboard/client/assets/{kanban-definition-3W4ZIXB7-DxUlb4wo.js → kanban-definition-3W4ZIXB7-CUFnzQE3.js} +1 -1
- package/dist/dashboard/client/assets/{layout-CYsQ5kjv.js → layout-BvvYJVPv.js} +1 -1
- package/dist/dashboard/client/assets/{linear-ByuMiLUn.js → linear-BiBJkzyE.js} +1 -1
- package/dist/dashboard/client/assets/{mermaid-renderer-cx-n1jFM.js → mermaid-renderer-DGUmIWXY.js} +4 -4
- package/dist/dashboard/client/assets/{mindmap-definition-VGOIOE7T-CI5zvW3G.js → mindmap-definition-VGOIOE7T-D-Kc9Xgu.js} +1 -1
- package/dist/dashboard/client/assets/{pieDiagram-ADFJNKIX-lC7QV-4L.js → pieDiagram-ADFJNKIX-CooPKLnX.js} +1 -1
- package/dist/dashboard/client/assets/{quadrantDiagram-AYHSOK5B-DI7Bn_fF.js → quadrantDiagram-AYHSOK5B-3soPtaSQ.js} +1 -1
- package/dist/dashboard/client/assets/{requirementDiagram-UZGBJVZJ-BVuFGUp6.js → requirementDiagram-UZGBJVZJ-rE40t0IG.js} +1 -1
- package/dist/dashboard/client/assets/{sankeyDiagram-TZEHDZUN-C-3hBPRk.js → sankeyDiagram-TZEHDZUN-CrgDF_jW.js} +1 -1
- package/dist/dashboard/client/assets/{sequenceDiagram-WL72ISMW-CLS6xCbv.js → sequenceDiagram-WL72ISMW-B628IlDW.js} +1 -1
- package/dist/dashboard/client/assets/{stateDiagram-FKZM4ZOC-XOLrkoEE.js → stateDiagram-FKZM4ZOC-C4yb7S9D.js} +1 -1
- package/dist/dashboard/client/assets/stateDiagram-v2-4FDKWEC3-BoFeOfLI.js +1 -0
- package/dist/dashboard/client/assets/{timeline-definition-IT6M3QCI-N9m6IkH5.js → timeline-definition-IT6M3QCI-5uLN4f_J.js} +1 -1
- package/dist/dashboard/client/assets/{treemap-GDKQZRPO-ayvdfxB1.js → treemap-GDKQZRPO-BHXME3bw.js} +1 -1
- package/dist/dashboard/client/assets/{xychartDiagram-PRI3JC2R-CUmVEVIH.js → xychartDiagram-PRI3JC2R-BYTod6eI.js} +1 -1
- package/dist/dashboard/client/index.html +2 -2
- package/dist/dashboard/server.js +532 -58
- package/dist/index.js +523 -15
- package/dist/lib/db/index.js +522 -0
- package/package.json +2 -2
- package/dist/dashboard/client/assets/channel-OmrThJE3.js +0 -1
- package/dist/dashboard/client/assets/classDiagram-2ON5EDUG-Dg5ffKNR.js +0 -1
- package/dist/dashboard/client/assets/classDiagram-v2-WZHVMYZB-Dg5ffKNR.js +0 -1
- package/dist/dashboard/client/assets/clone-CKI4Qu1i.js +0 -1
- package/dist/dashboard/client/assets/index-CPEavIIM.css +0 -1
- package/dist/dashboard/client/assets/stateDiagram-v2-4FDKWEC3-Cy33HZ1p.js +0 -1
package/dist/index.js
CHANGED
|
@@ -2157,7 +2157,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2157
2157
|
*
|
|
2158
2158
|
* @private
|
|
2159
2159
|
*/
|
|
2160
|
-
_executeSubCommand(
|
|
2160
|
+
_executeSubCommand(subcommand2, args) {
|
|
2161
2161
|
args = args.slice();
|
|
2162
2162
|
let launchWithNode = false;
|
|
2163
2163
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
@@ -2173,7 +2173,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2173
2173
|
}
|
|
2174
2174
|
this._checkForMissingMandatoryOptions();
|
|
2175
2175
|
this._checkForConflictingOptions();
|
|
2176
|
-
let executableFile =
|
|
2176
|
+
let executableFile = subcommand2._executableFile || `${this._name}-${subcommand2._name}`;
|
|
2177
2177
|
let executableDir = this._executableDir || "";
|
|
2178
2178
|
if (this._scriptPath) {
|
|
2179
2179
|
let resolvedScriptPath;
|
|
@@ -2189,7 +2189,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2189
2189
|
}
|
|
2190
2190
|
if (executableDir) {
|
|
2191
2191
|
let localFile = findFile(executableDir, executableFile);
|
|
2192
|
-
if (!localFile && !
|
|
2192
|
+
if (!localFile && !subcommand2._executableFile && this._scriptPath) {
|
|
2193
2193
|
const legacyName = path2.basename(
|
|
2194
2194
|
this._scriptPath,
|
|
2195
2195
|
path2.extname(this._scriptPath)
|
|
@@ -2197,7 +2197,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2197
2197
|
if (legacyName !== this._name) {
|
|
2198
2198
|
localFile = findFile(
|
|
2199
2199
|
executableDir,
|
|
2200
|
-
`${legacyName}-${
|
|
2200
|
+
`${legacyName}-${subcommand2._name}`
|
|
2201
2201
|
);
|
|
2202
2202
|
}
|
|
2203
2203
|
}
|
|
@@ -2217,7 +2217,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2217
2217
|
this._checkForMissingExecutable(
|
|
2218
2218
|
executableFile,
|
|
2219
2219
|
executableDir,
|
|
2220
|
-
|
|
2220
|
+
subcommand2._name
|
|
2221
2221
|
);
|
|
2222
2222
|
args.unshift(executableFile);
|
|
2223
2223
|
args = incrementNodeInspectorPort(process13.execArgv).concat(args);
|
|
@@ -2253,7 +2253,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2253
2253
|
this._checkForMissingExecutable(
|
|
2254
2254
|
executableFile,
|
|
2255
2255
|
executableDir,
|
|
2256
|
-
|
|
2256
|
+
subcommand2._name
|
|
2257
2257
|
);
|
|
2258
2258
|
} else if (err.code === "EACCES") {
|
|
2259
2259
|
throw new Error(`'${executableFile}' not executable`);
|
|
@@ -16283,6 +16283,30 @@ var init_migrations = __esm({
|
|
|
16283
16283
|
ALTER TABLE orchestration_events_new RENAME TO orchestration_events;
|
|
16284
16284
|
CREATE INDEX idx_events_session ON orchestration_events(session_id);
|
|
16285
16285
|
CREATE INDEX idx_events_type ON orchestration_events(event_type);
|
|
16286
|
+
`
|
|
16287
|
+
},
|
|
16288
|
+
{
|
|
16289
|
+
version: 6,
|
|
16290
|
+
description: "Add orchestrator-first columns to review_rounds for round-meta.json support",
|
|
16291
|
+
sql: `
|
|
16292
|
+
ALTER TABLE review_rounds ADD COLUMN source TEXT DEFAULT NULL;
|
|
16293
|
+
ALTER TABLE review_rounds ADD COLUMN reviewer_count INTEGER DEFAULT 0;
|
|
16294
|
+
ALTER TABLE review_rounds ADD COLUMN total_finding_count INTEGER DEFAULT 0;
|
|
16295
|
+
`
|
|
16296
|
+
},
|
|
16297
|
+
{
|
|
16298
|
+
version: 7,
|
|
16299
|
+
description: "Add category column to review_findings for blocker/should_fix/suggestion classification",
|
|
16300
|
+
sql: `
|
|
16301
|
+
ALTER TABLE review_findings ADD COLUMN category TEXT DEFAULT NULL;
|
|
16302
|
+
`
|
|
16303
|
+
},
|
|
16304
|
+
{
|
|
16305
|
+
version: 8,
|
|
16306
|
+
description: "Add orchestrator-first columns to map_runs for map-meta.json support",
|
|
16307
|
+
sql: `
|
|
16308
|
+
ALTER TABLE map_runs ADD COLUMN source TEXT DEFAULT NULL;
|
|
16309
|
+
ALTER TABLE map_runs ADD COLUMN section_count INTEGER DEFAULT 0;
|
|
16286
16310
|
`
|
|
16287
16311
|
}
|
|
16288
16312
|
];
|
|
@@ -20187,21 +20211,30 @@ import { join } from "node:path";
|
|
|
20187
20211
|
var START_MARKER = "# OCR:START \u2014 managed by open-code-review (do not edit this block)";
|
|
20188
20212
|
var END_MARKER = "# OCR:END";
|
|
20189
20213
|
var MANAGED_ENTRIES = ["sessions/", "data/", "*.db-shm", "*.db-wal"];
|
|
20214
|
+
var LEGACY_LINES = /* @__PURE__ */ new Set([
|
|
20215
|
+
"# OCR session files",
|
|
20216
|
+
"sessions/",
|
|
20217
|
+
"data",
|
|
20218
|
+
"data/"
|
|
20219
|
+
]);
|
|
20190
20220
|
function buildManagedBlock() {
|
|
20191
20221
|
return [START_MARKER, ...MANAGED_ENTRIES, END_MARKER].join("\n");
|
|
20192
20222
|
}
|
|
20193
20223
|
function escapeRegex(str) {
|
|
20194
20224
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
20195
20225
|
}
|
|
20226
|
+
function stripLegacyLines(content) {
|
|
20227
|
+
return content.split("\n").filter((line) => !LEGACY_LINES.has(line.trim())).join("\n");
|
|
20228
|
+
}
|
|
20196
20229
|
function ensureGitignore(ocrDir) {
|
|
20197
20230
|
const gitignorePath = join(ocrDir, ".gitignore");
|
|
20198
20231
|
const block = buildManagedBlock();
|
|
20199
20232
|
let content = existsSync(gitignorePath) ? readFileSync2(gitignorePath, "utf-8") : "";
|
|
20200
|
-
const
|
|
20233
|
+
const blockRegex = new RegExp(
|
|
20201
20234
|
`${escapeRegex(START_MARKER)}[\\s\\S]*?${escapeRegex(END_MARKER)}\\n?`,
|
|
20202
20235
|
"g"
|
|
20203
20236
|
);
|
|
20204
|
-
if (
|
|
20237
|
+
if (blockRegex.test(content)) {
|
|
20205
20238
|
content = content.replace(
|
|
20206
20239
|
new RegExp(
|
|
20207
20240
|
`${escapeRegex(START_MARKER)}[\\s\\S]*?${escapeRegex(END_MARKER)}\\n?`,
|
|
@@ -20210,7 +20243,7 @@ function ensureGitignore(ocrDir) {
|
|
|
20210
20243
|
block + "\n"
|
|
20211
20244
|
);
|
|
20212
20245
|
} else {
|
|
20213
|
-
content = content.trimEnd();
|
|
20246
|
+
content = stripLegacyLines(content).trimEnd();
|
|
20214
20247
|
if (content.length > 0) {
|
|
20215
20248
|
content += "\n\n";
|
|
20216
20249
|
}
|
|
@@ -24507,12 +24540,19 @@ function renderCombinedProgress(sessionPath, preservedStartTimes, ocrDir) {
|
|
|
24507
24540
|
}
|
|
24508
24541
|
|
|
24509
24542
|
// src/commands/state.ts
|
|
24510
|
-
import { existsSync as existsSync12, mkdirSync as
|
|
24543
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync5 } from "node:fs";
|
|
24511
24544
|
import { join as join14 } from "node:path";
|
|
24512
24545
|
|
|
24513
24546
|
// src/lib/state/index.ts
|
|
24514
24547
|
init_db();
|
|
24515
|
-
import {
|
|
24548
|
+
import {
|
|
24549
|
+
existsSync as existsSync11,
|
|
24550
|
+
mkdirSync as mkdirSync4,
|
|
24551
|
+
readdirSync as readdirSync6,
|
|
24552
|
+
readFileSync as readFileSync9,
|
|
24553
|
+
statSync as statSync2,
|
|
24554
|
+
writeFileSync as writeFileSync7
|
|
24555
|
+
} from "node:fs";
|
|
24516
24556
|
import { join as join13 } from "node:path";
|
|
24517
24557
|
async function stateInit(params) {
|
|
24518
24558
|
const { sessionId, branch, workflowType, sessionDir, ocrDir } = params;
|
|
@@ -24669,6 +24709,253 @@ async function resolveActiveSession(ocrDir) {
|
|
|
24669
24709
|
sessionDir: session.session_dir
|
|
24670
24710
|
};
|
|
24671
24711
|
}
|
|
24712
|
+
function readJsonFromSource(params) {
|
|
24713
|
+
if (params.source === "file") {
|
|
24714
|
+
if (!existsSync11(params.filePath)) {
|
|
24715
|
+
throw new Error(`File not found: ${params.filePath}`);
|
|
24716
|
+
}
|
|
24717
|
+
return readFileSync9(params.filePath, "utf-8");
|
|
24718
|
+
}
|
|
24719
|
+
return params.data;
|
|
24720
|
+
}
|
|
24721
|
+
function parseRawJson(raw, label) {
|
|
24722
|
+
try {
|
|
24723
|
+
return JSON.parse(raw);
|
|
24724
|
+
} catch (err) {
|
|
24725
|
+
throw new Error(
|
|
24726
|
+
`Failed to parse ${label}: ${err instanceof Error ? err.message : "invalid JSON"}`
|
|
24727
|
+
);
|
|
24728
|
+
}
|
|
24729
|
+
}
|
|
24730
|
+
function resolveSessionForCompletion(db, explicitId) {
|
|
24731
|
+
if (explicitId) {
|
|
24732
|
+
const existing = getSession(db, explicitId);
|
|
24733
|
+
if (!existing) throw new Error(`Session not found: ${explicitId}`);
|
|
24734
|
+
return {
|
|
24735
|
+
id: existing.id,
|
|
24736
|
+
session_dir: existing.session_dir,
|
|
24737
|
+
current_round: existing.current_round,
|
|
24738
|
+
current_map_run: existing.current_map_run
|
|
24739
|
+
};
|
|
24740
|
+
}
|
|
24741
|
+
const active = getLatestActiveSession(db);
|
|
24742
|
+
if (!active) throw new Error("No active session found");
|
|
24743
|
+
return {
|
|
24744
|
+
id: active.id,
|
|
24745
|
+
session_dir: active.session_dir,
|
|
24746
|
+
current_round: active.current_round,
|
|
24747
|
+
current_map_run: active.current_map_run
|
|
24748
|
+
};
|
|
24749
|
+
}
|
|
24750
|
+
var VALID_CATEGORIES = /* @__PURE__ */ new Set(["blocker", "should_fix", "suggestion", "style"]);
|
|
24751
|
+
var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "high", "medium", "low", "info"]);
|
|
24752
|
+
function validateRoundMeta(meta) {
|
|
24753
|
+
if (!meta || typeof meta !== "object") {
|
|
24754
|
+
throw new Error("round-meta.json must be a JSON object");
|
|
24755
|
+
}
|
|
24756
|
+
const obj = meta;
|
|
24757
|
+
if (obj.schema_version !== 1) {
|
|
24758
|
+
throw new Error(
|
|
24759
|
+
`Unsupported schema_version: ${String(obj.schema_version)}. Expected 1.`
|
|
24760
|
+
);
|
|
24761
|
+
}
|
|
24762
|
+
if (typeof obj.verdict !== "string" || obj.verdict.trim().length === 0) {
|
|
24763
|
+
throw new Error("round-meta.json must contain a non-empty verdict string");
|
|
24764
|
+
}
|
|
24765
|
+
if (!Array.isArray(obj.reviewers)) {
|
|
24766
|
+
throw new Error("round-meta.json must contain a reviewers array");
|
|
24767
|
+
}
|
|
24768
|
+
for (const reviewer of obj.reviewers) {
|
|
24769
|
+
if (!reviewer || typeof reviewer !== "object") {
|
|
24770
|
+
throw new Error("Each reviewer must be an object");
|
|
24771
|
+
}
|
|
24772
|
+
const r = reviewer;
|
|
24773
|
+
if (typeof r.type !== "string") {
|
|
24774
|
+
throw new Error("Each reviewer must have a type string");
|
|
24775
|
+
}
|
|
24776
|
+
if (typeof r.instance !== "number") {
|
|
24777
|
+
throw new Error("Each reviewer must have an instance number");
|
|
24778
|
+
}
|
|
24779
|
+
if (!Array.isArray(r.findings)) {
|
|
24780
|
+
throw new Error(`Reviewer ${r.type}-${r.instance} must have a findings array`);
|
|
24781
|
+
}
|
|
24782
|
+
for (const finding of r.findings) {
|
|
24783
|
+
if (!finding || typeof finding !== "object") {
|
|
24784
|
+
throw new Error("Each finding must be an object");
|
|
24785
|
+
}
|
|
24786
|
+
const f = finding;
|
|
24787
|
+
if (typeof f.title !== "string" || f.title.trim().length === 0) {
|
|
24788
|
+
throw new Error("Each finding must have a non-empty title");
|
|
24789
|
+
}
|
|
24790
|
+
if (typeof f.category !== "string" || !VALID_CATEGORIES.has(f.category)) {
|
|
24791
|
+
throw new Error(
|
|
24792
|
+
`Finding "${f.title}" has invalid category: "${String(f.category)}". Must be one of: ${[...VALID_CATEGORIES].join(", ")}`
|
|
24793
|
+
);
|
|
24794
|
+
}
|
|
24795
|
+
if (typeof f.severity !== "string" || !VALID_SEVERITIES.has(f.severity)) {
|
|
24796
|
+
throw new Error(
|
|
24797
|
+
`Finding "${f.title}" has invalid severity: "${String(f.severity)}". Must be one of: ${[...VALID_SEVERITIES].join(", ")}`
|
|
24798
|
+
);
|
|
24799
|
+
}
|
|
24800
|
+
if (typeof f.summary !== "string") {
|
|
24801
|
+
throw new Error(`Finding "${f.title}" must have a summary string`);
|
|
24802
|
+
}
|
|
24803
|
+
if (f.file_path !== void 0 && typeof f.file_path !== "string") {
|
|
24804
|
+
throw new Error(`Finding "${f.title}" has invalid file_path: expected string`);
|
|
24805
|
+
}
|
|
24806
|
+
if (f.line_start !== void 0 && typeof f.line_start !== "number") {
|
|
24807
|
+
throw new Error(`Finding "${f.title}" has invalid line_start: expected number`);
|
|
24808
|
+
}
|
|
24809
|
+
if (f.line_end !== void 0 && typeof f.line_end !== "number") {
|
|
24810
|
+
throw new Error(`Finding "${f.title}" has invalid line_end: expected number`);
|
|
24811
|
+
}
|
|
24812
|
+
if (f.flagged_by !== void 0 && !Array.isArray(f.flagged_by)) {
|
|
24813
|
+
throw new Error(`Finding "${f.title}" has invalid flagged_by: expected array`);
|
|
24814
|
+
}
|
|
24815
|
+
}
|
|
24816
|
+
}
|
|
24817
|
+
return meta;
|
|
24818
|
+
}
|
|
24819
|
+
function computeRoundCounts(meta) {
|
|
24820
|
+
const allFindings = [];
|
|
24821
|
+
for (const reviewer of meta.reviewers) {
|
|
24822
|
+
allFindings.push(...reviewer.findings);
|
|
24823
|
+
}
|
|
24824
|
+
return {
|
|
24825
|
+
blockerCount: allFindings.filter((f) => f.category === "blocker").length,
|
|
24826
|
+
shouldFixCount: allFindings.filter((f) => f.category === "should_fix").length,
|
|
24827
|
+
suggestionCount: allFindings.filter((f) => f.category === "suggestion").length,
|
|
24828
|
+
reviewerCount: meta.reviewers.length,
|
|
24829
|
+
totalFindingCount: allFindings.length
|
|
24830
|
+
};
|
|
24831
|
+
}
|
|
24832
|
+
async function stateRoundComplete(params) {
|
|
24833
|
+
const { ocrDir } = params;
|
|
24834
|
+
const db = await ensureDatabase(ocrDir);
|
|
24835
|
+
const dbPath = join13(ocrDir, "data", "ocr.db");
|
|
24836
|
+
const rawJsonString = readJsonFromSource(params);
|
|
24837
|
+
const label = params.source === "file" ? params.filePath : "stdin";
|
|
24838
|
+
const raw = parseRawJson(rawJsonString, label);
|
|
24839
|
+
const meta = validateRoundMeta(raw);
|
|
24840
|
+
const counts = computeRoundCounts(meta);
|
|
24841
|
+
const session = resolveSessionForCompletion(db, params.sessionId);
|
|
24842
|
+
const roundNumber = params.round ?? session.current_round;
|
|
24843
|
+
let metaPath;
|
|
24844
|
+
if (params.source === "stdin") {
|
|
24845
|
+
const roundDir = join13(session.session_dir, "rounds", `round-${roundNumber}`);
|
|
24846
|
+
mkdirSync4(roundDir, { recursive: true });
|
|
24847
|
+
metaPath = join13(roundDir, "round-meta.json");
|
|
24848
|
+
writeFileSync7(metaPath, JSON.stringify(meta, null, 2));
|
|
24849
|
+
}
|
|
24850
|
+
insertEvent(db, {
|
|
24851
|
+
session_id: session.id,
|
|
24852
|
+
event_type: "round_completed",
|
|
24853
|
+
phase: "synthesis",
|
|
24854
|
+
phase_number: 7,
|
|
24855
|
+
round: roundNumber,
|
|
24856
|
+
metadata: JSON.stringify({
|
|
24857
|
+
verdict: meta.verdict,
|
|
24858
|
+
blocker_count: counts.blockerCount,
|
|
24859
|
+
should_fix_count: counts.shouldFixCount,
|
|
24860
|
+
suggestion_count: counts.suggestionCount,
|
|
24861
|
+
reviewer_count: counts.reviewerCount,
|
|
24862
|
+
total_finding_count: counts.totalFindingCount,
|
|
24863
|
+
source: "orchestrator"
|
|
24864
|
+
})
|
|
24865
|
+
});
|
|
24866
|
+
saveDatabase(db, dbPath);
|
|
24867
|
+
return { sessionId: session.id, round: roundNumber, metaPath };
|
|
24868
|
+
}
|
|
24869
|
+
function validateMapMeta(meta) {
|
|
24870
|
+
if (!meta || typeof meta !== "object") {
|
|
24871
|
+
throw new Error("map-meta.json must be a JSON object");
|
|
24872
|
+
}
|
|
24873
|
+
const obj = meta;
|
|
24874
|
+
if (obj.schema_version !== 1) {
|
|
24875
|
+
throw new Error(
|
|
24876
|
+
`Unsupported schema_version: ${String(obj.schema_version)}. Expected 1.`
|
|
24877
|
+
);
|
|
24878
|
+
}
|
|
24879
|
+
if (!Array.isArray(obj.sections)) {
|
|
24880
|
+
throw new Error("map-meta.json must contain a sections array");
|
|
24881
|
+
}
|
|
24882
|
+
for (const section of obj.sections) {
|
|
24883
|
+
if (!section || typeof section !== "object") {
|
|
24884
|
+
throw new Error("Each section must be an object");
|
|
24885
|
+
}
|
|
24886
|
+
const s = section;
|
|
24887
|
+
if (typeof s.section_number !== "number") {
|
|
24888
|
+
throw new Error("Each section must have a section_number");
|
|
24889
|
+
}
|
|
24890
|
+
if (typeof s.title !== "string" || s.title.trim().length === 0) {
|
|
24891
|
+
throw new Error("Each section must have a non-empty title");
|
|
24892
|
+
}
|
|
24893
|
+
if (!Array.isArray(s.files)) {
|
|
24894
|
+
throw new Error(`Section "${s.title}" must have a files array`);
|
|
24895
|
+
}
|
|
24896
|
+
for (const file of s.files) {
|
|
24897
|
+
if (!file || typeof file !== "object") {
|
|
24898
|
+
throw new Error("Each file must be an object");
|
|
24899
|
+
}
|
|
24900
|
+
const f = file;
|
|
24901
|
+
if (typeof f.file_path !== "string" || f.file_path.trim().length === 0) {
|
|
24902
|
+
throw new Error("Each file must have a non-empty file_path");
|
|
24903
|
+
}
|
|
24904
|
+
if (typeof f.role !== "string") {
|
|
24905
|
+
throw new Error(`File "${f.file_path}" must have a role string`);
|
|
24906
|
+
}
|
|
24907
|
+
if (typeof f.lines_added !== "number") {
|
|
24908
|
+
throw new Error(`File "${f.file_path}" must have a lines_added number`);
|
|
24909
|
+
}
|
|
24910
|
+
if (typeof f.lines_deleted !== "number") {
|
|
24911
|
+
throw new Error(`File "${f.file_path}" must have a lines_deleted number`);
|
|
24912
|
+
}
|
|
24913
|
+
}
|
|
24914
|
+
}
|
|
24915
|
+
if (obj.dependencies !== void 0 && !Array.isArray(obj.dependencies)) {
|
|
24916
|
+
throw new Error("map-meta.json dependencies must be an array if provided");
|
|
24917
|
+
}
|
|
24918
|
+
return meta;
|
|
24919
|
+
}
|
|
24920
|
+
function computeMapCounts(meta) {
|
|
24921
|
+
return {
|
|
24922
|
+
sectionCount: meta.sections.length,
|
|
24923
|
+
fileCount: meta.sections.reduce((sum, s) => sum + s.files.length, 0)
|
|
24924
|
+
};
|
|
24925
|
+
}
|
|
24926
|
+
async function stateMapComplete(params) {
|
|
24927
|
+
const { ocrDir } = params;
|
|
24928
|
+
const db = await ensureDatabase(ocrDir);
|
|
24929
|
+
const dbPath = join13(ocrDir, "data", "ocr.db");
|
|
24930
|
+
const rawJsonString = readJsonFromSource(params);
|
|
24931
|
+
const label = params.source === "file" ? params.filePath : "stdin";
|
|
24932
|
+
const raw = parseRawJson(rawJsonString, label);
|
|
24933
|
+
const meta = validateMapMeta(raw);
|
|
24934
|
+
const counts = computeMapCounts(meta);
|
|
24935
|
+
const session = resolveSessionForCompletion(db, params.sessionId);
|
|
24936
|
+
const mapRunNumber = params.mapRun ?? session.current_map_run;
|
|
24937
|
+
let metaPath;
|
|
24938
|
+
if (params.source === "stdin") {
|
|
24939
|
+
const runDir = join13(session.session_dir, "map", "runs", `run-${mapRunNumber}`);
|
|
24940
|
+
mkdirSync4(runDir, { recursive: true });
|
|
24941
|
+
metaPath = join13(runDir, "map-meta.json");
|
|
24942
|
+
writeFileSync7(metaPath, JSON.stringify(meta, null, 2));
|
|
24943
|
+
}
|
|
24944
|
+
insertEvent(db, {
|
|
24945
|
+
session_id: session.id,
|
|
24946
|
+
event_type: "map_completed",
|
|
24947
|
+
phase: "synthesis",
|
|
24948
|
+
phase_number: 5,
|
|
24949
|
+
round: mapRunNumber,
|
|
24950
|
+
metadata: JSON.stringify({
|
|
24951
|
+
section_count: counts.sectionCount,
|
|
24952
|
+
file_count: counts.fileCount,
|
|
24953
|
+
source: "orchestrator"
|
|
24954
|
+
})
|
|
24955
|
+
});
|
|
24956
|
+
saveDatabase(db, dbPath);
|
|
24957
|
+
return { sessionId: session.id, mapRun: mapRunNumber, metaPath };
|
|
24958
|
+
}
|
|
24672
24959
|
async function stateSync(ocrDir) {
|
|
24673
24960
|
const db = await ensureDatabase(ocrDir);
|
|
24674
24961
|
const dbPath = join13(ocrDir, "data", "ocr.db");
|
|
@@ -24718,6 +25005,17 @@ async function stateSync(ocrDir) {
|
|
|
24718
25005
|
}
|
|
24719
25006
|
|
|
24720
25007
|
// src/commands/state.ts
|
|
25008
|
+
async function readStdin() {
|
|
25009
|
+
const chunks = [];
|
|
25010
|
+
for await (const chunk of process.stdin) {
|
|
25011
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
25012
|
+
}
|
|
25013
|
+
const data = Buffer.concat(chunks).toString("utf-8").trim();
|
|
25014
|
+
if (data.length === 0) {
|
|
25015
|
+
throw new Error("No data received on stdin");
|
|
25016
|
+
}
|
|
25017
|
+
return data;
|
|
25018
|
+
}
|
|
24721
25019
|
var initSubcommand = new Command("init").description("Initialize a new OCR session").requiredOption("--session-id <id>", "Session ID").requiredOption("--branch <branch>", "Branch name").requiredOption(
|
|
24722
25020
|
"--workflow-type <type>",
|
|
24723
25021
|
"Workflow type (review or map)",
|
|
@@ -24736,7 +25034,7 @@ var initSubcommand = new Command("init").description("Initialize a new OCR sessi
|
|
|
24736
25034
|
const ocrDir = join14(targetDir, ".ocr");
|
|
24737
25035
|
const sessionDir = options.sessionDir ?? join14(ocrDir, "sessions", options.sessionId);
|
|
24738
25036
|
if (!existsSync12(sessionDir)) {
|
|
24739
|
-
|
|
25037
|
+
mkdirSync5(sessionDir, { recursive: true });
|
|
24740
25038
|
}
|
|
24741
25039
|
try {
|
|
24742
25040
|
const sessionId = await stateInit({
|
|
@@ -24762,6 +25060,23 @@ var transitionSubcommand = new Command("transition").description("Transition ses
|
|
|
24762
25060
|
const targetDir = process.cwd();
|
|
24763
25061
|
requireOcrSetup(targetDir);
|
|
24764
25062
|
const ocrDir = join14(targetDir, ".ocr");
|
|
25063
|
+
const VALID_PHASES = /* @__PURE__ */ new Set([
|
|
25064
|
+
"context",
|
|
25065
|
+
"change-context",
|
|
25066
|
+
"analysis",
|
|
25067
|
+
"reviews",
|
|
25068
|
+
"aggregation",
|
|
25069
|
+
"discourse",
|
|
25070
|
+
"synthesis",
|
|
25071
|
+
"complete",
|
|
25072
|
+
"map-context",
|
|
25073
|
+
"topology",
|
|
25074
|
+
"flow-analysis",
|
|
25075
|
+
"requirements-mapping"
|
|
25076
|
+
]);
|
|
25077
|
+
if (!VALID_PHASES.has(options.phase)) {
|
|
25078
|
+
throw new Error(`Invalid phase: "${options.phase}". Must be one of: ${[...VALID_PHASES].join(", ")}`);
|
|
25079
|
+
}
|
|
24765
25080
|
try {
|
|
24766
25081
|
const sessionId = options.sessionId ?? (await resolveActiveSession(ocrDir)).id;
|
|
24767
25082
|
await stateTransition({
|
|
@@ -24890,7 +25205,105 @@ var syncSubcommand = new Command("sync").description("Rebuild session state from
|
|
|
24890
25205
|
process.exit(1);
|
|
24891
25206
|
}
|
|
24892
25207
|
});
|
|
24893
|
-
var
|
|
25208
|
+
var roundCompleteSubcommand = new Command("round-complete").description("Import structured round data into SQLite").option("--file <path>", "Path to round-meta.json").option("--stdin", "Read round-meta JSON from stdin (recommended)").option("--session-id <id>", "Session ID (auto-detects latest active if omitted)").option("--round <number>", "Round number (auto-detects current if omitted)", parseInt).action(
|
|
25209
|
+
async (options) => {
|
|
25210
|
+
const targetDir = process.cwd();
|
|
25211
|
+
requireOcrSetup(targetDir);
|
|
25212
|
+
const ocrDir = join14(targetDir, ".ocr");
|
|
25213
|
+
if (!options.file && !options.stdin) {
|
|
25214
|
+
console.error(source_default.red("Error: Provide either --file <path> or --stdin"));
|
|
25215
|
+
process.exit(1);
|
|
25216
|
+
}
|
|
25217
|
+
if (options.file && options.stdin) {
|
|
25218
|
+
console.error(source_default.red("Error: --file and --stdin are mutually exclusive"));
|
|
25219
|
+
process.exit(1);
|
|
25220
|
+
}
|
|
25221
|
+
try {
|
|
25222
|
+
let result;
|
|
25223
|
+
if (options.stdin) {
|
|
25224
|
+
const data = await readStdin();
|
|
25225
|
+
result = await stateRoundComplete({
|
|
25226
|
+
source: "stdin",
|
|
25227
|
+
ocrDir,
|
|
25228
|
+
data,
|
|
25229
|
+
sessionId: options.sessionId,
|
|
25230
|
+
round: options.round
|
|
25231
|
+
});
|
|
25232
|
+
} else if (options.file) {
|
|
25233
|
+
result = await stateRoundComplete({
|
|
25234
|
+
source: "file",
|
|
25235
|
+
ocrDir,
|
|
25236
|
+
filePath: options.file,
|
|
25237
|
+
sessionId: options.sessionId,
|
|
25238
|
+
round: options.round
|
|
25239
|
+
});
|
|
25240
|
+
} else {
|
|
25241
|
+
process.exit(1);
|
|
25242
|
+
}
|
|
25243
|
+
console.log(source_default.green("Round data imported successfully."));
|
|
25244
|
+
if (result.metaPath) {
|
|
25245
|
+
console.log(source_default.dim(`Wrote ${result.metaPath}`));
|
|
25246
|
+
}
|
|
25247
|
+
} catch (error) {
|
|
25248
|
+
console.error(
|
|
25249
|
+
source_default.red(
|
|
25250
|
+
`Error: ${error instanceof Error ? error.message : "Failed to import round data"}`
|
|
25251
|
+
)
|
|
25252
|
+
);
|
|
25253
|
+
process.exit(1);
|
|
25254
|
+
}
|
|
25255
|
+
}
|
|
25256
|
+
);
|
|
25257
|
+
var mapCompleteSubcommand = new Command("map-complete").description("Import structured map run data into SQLite").option("--file <path>", "Path to map-meta.json").option("--stdin", "Read map-meta JSON from stdin (recommended)").option("--session-id <id>", "Session ID (auto-detects latest active if omitted)").option("--map-run <number>", "Map run number (auto-detects current if omitted)", parseInt).action(
|
|
25258
|
+
async (options) => {
|
|
25259
|
+
const targetDir = process.cwd();
|
|
25260
|
+
requireOcrSetup(targetDir);
|
|
25261
|
+
const ocrDir = join14(targetDir, ".ocr");
|
|
25262
|
+
if (!options.file && !options.stdin) {
|
|
25263
|
+
console.error(source_default.red("Error: Provide either --file <path> or --stdin"));
|
|
25264
|
+
process.exit(1);
|
|
25265
|
+
}
|
|
25266
|
+
if (options.file && options.stdin) {
|
|
25267
|
+
console.error(source_default.red("Error: --file and --stdin are mutually exclusive"));
|
|
25268
|
+
process.exit(1);
|
|
25269
|
+
}
|
|
25270
|
+
try {
|
|
25271
|
+
let result;
|
|
25272
|
+
if (options.stdin) {
|
|
25273
|
+
const data = await readStdin();
|
|
25274
|
+
result = await stateMapComplete({
|
|
25275
|
+
source: "stdin",
|
|
25276
|
+
ocrDir,
|
|
25277
|
+
data,
|
|
25278
|
+
sessionId: options.sessionId,
|
|
25279
|
+
mapRun: options.mapRun
|
|
25280
|
+
});
|
|
25281
|
+
} else if (options.file) {
|
|
25282
|
+
result = await stateMapComplete({
|
|
25283
|
+
source: "file",
|
|
25284
|
+
ocrDir,
|
|
25285
|
+
filePath: options.file,
|
|
25286
|
+
sessionId: options.sessionId,
|
|
25287
|
+
mapRun: options.mapRun
|
|
25288
|
+
});
|
|
25289
|
+
} else {
|
|
25290
|
+
process.exit(1);
|
|
25291
|
+
}
|
|
25292
|
+
console.log(source_default.green("Map data imported successfully."));
|
|
25293
|
+
if (result.metaPath) {
|
|
25294
|
+
console.log(source_default.dim(`Wrote ${result.metaPath}`));
|
|
25295
|
+
}
|
|
25296
|
+
} catch (error) {
|
|
25297
|
+
console.error(
|
|
25298
|
+
source_default.red(
|
|
25299
|
+
`Error: ${error instanceof Error ? error.message : "Failed to import map data"}`
|
|
25300
|
+
)
|
|
25301
|
+
);
|
|
25302
|
+
process.exit(1);
|
|
25303
|
+
}
|
|
25304
|
+
}
|
|
25305
|
+
);
|
|
25306
|
+
var stateCommand = new Command("state").description("Manage OCR session state").addCommand(initSubcommand).addCommand(transitionSubcommand).addCommand(closeSubcommand).addCommand(showSubcommand).addCommand(syncSubcommand).addCommand(roundCompleteSubcommand).addCommand(mapCompleteSubcommand);
|
|
24894
25307
|
|
|
24895
25308
|
// src/commands/update.ts
|
|
24896
25309
|
import { existsSync as existsSync13 } from "node:fs";
|
|
@@ -25203,8 +25616,94 @@ var doctorCommand = new Command("doctor").description("Check OCR installation an
|
|
|
25203
25616
|
console.log();
|
|
25204
25617
|
});
|
|
25205
25618
|
|
|
25619
|
+
// src/lib/update-check.ts
|
|
25620
|
+
import { homedir } from "node:os";
|
|
25621
|
+
import { join as join18 } from "node:path";
|
|
25622
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync8, mkdirSync as mkdirSync6 } from "node:fs";
|
|
25623
|
+
var PACKAGE_NAME = "@open-code-review/cli";
|
|
25624
|
+
var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
25625
|
+
var CACHE_DIR = join18(homedir(), ".ocr");
|
|
25626
|
+
var CACHE_FILE = join18(CACHE_DIR, "update-check.json");
|
|
25627
|
+
var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
|
|
25628
|
+
var FETCH_TIMEOUT_MS = 3e3;
|
|
25629
|
+
function readCache(cacheFile) {
|
|
25630
|
+
try {
|
|
25631
|
+
return JSON.parse(readFileSync10(cacheFile, "utf-8"));
|
|
25632
|
+
} catch {
|
|
25633
|
+
return null;
|
|
25634
|
+
}
|
|
25635
|
+
}
|
|
25636
|
+
function writeCache(cacheFile, cache) {
|
|
25637
|
+
try {
|
|
25638
|
+
mkdirSync6(join18(cacheFile, ".."), { recursive: true });
|
|
25639
|
+
writeFileSync8(cacheFile, JSON.stringify(cache));
|
|
25640
|
+
} catch {
|
|
25641
|
+
}
|
|
25642
|
+
}
|
|
25643
|
+
function isNewer(latest, current) {
|
|
25644
|
+
const l = latest.split(".").map(Number);
|
|
25645
|
+
const c = current.split(".").map(Number);
|
|
25646
|
+
for (let i = 0; i < 3; i++) {
|
|
25647
|
+
if ((l[i] ?? 0) > (c[i] ?? 0)) return true;
|
|
25648
|
+
if ((l[i] ?? 0) < (c[i] ?? 0)) return false;
|
|
25649
|
+
}
|
|
25650
|
+
return false;
|
|
25651
|
+
}
|
|
25652
|
+
function detectUpdateCommand() {
|
|
25653
|
+
return `npm i -g ${PACKAGE_NAME}@latest && ocr update`;
|
|
25654
|
+
}
|
|
25655
|
+
async function checkForUpdate(currentVersion, options) {
|
|
25656
|
+
if (process.env.CI || process.env.OCR_NO_UPDATE_CHECK) {
|
|
25657
|
+
return null;
|
|
25658
|
+
}
|
|
25659
|
+
const cacheFile = join18(options?.cacheDir ?? CACHE_DIR, "update-check.json");
|
|
25660
|
+
try {
|
|
25661
|
+
const cache = readCache(cacheFile);
|
|
25662
|
+
if (cache && Date.now() - cache.lastCheck < CHECK_INTERVAL_MS) {
|
|
25663
|
+
if (!cache.latestVersion) return null;
|
|
25664
|
+
if (!isNewer(cache.latestVersion, currentVersion)) return null;
|
|
25665
|
+
return {
|
|
25666
|
+
updateAvailable: true,
|
|
25667
|
+
currentVersion,
|
|
25668
|
+
latestVersion: cache.latestVersion,
|
|
25669
|
+
updateCommand: detectUpdateCommand()
|
|
25670
|
+
};
|
|
25671
|
+
}
|
|
25672
|
+
const response = await fetch(REGISTRY_URL, {
|
|
25673
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
25674
|
+
});
|
|
25675
|
+
const data = await response.json();
|
|
25676
|
+
const latestVersion = data.version ?? null;
|
|
25677
|
+
writeCache(cacheFile, { lastCheck: Date.now(), latestVersion });
|
|
25678
|
+
if (!latestVersion || !isNewer(latestVersion, currentVersion)) {
|
|
25679
|
+
return null;
|
|
25680
|
+
}
|
|
25681
|
+
return {
|
|
25682
|
+
updateAvailable: true,
|
|
25683
|
+
currentVersion,
|
|
25684
|
+
latestVersion,
|
|
25685
|
+
updateCommand: detectUpdateCommand()
|
|
25686
|
+
};
|
|
25687
|
+
} catch {
|
|
25688
|
+
writeCache(cacheFile, { lastCheck: Date.now(), latestVersion: null });
|
|
25689
|
+
return null;
|
|
25690
|
+
}
|
|
25691
|
+
}
|
|
25692
|
+
function printUpdateNotification(result) {
|
|
25693
|
+
const line1 = source_default.yellow(" Update available: ") + source_default.dim(result.currentVersion) + source_default.yellow(" \u2192 ") + source_default.green(result.latestVersion);
|
|
25694
|
+
const line2 = source_default.dim(" Run: ") + source_default.bold(result.updateCommand);
|
|
25695
|
+
process.stderr.write(`
|
|
25696
|
+
${line1}
|
|
25697
|
+
${line2}
|
|
25698
|
+
|
|
25699
|
+
`);
|
|
25700
|
+
}
|
|
25701
|
+
|
|
25206
25702
|
// src/index.ts
|
|
25207
|
-
var cliVersion = true ? "1.
|
|
25703
|
+
var cliVersion = true ? "1.6.0" : createRequire(import.meta.url)("../package.json").version;
|
|
25704
|
+
var HUMAN_COMMANDS = /* @__PURE__ */ new Set(["init", "update", "doctor", "dashboard", "progress"]);
|
|
25705
|
+
var subcommand = process.argv[2];
|
|
25706
|
+
var updateCheck = subcommand && HUMAN_COMMANDS.has(subcommand) ? checkForUpdate(cliVersion) : null;
|
|
25208
25707
|
var program2 = new Command();
|
|
25209
25708
|
program2.name("ocr").description("Open Code Review - AI-powered multi-agent code review").version(cliVersion);
|
|
25210
25709
|
program2.addCommand(initCommand);
|
|
@@ -25213,7 +25712,16 @@ program2.addCommand(stateCommand);
|
|
|
25213
25712
|
program2.addCommand(updateCommand);
|
|
25214
25713
|
program2.addCommand(dashboardCommand);
|
|
25215
25714
|
program2.addCommand(doctorCommand);
|
|
25216
|
-
program2.
|
|
25715
|
+
await program2.parseAsync();
|
|
25716
|
+
if (updateCheck) {
|
|
25717
|
+
const updateResult = await Promise.race([
|
|
25718
|
+
updateCheck,
|
|
25719
|
+
new Promise((r) => setTimeout(() => r(null), 500))
|
|
25720
|
+
]);
|
|
25721
|
+
if (updateResult?.updateAvailable) {
|
|
25722
|
+
printUpdateNotification(updateResult);
|
|
25723
|
+
}
|
|
25724
|
+
}
|
|
25217
25725
|
/*! Bundled license information:
|
|
25218
25726
|
|
|
25219
25727
|
chokidar/esm/index.js:
|