@open-code-review/cli 2.2.1 → 2.4.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 +9 -0
- package/dist/dashboard/client/assets/{_basePickBy-BAlGnwHG.js → _basePickBy-CyrHyeyN.js} +1 -1
- package/dist/dashboard/client/assets/{_baseUniq-CoauyOeL.js → _baseUniq-Bg7NJSGS.js} +1 -1
- package/dist/dashboard/client/assets/{arc-DtS0aHfP.js → arc-zDGAKMur.js} +1 -1
- package/dist/dashboard/client/assets/{architectureDiagram-VXUJARFQ-CnWmtRTh.js → architectureDiagram-VXUJARFQ-BxlGxm0Q.js} +1 -1
- package/dist/dashboard/client/assets/{blockDiagram-VD42YOAC-DgPp4oGV.js → blockDiagram-VD42YOAC-BskTNyX5.js} +1 -1
- package/dist/dashboard/client/assets/{c4Diagram-YG6GDRKO--LV4qQaE.js → c4Diagram-YG6GDRKO-Dr9QQ-dn.js} +1 -1
- package/dist/dashboard/client/assets/channel-BUnm_-UQ.js +1 -0
- package/dist/dashboard/client/assets/{chunk-4BX2VUAB-BRglpc7Z.js → chunk-4BX2VUAB-xq9xoCTv.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-55IACEB6-Bgx06_CV.js → chunk-55IACEB6-DYdXYVh5.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-B4BG7PRW-D6HN3Yiy.js → chunk-B4BG7PRW-BGAyFRFS.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-DI55MBZ5-NH9EgN9T.js → chunk-DI55MBZ5-C5ul9stk.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-FMBD7UC4-xriO6WNP.js → chunk-FMBD7UC4-BSaPo2xa.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-QN33PNHL-CV1h6_Zl.js → chunk-QN33PNHL-CyzabUv0.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-QZHKN3VN-CV4VzxNq.js → chunk-QZHKN3VN-CceRbxt_.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-TZMSLE5B-isdklocW.js → chunk-TZMSLE5B-Bjg9IoOQ.js} +1 -1
- package/dist/dashboard/client/assets/classDiagram-2ON5EDUG-D_fkmNvU.js +1 -0
- package/dist/dashboard/client/assets/classDiagram-v2-WZHVMYZB-D_fkmNvU.js +1 -0
- package/dist/dashboard/client/assets/clone-DTyrNOLZ.js +1 -0
- package/dist/dashboard/client/assets/{cose-bilkent-S5V4N54A-CCzlFSJf.js → cose-bilkent-S5V4N54A-DEdXBrCt.js} +1 -1
- package/dist/dashboard/client/assets/{dagre-6UL2VRFP-DVN3PkjZ.js → dagre-6UL2VRFP-DRdIiP58.js} +1 -1
- package/dist/dashboard/client/assets/{diagram-PSM6KHXK-SzJVoSsb.js → diagram-PSM6KHXK-Bo7Q2VlK.js} +1 -1
- package/dist/dashboard/client/assets/{diagram-QEK2KX5R-CgGn7ts-.js → diagram-QEK2KX5R-2Fmc2o5x.js} +1 -1
- package/dist/dashboard/client/assets/{diagram-S2PKOQOG-Bz1ukSx8.js → diagram-S2PKOQOG-5WE8f0p7.js} +1 -1
- package/dist/dashboard/client/assets/{erDiagram-Q2GNP2WA-CpstUTMZ.js → erDiagram-Q2GNP2WA-DD-iXWd_.js} +1 -1
- package/dist/dashboard/client/assets/{flowDiagram-NV44I4VS-aYVydGhp.js → flowDiagram-NV44I4VS-CCWo8Ue9.js} +1 -1
- package/dist/dashboard/client/assets/{ganttDiagram-JELNMOA3-Cb2DUSRk.js → ganttDiagram-JELNMOA3-CNY4d5UK.js} +1 -1
- package/dist/dashboard/client/assets/{gitGraphDiagram-V2S2FVAM-BUOnwA2w.js → gitGraphDiagram-V2S2FVAM-Dq5SBEJJ.js} +1 -1
- package/dist/dashboard/client/assets/{graph-4X5ddhLp.js → graph-BTt9lokK.js} +1 -1
- package/dist/dashboard/client/assets/{index-CKWqYAfu.js → index-B0k81q2b.js} +138 -138
- package/dist/dashboard/client/assets/index-Czwdh6UA.css +1 -0
- package/dist/dashboard/client/assets/{infoDiagram-HS3SLOUP-BlMqcrwm.js → infoDiagram-HS3SLOUP-AnKZja-G.js} +1 -1
- package/dist/dashboard/client/assets/{journeyDiagram-XKPGCS4Q-DF2ew7ju.js → journeyDiagram-XKPGCS4Q-nC-_WjPN.js} +1 -1
- package/dist/dashboard/client/assets/{kanban-definition-3W4ZIXB7-BKQMx0-n.js → kanban-definition-3W4ZIXB7-BEY73sWU.js} +1 -1
- package/dist/dashboard/client/assets/{layout-DNcn2g9w.js → layout-D4DfNpzH.js} +1 -1
- package/dist/dashboard/client/assets/{linear-Bqy9gvqb.js → linear-ZpGvKjeP.js} +1 -1
- package/dist/dashboard/client/assets/{mermaid-renderer-dJ71wgld.js → mermaid-renderer-BCDxmS9g.js} +4 -4
- package/dist/dashboard/client/assets/{mindmap-definition-VGOIOE7T-BARc8sqJ.js → mindmap-definition-VGOIOE7T-MzAaKESA.js} +1 -1
- package/dist/dashboard/client/assets/{pieDiagram-ADFJNKIX-CULlNZTd.js → pieDiagram-ADFJNKIX-B_X1kySF.js} +1 -1
- package/dist/dashboard/client/assets/{quadrantDiagram-AYHSOK5B-BJEZPVe9.js → quadrantDiagram-AYHSOK5B-CMoIEMLN.js} +1 -1
- package/dist/dashboard/client/assets/{requirementDiagram-UZGBJVZJ-BhMsmUIs.js → requirementDiagram-UZGBJVZJ-v4CRsn1w.js} +1 -1
- package/dist/dashboard/client/assets/{sankeyDiagram-TZEHDZUN-BYbNgogG.js → sankeyDiagram-TZEHDZUN-CPcyN8Jj.js} +1 -1
- package/dist/dashboard/client/assets/{sequenceDiagram-WL72ISMW-MoM_NwWk.js → sequenceDiagram-WL72ISMW-CTg0Vx1H.js} +1 -1
- package/dist/dashboard/client/assets/{stateDiagram-FKZM4ZOC-ditrlbM3.js → stateDiagram-FKZM4ZOC-BMWBN6Nq.js} +1 -1
- package/dist/dashboard/client/assets/stateDiagram-v2-4FDKWEC3-C9Jk1xd0.js +1 -0
- package/dist/dashboard/client/assets/{timeline-definition-IT6M3QCI-DOAJyjuz.js → timeline-definition-IT6M3QCI-B8xFcSGb.js} +1 -1
- package/dist/dashboard/client/assets/{treemap-GDKQZRPO-BBJkjnJl.js → treemap-GDKQZRPO-HQQuGl9w.js} +1 -1
- package/dist/dashboard/client/assets/{xychartDiagram-PRI3JC2R-CPW4s5vm.js → xychartDiagram-PRI3JC2R-Drz0SW3I.js} +1 -1
- package/dist/dashboard/client/index.html +2 -2
- package/dist/dashboard/server.js +926 -461
- package/dist/index.js +1344 -323
- package/package.json +5 -38
- package/dist/dashboard/client/assets/channel-BU2129fl.js +0 -1
- package/dist/dashboard/client/assets/classDiagram-2ON5EDUG-CVftFGiR.js +0 -1
- package/dist/dashboard/client/assets/classDiagram-v2-WZHVMYZB-CVftFGiR.js +0 -1
- package/dist/dashboard/client/assets/clone-DC6LEEC5.js +0 -1
- package/dist/dashboard/client/assets/index-CzxeSSaQ.css +0 -1
- package/dist/dashboard/client/assets/stateDiagram-v2-4FDKWEC3-SqoG2LCn.js +0 -1
- package/dist/lib/db/index.js +0 -2177
- package/dist/lib/models.js +0 -160
- package/dist/lib/runtime-config.js +0 -55
- package/dist/lib/state/index.js +0 -2196
- package/dist/lib/team-config.js +0 -175
- package/dist/lib/vendor-resume.js +0 -31
package/dist/index.js
CHANGED
|
@@ -39,7 +39,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
39
39
|
mod
|
|
40
40
|
));
|
|
41
41
|
|
|
42
|
-
// src/
|
|
42
|
+
// ../shared/persistence/src/runtime-checks.ts
|
|
43
43
|
function isSupportedNode(version) {
|
|
44
44
|
const [major = 0, minor = 0] = version.split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
45
45
|
return major > NODE_FLOOR.major || major === NODE_FLOOR.major && minor >= NODE_FLOOR.minor;
|
|
@@ -57,7 +57,7 @@ function isSuppressibleSqliteWarning(warning) {
|
|
|
57
57
|
}
|
|
58
58
|
var NODE_FLOOR;
|
|
59
59
|
var init_runtime_checks = __esm({
|
|
60
|
-
"src/
|
|
60
|
+
"../shared/persistence/src/runtime-checks.ts"() {
|
|
61
61
|
"use strict";
|
|
62
62
|
NODE_FLOOR = { major: 22, minor: 5 };
|
|
63
63
|
}
|
|
@@ -16017,35 +16017,688 @@ var require_emoji_regex2 = __commonJS({
|
|
|
16017
16017
|
}
|
|
16018
16018
|
});
|
|
16019
16019
|
|
|
16020
|
-
//
|
|
16021
|
-
|
|
16022
|
-
|
|
16023
|
-
|
|
16024
|
-
|
|
16025
|
-
|
|
16026
|
-
|
|
16027
|
-
|
|
16028
|
-
|
|
16029
|
-
|
|
16030
|
-
|
|
16020
|
+
// ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.js
|
|
16021
|
+
var require_windows = __commonJS({
|
|
16022
|
+
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.js"(exports, module) {
|
|
16023
|
+
"use strict";
|
|
16024
|
+
module.exports = isexe;
|
|
16025
|
+
isexe.sync = sync;
|
|
16026
|
+
var fs = __require("fs");
|
|
16027
|
+
function checkPathExt(path2, options) {
|
|
16028
|
+
var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
|
|
16029
|
+
if (!pathext) {
|
|
16030
|
+
return true;
|
|
16031
|
+
}
|
|
16032
|
+
pathext = pathext.split(";");
|
|
16033
|
+
if (pathext.indexOf("") !== -1) {
|
|
16034
|
+
return true;
|
|
16035
|
+
}
|
|
16036
|
+
for (var i = 0; i < pathext.length; i++) {
|
|
16037
|
+
var p = pathext[i].toLowerCase();
|
|
16038
|
+
if (p && path2.substr(-p.length).toLowerCase() === p) {
|
|
16039
|
+
return true;
|
|
16040
|
+
}
|
|
16041
|
+
}
|
|
16042
|
+
return false;
|
|
16043
|
+
}
|
|
16044
|
+
function checkStat(stat4, path2, options) {
|
|
16045
|
+
if (!stat4.isSymbolicLink() && !stat4.isFile()) {
|
|
16046
|
+
return false;
|
|
16047
|
+
}
|
|
16048
|
+
return checkPathExt(path2, options);
|
|
16049
|
+
}
|
|
16050
|
+
function isexe(path2, options, cb) {
|
|
16051
|
+
fs.stat(path2, function(er, stat4) {
|
|
16052
|
+
cb(er, er ? false : checkStat(stat4, path2, options));
|
|
16053
|
+
});
|
|
16054
|
+
}
|
|
16055
|
+
function sync(path2, options) {
|
|
16056
|
+
return checkStat(fs.statSync(path2), path2, options);
|
|
16057
|
+
}
|
|
16058
|
+
}
|
|
16059
|
+
});
|
|
16060
|
+
|
|
16061
|
+
// ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.js
|
|
16062
|
+
var require_mode = __commonJS({
|
|
16063
|
+
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.js"(exports, module) {
|
|
16064
|
+
"use strict";
|
|
16065
|
+
module.exports = isexe;
|
|
16066
|
+
isexe.sync = sync;
|
|
16067
|
+
var fs = __require("fs");
|
|
16068
|
+
function isexe(path2, options, cb) {
|
|
16069
|
+
fs.stat(path2, function(er, stat4) {
|
|
16070
|
+
cb(er, er ? false : checkStat(stat4, options));
|
|
16071
|
+
});
|
|
16072
|
+
}
|
|
16073
|
+
function sync(path2, options) {
|
|
16074
|
+
return checkStat(fs.statSync(path2), options);
|
|
16075
|
+
}
|
|
16076
|
+
function checkStat(stat4, options) {
|
|
16077
|
+
return stat4.isFile() && checkMode(stat4, options);
|
|
16078
|
+
}
|
|
16079
|
+
function checkMode(stat4, options) {
|
|
16080
|
+
var mod = stat4.mode;
|
|
16081
|
+
var uid = stat4.uid;
|
|
16082
|
+
var gid = stat4.gid;
|
|
16083
|
+
var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid();
|
|
16084
|
+
var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid();
|
|
16085
|
+
var u = parseInt("100", 8);
|
|
16086
|
+
var g = parseInt("010", 8);
|
|
16087
|
+
var o = parseInt("001", 8);
|
|
16088
|
+
var ug = u | g;
|
|
16089
|
+
var ret = mod & o || mod & g && gid === myGid || mod & u && uid === myUid || mod & ug && myUid === 0;
|
|
16090
|
+
return ret;
|
|
16091
|
+
}
|
|
16092
|
+
}
|
|
16093
|
+
});
|
|
16094
|
+
|
|
16095
|
+
// ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js
|
|
16096
|
+
var require_isexe = __commonJS({
|
|
16097
|
+
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js"(exports, module) {
|
|
16098
|
+
"use strict";
|
|
16099
|
+
var fs = __require("fs");
|
|
16100
|
+
var core;
|
|
16101
|
+
if (process.platform === "win32" || global.TESTING_WINDOWS) {
|
|
16102
|
+
core = require_windows();
|
|
16103
|
+
} else {
|
|
16104
|
+
core = require_mode();
|
|
16105
|
+
}
|
|
16106
|
+
module.exports = isexe;
|
|
16107
|
+
isexe.sync = sync;
|
|
16108
|
+
function isexe(path2, options, cb) {
|
|
16109
|
+
if (typeof options === "function") {
|
|
16110
|
+
cb = options;
|
|
16111
|
+
options = {};
|
|
16112
|
+
}
|
|
16113
|
+
if (!cb) {
|
|
16114
|
+
if (typeof Promise !== "function") {
|
|
16115
|
+
throw new TypeError("callback not provided");
|
|
16116
|
+
}
|
|
16117
|
+
return new Promise(function(resolve3, reject) {
|
|
16118
|
+
isexe(path2, options || {}, function(er, is) {
|
|
16119
|
+
if (er) {
|
|
16120
|
+
reject(er);
|
|
16121
|
+
} else {
|
|
16122
|
+
resolve3(is);
|
|
16123
|
+
}
|
|
16124
|
+
});
|
|
16125
|
+
});
|
|
16126
|
+
}
|
|
16127
|
+
core(path2, options || {}, function(er, is) {
|
|
16128
|
+
if (er) {
|
|
16129
|
+
if (er.code === "EACCES" || options && options.ignoreErrors) {
|
|
16130
|
+
er = null;
|
|
16131
|
+
is = false;
|
|
16132
|
+
}
|
|
16133
|
+
}
|
|
16134
|
+
cb(er, is);
|
|
16135
|
+
});
|
|
16136
|
+
}
|
|
16137
|
+
function sync(path2, options) {
|
|
16138
|
+
try {
|
|
16139
|
+
return core.sync(path2, options || {});
|
|
16140
|
+
} catch (er) {
|
|
16141
|
+
if (options && options.ignoreErrors || er.code === "EACCES") {
|
|
16142
|
+
return false;
|
|
16143
|
+
} else {
|
|
16144
|
+
throw er;
|
|
16145
|
+
}
|
|
16146
|
+
}
|
|
16147
|
+
}
|
|
16148
|
+
}
|
|
16149
|
+
});
|
|
16150
|
+
|
|
16151
|
+
// ../../node_modules/.pnpm/which@2.0.2/node_modules/which/which.js
|
|
16152
|
+
var require_which = __commonJS({
|
|
16153
|
+
"../../node_modules/.pnpm/which@2.0.2/node_modules/which/which.js"(exports, module) {
|
|
16154
|
+
"use strict";
|
|
16155
|
+
var isWindows5 = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
|
|
16156
|
+
var path2 = __require("path");
|
|
16157
|
+
var COLON = isWindows5 ? ";" : ":";
|
|
16158
|
+
var isexe = require_isexe();
|
|
16159
|
+
var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
|
|
16160
|
+
var getPathInfo = (cmd, opt) => {
|
|
16161
|
+
const colon = opt.colon || COLON;
|
|
16162
|
+
const pathEnv = cmd.match(/\//) || isWindows5 && cmd.match(/\\/) ? [""] : [
|
|
16163
|
+
// windows always checks the cwd first
|
|
16164
|
+
...isWindows5 ? [process.cwd()] : [],
|
|
16165
|
+
...(opt.path || process.env.PATH || /* istanbul ignore next: very unusual */
|
|
16166
|
+
"").split(colon)
|
|
16167
|
+
];
|
|
16168
|
+
const pathExtExe = isWindows5 ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "";
|
|
16169
|
+
const pathExt = isWindows5 ? pathExtExe.split(colon) : [""];
|
|
16170
|
+
if (isWindows5) {
|
|
16171
|
+
if (cmd.indexOf(".") !== -1 && pathExt[0] !== "")
|
|
16172
|
+
pathExt.unshift("");
|
|
16173
|
+
}
|
|
16174
|
+
return {
|
|
16175
|
+
pathEnv,
|
|
16176
|
+
pathExt,
|
|
16177
|
+
pathExtExe
|
|
16178
|
+
};
|
|
16179
|
+
};
|
|
16180
|
+
var which = (cmd, opt, cb) => {
|
|
16181
|
+
if (typeof opt === "function") {
|
|
16182
|
+
cb = opt;
|
|
16183
|
+
opt = {};
|
|
16184
|
+
}
|
|
16185
|
+
if (!opt)
|
|
16186
|
+
opt = {};
|
|
16187
|
+
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
16188
|
+
const found = [];
|
|
16189
|
+
const step = (i) => new Promise((resolve3, reject) => {
|
|
16190
|
+
if (i === pathEnv.length)
|
|
16191
|
+
return opt.all && found.length ? resolve3(found) : reject(getNotFoundError(cmd));
|
|
16192
|
+
const ppRaw = pathEnv[i];
|
|
16193
|
+
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
16194
|
+
const pCmd = path2.join(pathPart, cmd);
|
|
16195
|
+
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
16196
|
+
resolve3(subStep(p, i, 0));
|
|
16197
|
+
});
|
|
16198
|
+
const subStep = (p, i, ii) => new Promise((resolve3, reject) => {
|
|
16199
|
+
if (ii === pathExt.length)
|
|
16200
|
+
return resolve3(step(i + 1));
|
|
16201
|
+
const ext = pathExt[ii];
|
|
16202
|
+
isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
|
|
16203
|
+
if (!er && is) {
|
|
16204
|
+
if (opt.all)
|
|
16205
|
+
found.push(p + ext);
|
|
16206
|
+
else
|
|
16207
|
+
return resolve3(p + ext);
|
|
16208
|
+
}
|
|
16209
|
+
return resolve3(subStep(p, i, ii + 1));
|
|
16210
|
+
});
|
|
16211
|
+
});
|
|
16212
|
+
return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
|
|
16213
|
+
};
|
|
16214
|
+
var whichSync = (cmd, opt) => {
|
|
16215
|
+
opt = opt || {};
|
|
16216
|
+
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
16217
|
+
const found = [];
|
|
16218
|
+
for (let i = 0; i < pathEnv.length; i++) {
|
|
16219
|
+
const ppRaw = pathEnv[i];
|
|
16220
|
+
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
16221
|
+
const pCmd = path2.join(pathPart, cmd);
|
|
16222
|
+
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
16223
|
+
for (let j = 0; j < pathExt.length; j++) {
|
|
16224
|
+
const cur = p + pathExt[j];
|
|
16225
|
+
try {
|
|
16226
|
+
const is = isexe.sync(cur, { pathExt: pathExtExe });
|
|
16227
|
+
if (is) {
|
|
16228
|
+
if (opt.all)
|
|
16229
|
+
found.push(cur);
|
|
16230
|
+
else
|
|
16231
|
+
return cur;
|
|
16232
|
+
}
|
|
16233
|
+
} catch (ex) {
|
|
16234
|
+
}
|
|
16235
|
+
}
|
|
16236
|
+
}
|
|
16237
|
+
if (opt.all && found.length)
|
|
16238
|
+
return found;
|
|
16239
|
+
if (opt.nothrow)
|
|
16240
|
+
return null;
|
|
16241
|
+
throw getNotFoundError(cmd);
|
|
16242
|
+
};
|
|
16243
|
+
module.exports = which;
|
|
16244
|
+
which.sync = whichSync;
|
|
16245
|
+
}
|
|
16246
|
+
});
|
|
16247
|
+
|
|
16248
|
+
// ../../node_modules/.pnpm/path-key@3.1.1/node_modules/path-key/index.js
|
|
16249
|
+
var require_path_key = __commonJS({
|
|
16250
|
+
"../../node_modules/.pnpm/path-key@3.1.1/node_modules/path-key/index.js"(exports, module) {
|
|
16251
|
+
"use strict";
|
|
16252
|
+
var pathKey = (options = {}) => {
|
|
16253
|
+
const environment = options.env || process.env;
|
|
16254
|
+
const platform2 = options.platform || process.platform;
|
|
16255
|
+
if (platform2 !== "win32") {
|
|
16256
|
+
return "PATH";
|
|
16257
|
+
}
|
|
16258
|
+
return Object.keys(environment).reverse().find((key) => key.toUpperCase() === "PATH") || "Path";
|
|
16259
|
+
};
|
|
16260
|
+
module.exports = pathKey;
|
|
16261
|
+
module.exports.default = pathKey;
|
|
16262
|
+
}
|
|
16263
|
+
});
|
|
16264
|
+
|
|
16265
|
+
// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js
|
|
16266
|
+
var require_resolveCommand = __commonJS({
|
|
16267
|
+
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js"(exports, module) {
|
|
16268
|
+
"use strict";
|
|
16269
|
+
var path2 = __require("path");
|
|
16270
|
+
var which = require_which();
|
|
16271
|
+
var getPathKey = require_path_key();
|
|
16272
|
+
function resolveCommandAttempt(parsed, withoutPathExt) {
|
|
16273
|
+
const env2 = parsed.options.env || process.env;
|
|
16274
|
+
const cwd = process.cwd();
|
|
16275
|
+
const hasCustomCwd = parsed.options.cwd != null;
|
|
16276
|
+
const shouldSwitchCwd = hasCustomCwd && process.chdir !== void 0 && !process.chdir.disabled;
|
|
16277
|
+
if (shouldSwitchCwd) {
|
|
16278
|
+
try {
|
|
16279
|
+
process.chdir(parsed.options.cwd);
|
|
16280
|
+
} catch (err) {
|
|
16281
|
+
}
|
|
16282
|
+
}
|
|
16283
|
+
let resolved;
|
|
16284
|
+
try {
|
|
16285
|
+
resolved = which.sync(parsed.command, {
|
|
16286
|
+
path: env2[getPathKey({ env: env2 })],
|
|
16287
|
+
pathExt: withoutPathExt ? path2.delimiter : void 0
|
|
16288
|
+
});
|
|
16289
|
+
} catch (e) {
|
|
16290
|
+
} finally {
|
|
16291
|
+
if (shouldSwitchCwd) {
|
|
16292
|
+
process.chdir(cwd);
|
|
16293
|
+
}
|
|
16294
|
+
}
|
|
16295
|
+
if (resolved) {
|
|
16296
|
+
resolved = path2.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
|
|
16297
|
+
}
|
|
16298
|
+
return resolved;
|
|
16299
|
+
}
|
|
16300
|
+
function resolveCommand(parsed) {
|
|
16301
|
+
return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
|
|
16302
|
+
}
|
|
16303
|
+
module.exports = resolveCommand;
|
|
16304
|
+
}
|
|
16305
|
+
});
|
|
16306
|
+
|
|
16307
|
+
// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/escape.js
|
|
16308
|
+
var require_escape = __commonJS({
|
|
16309
|
+
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/escape.js"(exports, module) {
|
|
16310
|
+
"use strict";
|
|
16311
|
+
var metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
|
|
16312
|
+
function escapeCommand(arg) {
|
|
16313
|
+
arg = arg.replace(metaCharsRegExp, "^$1");
|
|
16314
|
+
return arg;
|
|
16315
|
+
}
|
|
16316
|
+
function escapeArgument(arg, doubleEscapeMetaChars) {
|
|
16317
|
+
arg = `${arg}`;
|
|
16318
|
+
arg = arg.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"');
|
|
16319
|
+
arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1");
|
|
16320
|
+
arg = `"${arg}"`;
|
|
16321
|
+
arg = arg.replace(metaCharsRegExp, "^$1");
|
|
16322
|
+
if (doubleEscapeMetaChars) {
|
|
16323
|
+
arg = arg.replace(metaCharsRegExp, "^$1");
|
|
16324
|
+
}
|
|
16325
|
+
return arg;
|
|
16326
|
+
}
|
|
16327
|
+
module.exports.command = escapeCommand;
|
|
16328
|
+
module.exports.argument = escapeArgument;
|
|
16329
|
+
}
|
|
16330
|
+
});
|
|
16331
|
+
|
|
16332
|
+
// ../../node_modules/.pnpm/shebang-regex@3.0.0/node_modules/shebang-regex/index.js
|
|
16333
|
+
var require_shebang_regex = __commonJS({
|
|
16334
|
+
"../../node_modules/.pnpm/shebang-regex@3.0.0/node_modules/shebang-regex/index.js"(exports, module) {
|
|
16335
|
+
"use strict";
|
|
16336
|
+
module.exports = /^#!(.*)/;
|
|
16337
|
+
}
|
|
16338
|
+
});
|
|
16339
|
+
|
|
16340
|
+
// ../../node_modules/.pnpm/shebang-command@2.0.0/node_modules/shebang-command/index.js
|
|
16341
|
+
var require_shebang_command = __commonJS({
|
|
16342
|
+
"../../node_modules/.pnpm/shebang-command@2.0.0/node_modules/shebang-command/index.js"(exports, module) {
|
|
16343
|
+
"use strict";
|
|
16344
|
+
var shebangRegex = require_shebang_regex();
|
|
16345
|
+
module.exports = (string = "") => {
|
|
16346
|
+
const match = string.match(shebangRegex);
|
|
16347
|
+
if (!match) {
|
|
16348
|
+
return null;
|
|
16349
|
+
}
|
|
16350
|
+
const [path2, argument] = match[0].replace(/#! ?/, "").split(" ");
|
|
16351
|
+
const binary = path2.split("/").pop();
|
|
16352
|
+
if (binary === "env") {
|
|
16353
|
+
return argument;
|
|
16354
|
+
}
|
|
16355
|
+
return argument ? `${binary} ${argument}` : binary;
|
|
16356
|
+
};
|
|
16357
|
+
}
|
|
16358
|
+
});
|
|
16359
|
+
|
|
16360
|
+
// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js
|
|
16361
|
+
var require_readShebang = __commonJS({
|
|
16362
|
+
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js"(exports, module) {
|
|
16363
|
+
"use strict";
|
|
16364
|
+
var fs = __require("fs");
|
|
16365
|
+
var shebangCommand = require_shebang_command();
|
|
16366
|
+
function readShebang(command) {
|
|
16367
|
+
const size = 150;
|
|
16368
|
+
const buffer = Buffer.alloc(size);
|
|
16369
|
+
let fd;
|
|
16370
|
+
try {
|
|
16371
|
+
fd = fs.openSync(command, "r");
|
|
16372
|
+
fs.readSync(fd, buffer, 0, size, 0);
|
|
16373
|
+
fs.closeSync(fd);
|
|
16374
|
+
} catch (e) {
|
|
16375
|
+
}
|
|
16376
|
+
return shebangCommand(buffer.toString());
|
|
16377
|
+
}
|
|
16378
|
+
module.exports = readShebang;
|
|
16379
|
+
}
|
|
16380
|
+
});
|
|
16381
|
+
|
|
16382
|
+
// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js
|
|
16383
|
+
var require_parse = __commonJS({
|
|
16384
|
+
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js"(exports, module) {
|
|
16385
|
+
"use strict";
|
|
16386
|
+
var path2 = __require("path");
|
|
16387
|
+
var resolveCommand = require_resolveCommand();
|
|
16388
|
+
var escape = require_escape();
|
|
16389
|
+
var readShebang = require_readShebang();
|
|
16390
|
+
var isWin = process.platform === "win32";
|
|
16391
|
+
var isExecutableRegExp = /\.(?:com|exe)$/i;
|
|
16392
|
+
var isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
|
|
16393
|
+
function detectShebang(parsed) {
|
|
16394
|
+
parsed.file = resolveCommand(parsed);
|
|
16395
|
+
const shebang = parsed.file && readShebang(parsed.file);
|
|
16396
|
+
if (shebang) {
|
|
16397
|
+
parsed.args.unshift(parsed.file);
|
|
16398
|
+
parsed.command = shebang;
|
|
16399
|
+
return resolveCommand(parsed);
|
|
16400
|
+
}
|
|
16401
|
+
return parsed.file;
|
|
16402
|
+
}
|
|
16403
|
+
function parseNonShell(parsed) {
|
|
16404
|
+
if (!isWin) {
|
|
16405
|
+
return parsed;
|
|
16406
|
+
}
|
|
16407
|
+
const commandFile = detectShebang(parsed);
|
|
16408
|
+
const needsShell = !isExecutableRegExp.test(commandFile);
|
|
16409
|
+
if (parsed.options.forceShell || needsShell) {
|
|
16410
|
+
const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
|
|
16411
|
+
parsed.command = path2.normalize(parsed.command);
|
|
16412
|
+
parsed.command = escape.command(parsed.command);
|
|
16413
|
+
parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
|
|
16414
|
+
const shellCommand = [parsed.command].concat(parsed.args).join(" ");
|
|
16415
|
+
parsed.args = ["/d", "/s", "/c", `"${shellCommand}"`];
|
|
16416
|
+
parsed.command = process.env.comspec || "cmd.exe";
|
|
16417
|
+
parsed.options.windowsVerbatimArguments = true;
|
|
16418
|
+
}
|
|
16419
|
+
return parsed;
|
|
16420
|
+
}
|
|
16421
|
+
function parse(command, args, options) {
|
|
16422
|
+
if (args && !Array.isArray(args)) {
|
|
16423
|
+
options = args;
|
|
16424
|
+
args = null;
|
|
16425
|
+
}
|
|
16426
|
+
args = args ? args.slice(0) : [];
|
|
16427
|
+
options = Object.assign({}, options);
|
|
16428
|
+
const parsed = {
|
|
16429
|
+
command,
|
|
16430
|
+
args,
|
|
16431
|
+
options,
|
|
16432
|
+
file: void 0,
|
|
16433
|
+
original: {
|
|
16434
|
+
command,
|
|
16435
|
+
args
|
|
16436
|
+
}
|
|
16437
|
+
};
|
|
16438
|
+
return options.shell ? parsed : parseNonShell(parsed);
|
|
16439
|
+
}
|
|
16440
|
+
module.exports = parse;
|
|
16441
|
+
}
|
|
16442
|
+
});
|
|
16443
|
+
|
|
16444
|
+
// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/enoent.js
|
|
16445
|
+
var require_enoent = __commonJS({
|
|
16446
|
+
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/enoent.js"(exports, module) {
|
|
16447
|
+
"use strict";
|
|
16448
|
+
var isWin = process.platform === "win32";
|
|
16449
|
+
function notFoundError(original, syscall) {
|
|
16450
|
+
return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), {
|
|
16451
|
+
code: "ENOENT",
|
|
16452
|
+
errno: "ENOENT",
|
|
16453
|
+
syscall: `${syscall} ${original.command}`,
|
|
16454
|
+
path: original.command,
|
|
16455
|
+
spawnargs: original.args
|
|
16456
|
+
});
|
|
16457
|
+
}
|
|
16458
|
+
function hookChildProcess(cp, parsed) {
|
|
16459
|
+
if (!isWin) {
|
|
16460
|
+
return;
|
|
16461
|
+
}
|
|
16462
|
+
const originalEmit = cp.emit;
|
|
16463
|
+
cp.emit = function(name, arg1) {
|
|
16464
|
+
if (name === "exit") {
|
|
16465
|
+
const err = verifyENOENT(arg1, parsed);
|
|
16466
|
+
if (err) {
|
|
16467
|
+
return originalEmit.call(cp, "error", err);
|
|
16468
|
+
}
|
|
16469
|
+
}
|
|
16470
|
+
return originalEmit.apply(cp, arguments);
|
|
16471
|
+
};
|
|
16472
|
+
}
|
|
16473
|
+
function verifyENOENT(status, parsed) {
|
|
16474
|
+
if (isWin && status === 1 && !parsed.file) {
|
|
16475
|
+
return notFoundError(parsed.original, "spawn");
|
|
16476
|
+
}
|
|
16477
|
+
return null;
|
|
16478
|
+
}
|
|
16479
|
+
function verifyENOENTSync(status, parsed) {
|
|
16480
|
+
if (isWin && status === 1 && !parsed.file) {
|
|
16481
|
+
return notFoundError(parsed.original, "spawnSync");
|
|
16482
|
+
}
|
|
16483
|
+
return null;
|
|
16484
|
+
}
|
|
16485
|
+
module.exports = {
|
|
16486
|
+
hookChildProcess,
|
|
16487
|
+
verifyENOENT,
|
|
16488
|
+
verifyENOENTSync,
|
|
16489
|
+
notFoundError
|
|
16490
|
+
};
|
|
16491
|
+
}
|
|
16492
|
+
});
|
|
16493
|
+
|
|
16494
|
+
// ../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/index.js
|
|
16495
|
+
var require_cross_spawn = __commonJS({
|
|
16496
|
+
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/index.js"(exports, module) {
|
|
16497
|
+
"use strict";
|
|
16498
|
+
var cp = __require("child_process");
|
|
16499
|
+
var parse = require_parse();
|
|
16500
|
+
var enoent = require_enoent();
|
|
16501
|
+
function spawn2(command, args, options) {
|
|
16502
|
+
const parsed = parse(command, args, options);
|
|
16503
|
+
const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
|
|
16504
|
+
enoent.hookChildProcess(spawned, parsed);
|
|
16505
|
+
return spawned;
|
|
16506
|
+
}
|
|
16507
|
+
function spawnSync2(command, args, options) {
|
|
16508
|
+
const parsed = parse(command, args, options);
|
|
16509
|
+
const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
|
|
16510
|
+
result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
|
|
16511
|
+
return result;
|
|
16512
|
+
}
|
|
16513
|
+
module.exports = spawn2;
|
|
16514
|
+
module.exports.spawn = spawn2;
|
|
16515
|
+
module.exports.sync = spawnSync2;
|
|
16516
|
+
module.exports._parse = parse;
|
|
16517
|
+
module.exports._enoent = enoent;
|
|
16518
|
+
}
|
|
16519
|
+
});
|
|
16520
|
+
|
|
16521
|
+
// ../shared/platform/src/spawn.ts
|
|
16031
16522
|
function execBinary(binary, args, opts) {
|
|
16032
|
-
|
|
16033
|
-
|
|
16034
|
-
|
|
16523
|
+
const result = import_cross_spawn.default.sync(binary, args, {
|
|
16524
|
+
maxBuffer: DEFAULT_MAX_BUFFER,
|
|
16525
|
+
...opts
|
|
16035
16526
|
});
|
|
16527
|
+
if (result.error) throw result.error;
|
|
16528
|
+
if (result.status !== 0) {
|
|
16529
|
+
throw Object.assign(
|
|
16530
|
+
new Error(
|
|
16531
|
+
`Command failed: ${binary} ${args.join(" ")}
|
|
16532
|
+
${String(result.stderr ?? "")}`
|
|
16533
|
+
),
|
|
16534
|
+
{
|
|
16535
|
+
status: result.status,
|
|
16536
|
+
code: result.status,
|
|
16537
|
+
signal: result.signal,
|
|
16538
|
+
stdout: result.stdout,
|
|
16539
|
+
stderr: result.stderr,
|
|
16540
|
+
pid: result.pid
|
|
16541
|
+
}
|
|
16542
|
+
);
|
|
16543
|
+
}
|
|
16544
|
+
return result.stdout;
|
|
16036
16545
|
}
|
|
16037
16546
|
async function execBinaryAsync(binary, args, opts) {
|
|
16038
|
-
return
|
|
16547
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
16548
|
+
const child = (0, import_cross_spawn.default)(binary, args, {
|
|
16549
|
+
cwd: opts.cwd,
|
|
16550
|
+
env: opts.env,
|
|
16551
|
+
windowsHide: true
|
|
16552
|
+
});
|
|
16553
|
+
const maxBuffer = opts.maxBuffer ?? DEFAULT_MAX_BUFFER;
|
|
16554
|
+
let stdout = "";
|
|
16555
|
+
let stderr = "";
|
|
16556
|
+
let killed = false;
|
|
16557
|
+
let settled = false;
|
|
16558
|
+
const settle = (fn) => {
|
|
16559
|
+
if (settled) return;
|
|
16560
|
+
settled = true;
|
|
16561
|
+
if (timer) clearTimeout(timer);
|
|
16562
|
+
fn();
|
|
16563
|
+
};
|
|
16564
|
+
const overflow = () => {
|
|
16565
|
+
killed = true;
|
|
16566
|
+
child.kill();
|
|
16567
|
+
};
|
|
16568
|
+
child.stdout?.setEncoding(opts.encoding);
|
|
16569
|
+
child.stderr?.setEncoding(opts.encoding);
|
|
16570
|
+
child.stdout?.on("data", (chunk) => {
|
|
16571
|
+
stdout += chunk;
|
|
16572
|
+
if (stdout.length > maxBuffer) overflow();
|
|
16573
|
+
});
|
|
16574
|
+
child.stderr?.on("data", (chunk) => {
|
|
16575
|
+
stderr += chunk;
|
|
16576
|
+
if (stderr.length > maxBuffer) overflow();
|
|
16577
|
+
});
|
|
16578
|
+
const timer = opts.timeout ? setTimeout(() => {
|
|
16579
|
+
killed = true;
|
|
16580
|
+
child.kill();
|
|
16581
|
+
}, opts.timeout) : void 0;
|
|
16582
|
+
child.on("error", (err) => {
|
|
16583
|
+
settle(
|
|
16584
|
+
() => rejectPromise(Object.assign(err, { stdout, stderr, killed }))
|
|
16585
|
+
);
|
|
16586
|
+
});
|
|
16587
|
+
child.on("close", (code, signal) => {
|
|
16588
|
+
settle(() => {
|
|
16589
|
+
if (code === 0 && !killed) {
|
|
16590
|
+
resolvePromise({ stdout, stderr });
|
|
16591
|
+
return;
|
|
16592
|
+
}
|
|
16593
|
+
rejectPromise(
|
|
16594
|
+
Object.assign(
|
|
16595
|
+
new Error(
|
|
16596
|
+
`Command failed: ${binary} ${args.join(" ")}
|
|
16597
|
+
${stderr}`
|
|
16598
|
+
),
|
|
16599
|
+
{
|
|
16600
|
+
code: code ?? void 0,
|
|
16601
|
+
signal,
|
|
16602
|
+
stdout,
|
|
16603
|
+
stderr,
|
|
16604
|
+
killed
|
|
16605
|
+
}
|
|
16606
|
+
)
|
|
16607
|
+
);
|
|
16608
|
+
});
|
|
16609
|
+
});
|
|
16610
|
+
});
|
|
16611
|
+
}
|
|
16612
|
+
function spawnBinary(binary, args, opts) {
|
|
16613
|
+
return (0, import_cross_spawn.default)(binary, args, {
|
|
16039
16614
|
...opts,
|
|
16040
|
-
|
|
16615
|
+
windowsHide: true
|
|
16041
16616
|
});
|
|
16042
16617
|
}
|
|
16618
|
+
var import_cross_spawn, DEFAULT_MAX_BUFFER;
|
|
16619
|
+
var init_spawn = __esm({
|
|
16620
|
+
"../shared/platform/src/spawn.ts"() {
|
|
16621
|
+
"use strict";
|
|
16622
|
+
import_cross_spawn = __toESM(require_cross_spawn(), 1);
|
|
16623
|
+
DEFAULT_MAX_BUFFER = 1024 * 1024;
|
|
16624
|
+
}
|
|
16625
|
+
});
|
|
16626
|
+
|
|
16627
|
+
// ../shared/platform/src/verdict.ts
|
|
16628
|
+
function isCanonicalVerdict(v) {
|
|
16629
|
+
return VERDICT_SET.has(v);
|
|
16630
|
+
}
|
|
16631
|
+
var CANONICAL_VERDICTS, VERDICT_SET;
|
|
16632
|
+
var init_verdict = __esm({
|
|
16633
|
+
"../shared/platform/src/verdict.ts"() {
|
|
16634
|
+
"use strict";
|
|
16635
|
+
CANONICAL_VERDICTS = [
|
|
16636
|
+
"APPROVE",
|
|
16637
|
+
"REQUEST CHANGES",
|
|
16638
|
+
"NEEDS DISCUSSION"
|
|
16639
|
+
];
|
|
16640
|
+
VERDICT_SET = new Set(CANONICAL_VERDICTS);
|
|
16641
|
+
}
|
|
16642
|
+
});
|
|
16643
|
+
|
|
16644
|
+
// ../shared/platform/src/counts.ts
|
|
16645
|
+
function deriveCounts(findings) {
|
|
16646
|
+
const counts = {
|
|
16647
|
+
blocker: 0,
|
|
16648
|
+
should_fix: 0,
|
|
16649
|
+
suggestion: 0,
|
|
16650
|
+
style: 0
|
|
16651
|
+
};
|
|
16652
|
+
for (const finding of findings) {
|
|
16653
|
+
const category = finding?.category;
|
|
16654
|
+
if (category === "blocker" || category === "should_fix" || category === "suggestion" || category === "style") {
|
|
16655
|
+
counts[category]++;
|
|
16656
|
+
}
|
|
16657
|
+
}
|
|
16658
|
+
return counts;
|
|
16659
|
+
}
|
|
16660
|
+
function collectFindings(meta) {
|
|
16661
|
+
const all = [];
|
|
16662
|
+
for (const reviewer of meta.reviewers ?? []) {
|
|
16663
|
+
for (const finding of reviewer?.findings ?? []) all.push(finding);
|
|
16664
|
+
}
|
|
16665
|
+
return all;
|
|
16666
|
+
}
|
|
16667
|
+
function preferred(scValue, derivedValue) {
|
|
16668
|
+
return typeof scValue === "number" && Number.isFinite(scValue) ? scValue : derivedValue;
|
|
16669
|
+
}
|
|
16670
|
+
function resolveRoundCounts(meta) {
|
|
16671
|
+
const allFindings = collectFindings(meta);
|
|
16672
|
+
const derived = deriveCounts(allFindings);
|
|
16673
|
+
const sc = meta.synthesis_counts ?? void 0;
|
|
16674
|
+
return {
|
|
16675
|
+
blockerCount: sc ? preferred(sc.blockers, derived.blocker) : derived.blocker,
|
|
16676
|
+
shouldFixCount: sc ? preferred(sc.should_fix, derived.should_fix) : derived.should_fix,
|
|
16677
|
+
suggestionCount: sc ? preferred(sc.suggestions, derived.suggestion) : derived.suggestion,
|
|
16678
|
+
reviewerCount: (meta.reviewers ?? []).length,
|
|
16679
|
+
totalFindingCount: allFindings.length
|
|
16680
|
+
};
|
|
16681
|
+
}
|
|
16682
|
+
var init_counts = __esm({
|
|
16683
|
+
"../shared/platform/src/counts.ts"() {
|
|
16684
|
+
"use strict";
|
|
16685
|
+
}
|
|
16686
|
+
});
|
|
16687
|
+
|
|
16688
|
+
// ../shared/platform/src/index.ts
|
|
16689
|
+
import { pathToFileURL } from "node:url";
|
|
16690
|
+
async function importModule(absolutePath) {
|
|
16691
|
+
return import(pathToFileURL(absolutePath).href);
|
|
16692
|
+
}
|
|
16693
|
+
function killErrorMeansDead(err) {
|
|
16694
|
+
return err instanceof Error && "code" in err && err.code === "ESRCH";
|
|
16695
|
+
}
|
|
16043
16696
|
function isProcessAlive(pid) {
|
|
16044
16697
|
try {
|
|
16045
16698
|
process.kill(pid, 0);
|
|
16046
16699
|
return true;
|
|
16047
16700
|
} catch (err) {
|
|
16048
|
-
return !(err
|
|
16701
|
+
return !killErrorMeansDead(err);
|
|
16049
16702
|
}
|
|
16050
16703
|
}
|
|
16051
16704
|
function defaultIconFor(id, tier) {
|
|
@@ -16054,11 +16707,13 @@ function defaultIconFor(id, tier) {
|
|
|
16054
16707
|
function hostCapabilitiesFor(vendor) {
|
|
16055
16708
|
return vendor && HOST_CAPABILITIES[vendor] || DEFAULT_HOST_CAPABILITIES;
|
|
16056
16709
|
}
|
|
16057
|
-
var
|
|
16710
|
+
var isWindows, BUILTIN_ICON_MAP, DEFAULT_HOST_CAPABILITIES, HOST_CAPABILITIES;
|
|
16058
16711
|
var init_src = __esm({
|
|
16059
16712
|
"../shared/platform/src/index.ts"() {
|
|
16060
16713
|
"use strict";
|
|
16061
|
-
|
|
16714
|
+
init_spawn();
|
|
16715
|
+
init_verdict();
|
|
16716
|
+
init_counts();
|
|
16062
16717
|
isWindows = process.platform === "win32";
|
|
16063
16718
|
BUILTIN_ICON_MAP = {
|
|
16064
16719
|
architect: "blocks",
|
|
@@ -23399,31 +24054,7 @@ var require_dist = __commonJS({
|
|
|
23399
24054
|
}
|
|
23400
24055
|
});
|
|
23401
24056
|
|
|
23402
|
-
// src/
|
|
23403
|
-
function resultToRows(result) {
|
|
23404
|
-
if (result.length === 0 || !result[0]) {
|
|
23405
|
-
return [];
|
|
23406
|
-
}
|
|
23407
|
-
const { columns, values } = result[0];
|
|
23408
|
-
return values.map((row) => {
|
|
23409
|
-
const obj = {};
|
|
23410
|
-
for (let i = 0; i < columns.length; i++) {
|
|
23411
|
-
obj[columns[i]] = row[i];
|
|
23412
|
-
}
|
|
23413
|
-
return obj;
|
|
23414
|
-
});
|
|
23415
|
-
}
|
|
23416
|
-
function resultToRow(result) {
|
|
23417
|
-
const rows = resultToRows(result);
|
|
23418
|
-
return rows[0];
|
|
23419
|
-
}
|
|
23420
|
-
var init_result_mapper = __esm({
|
|
23421
|
-
"src/lib/db/result-mapper.ts"() {
|
|
23422
|
-
"use strict";
|
|
23423
|
-
}
|
|
23424
|
-
});
|
|
23425
|
-
|
|
23426
|
-
// src/lib/db/engine.ts
|
|
24057
|
+
// ../shared/persistence/src/db/engine.ts
|
|
23427
24058
|
import { createRequire as createRequire2 } from "node:module";
|
|
23428
24059
|
function applyEnginePreconditions() {
|
|
23429
24060
|
if (_preconditionsApplied) return;
|
|
@@ -23477,7 +24108,7 @@ function openEngine(dbPath) {
|
|
|
23477
24108
|
}
|
|
23478
24109
|
var SQLITE_BUSY, SQLITE_BUSY_SNAPSHOT, BUSY_RETRY_ATTEMPTS, BUSY_RETRY_BACKOFF_MS, savepointName, nodeRequire, _preconditionsApplied, _DatabaseSyncCtor, SLEEP_BUF, NodeSqliteAdapter;
|
|
23479
24110
|
var init_engine = __esm({
|
|
23480
|
-
"src/
|
|
24111
|
+
"../shared/persistence/src/db/engine.ts"() {
|
|
23481
24112
|
"use strict";
|
|
23482
24113
|
init_runtime_checks();
|
|
23483
24114
|
SQLITE_BUSY = 5;
|
|
@@ -23604,7 +24235,7 @@ var init_engine = __esm({
|
|
|
23604
24235
|
}
|
|
23605
24236
|
});
|
|
23606
24237
|
|
|
23607
|
-
// src/
|
|
24238
|
+
// ../shared/persistence/src/db/migrations.ts
|
|
23608
24239
|
function columnExists(db, table, column) {
|
|
23609
24240
|
const result = db.exec(`PRAGMA table_info(${table})`);
|
|
23610
24241
|
const first = result[0];
|
|
@@ -23659,7 +24290,7 @@ function runMigrations(db) {
|
|
|
23659
24290
|
}
|
|
23660
24291
|
var MIGRATIONS;
|
|
23661
24292
|
var init_migrations = __esm({
|
|
23662
|
-
"src/
|
|
24293
|
+
"../shared/persistence/src/db/migrations.ts"() {
|
|
23663
24294
|
"use strict";
|
|
23664
24295
|
MIGRATIONS = [
|
|
23665
24296
|
{
|
|
@@ -24158,7 +24789,31 @@ var init_migrations = __esm({
|
|
|
24158
24789
|
}
|
|
24159
24790
|
});
|
|
24160
24791
|
|
|
24161
|
-
// src/
|
|
24792
|
+
// ../shared/persistence/src/db/result-mapper.ts
|
|
24793
|
+
function resultToRows(result) {
|
|
24794
|
+
if (result.length === 0 || !result[0]) {
|
|
24795
|
+
return [];
|
|
24796
|
+
}
|
|
24797
|
+
const { columns, values } = result[0];
|
|
24798
|
+
return values.map((row) => {
|
|
24799
|
+
const obj = {};
|
|
24800
|
+
for (let i = 0; i < columns.length; i++) {
|
|
24801
|
+
obj[columns[i]] = row[i];
|
|
24802
|
+
}
|
|
24803
|
+
return obj;
|
|
24804
|
+
});
|
|
24805
|
+
}
|
|
24806
|
+
function resultToRow(result) {
|
|
24807
|
+
const rows = resultToRows(result);
|
|
24808
|
+
return rows[0];
|
|
24809
|
+
}
|
|
24810
|
+
var init_result_mapper = __esm({
|
|
24811
|
+
"../shared/persistence/src/db/result-mapper.ts"() {
|
|
24812
|
+
"use strict";
|
|
24813
|
+
}
|
|
24814
|
+
});
|
|
24815
|
+
|
|
24816
|
+
// ../shared/persistence/src/db/queries.ts
|
|
24162
24817
|
function insertSession(db, params) {
|
|
24163
24818
|
const {
|
|
24164
24819
|
id,
|
|
@@ -24273,15 +24928,15 @@ function commitReasonClose(db, sessionId, reasonEvent, projectionUpdates) {
|
|
|
24273
24928
|
});
|
|
24274
24929
|
}
|
|
24275
24930
|
var init_queries = __esm({
|
|
24276
|
-
"src/
|
|
24931
|
+
"../shared/persistence/src/db/queries.ts"() {
|
|
24277
24932
|
"use strict";
|
|
24278
24933
|
init_result_mapper();
|
|
24279
24934
|
}
|
|
24280
24935
|
});
|
|
24281
24936
|
|
|
24282
|
-
// src/
|
|
24283
|
-
import { existsSync as
|
|
24284
|
-
import { isAbsolute as isAbsolute2, join as
|
|
24937
|
+
// ../shared/persistence/src/db/reconcile.ts
|
|
24938
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
24939
|
+
import { isAbsolute as isAbsolute2, join as join9, dirname as dirname5 } from "node:path";
|
|
24285
24940
|
function hasTerminalArtifactEvent(db, sessionId, workflowType, currentRound, currentMapRun) {
|
|
24286
24941
|
const eventType = workflowType === "map" ? "map_completed" : "round_completed";
|
|
24287
24942
|
const round = workflowType === "map" ? currentMapRun : currentRound;
|
|
@@ -24322,7 +24977,7 @@ function hasInFlightDependents(db, sessionId) {
|
|
|
24322
24977
|
function resolveSessionDir(ocrDir, sessionDir) {
|
|
24323
24978
|
if (!sessionDir) return null;
|
|
24324
24979
|
if (isAbsolute2(sessionDir)) return sessionDir;
|
|
24325
|
-
return
|
|
24980
|
+
return join9(dirname5(ocrDir), sessionDir);
|
|
24326
24981
|
}
|
|
24327
24982
|
function reconcileLegacyState(db, ocrDir, opts = {}) {
|
|
24328
24983
|
const dryRun = opts.dryRun ?? false;
|
|
@@ -24334,8 +24989,8 @@ function reconcileLegacyState(db, ocrDir, opts = {}) {
|
|
|
24334
24989
|
if (hasTerminalArtifactEvent(db, s.id, s.workflow_type, s.current_round, s.current_map_run) || hasReasonEvent(db, s.id)) {
|
|
24335
24990
|
continue;
|
|
24336
24991
|
}
|
|
24337
|
-
const reviewFinal = s.workflow_type === "review" && dir ?
|
|
24338
|
-
const mapFinal = s.workflow_type === "map" && dir ?
|
|
24992
|
+
const reviewFinal = s.workflow_type === "review" && dir ? existsSync7(join9(dir, "rounds", `round-${s.current_round}`, "final.md")) : false;
|
|
24993
|
+
const mapFinal = s.workflow_type === "map" && dir ? existsSync7(join9(dir, "map", "runs", `run-${s.current_map_run}`, "map.md")) : false;
|
|
24339
24994
|
if (reviewFinal) {
|
|
24340
24995
|
actions.push({
|
|
24341
24996
|
sessionId: s.id,
|
|
@@ -24411,20 +25066,20 @@ function reconcileLegacyState(db, ocrDir, opts = {}) {
|
|
|
24411
25066
|
}
|
|
24412
25067
|
var DEFAULT_STALE_THRESHOLD_SECONDS;
|
|
24413
25068
|
var init_reconcile = __esm({
|
|
24414
|
-
"src/
|
|
25069
|
+
"../shared/persistence/src/db/reconcile.ts"() {
|
|
24415
25070
|
"use strict";
|
|
24416
25071
|
init_queries();
|
|
24417
25072
|
DEFAULT_STALE_THRESHOLD_SECONDS = 7 * 24 * 60 * 60;
|
|
24418
25073
|
}
|
|
24419
25074
|
});
|
|
24420
25075
|
|
|
24421
|
-
// src/
|
|
25076
|
+
// ../shared/persistence/src/db/liveness.ts
|
|
24422
25077
|
function defaultIsAlive(pid) {
|
|
24423
25078
|
try {
|
|
24424
25079
|
process.kill(pid, 0);
|
|
24425
25080
|
return true;
|
|
24426
25081
|
} catch (err) {
|
|
24427
|
-
return !(err
|
|
25082
|
+
return !killErrorMeansDead(err);
|
|
24428
25083
|
}
|
|
24429
25084
|
}
|
|
24430
25085
|
function sqliteUtcMs(ts) {
|
|
@@ -24433,16 +25088,17 @@ function sqliteUtcMs(ts) {
|
|
|
24433
25088
|
}
|
|
24434
25089
|
var PID_REUSE_GUARD_MS;
|
|
24435
25090
|
var init_liveness = __esm({
|
|
24436
|
-
"src/
|
|
25091
|
+
"../shared/persistence/src/db/liveness.ts"() {
|
|
24437
25092
|
"use strict";
|
|
25093
|
+
init_src();
|
|
24438
25094
|
PID_REUSE_GUARD_MS = 24 * 60 * 60 * 1e3;
|
|
24439
25095
|
}
|
|
24440
25096
|
});
|
|
24441
25097
|
|
|
24442
|
-
// src/
|
|
25098
|
+
// ../shared/persistence/src/state/exit-codes.ts
|
|
24443
25099
|
var STATE_EXIT, StateError, CANCELLED_EXIT_CODE, ORPHAN_EXIT_CODE, CASCADE_CLOSE_EXIT_CODE, WATCHDOG_DEADLINE_EXIT_CODE;
|
|
24444
25100
|
var init_exit_codes = __esm({
|
|
24445
|
-
"src/
|
|
25101
|
+
"../shared/persistence/src/state/exit-codes.ts"() {
|
|
24446
25102
|
"use strict";
|
|
24447
25103
|
STATE_EXIT = {
|
|
24448
25104
|
OK: 0,
|
|
@@ -24469,7 +25125,7 @@ var init_exit_codes = __esm({
|
|
|
24469
25125
|
}
|
|
24470
25126
|
});
|
|
24471
25127
|
|
|
24472
|
-
// src/
|
|
25128
|
+
// ../shared/persistence/src/db/agent-sessions.ts
|
|
24473
25129
|
function cascadeTerminateExecutions(db, workflowId, exitCode, note) {
|
|
24474
25130
|
db.run(
|
|
24475
25131
|
`UPDATE command_executions
|
|
@@ -24640,6 +25296,9 @@ function bindVendorSessionIdOpportunistically(db, vendorSessionId) {
|
|
|
24640
25296
|
);
|
|
24641
25297
|
return candidate.uid ?? String(candidate.id);
|
|
24642
25298
|
}
|
|
25299
|
+
function isSafeVendorSessionId(id) {
|
|
25300
|
+
return SAFE_VENDOR_SESSION_ID.test(id);
|
|
25301
|
+
}
|
|
24643
25302
|
function recordVendorSessionIdForExecution(db, executionId, vendorSessionId) {
|
|
24644
25303
|
db.run(
|
|
24645
25304
|
`UPDATE command_executions
|
|
@@ -24835,9 +25494,9 @@ function sweepStaleSessions(db, thresholdSeconds) {
|
|
|
24835
25494
|
}
|
|
24836
25495
|
return { closedSessionIds: rows.map((r) => r.id) };
|
|
24837
25496
|
}
|
|
24838
|
-
var NOTE_ORPHAN_PREFIX, INSTANCE_COMMAND;
|
|
25497
|
+
var NOTE_ORPHAN_PREFIX, INSTANCE_COMMAND, SAFE_VENDOR_SESSION_ID;
|
|
24839
25498
|
var init_agent_sessions = __esm({
|
|
24840
|
-
"src/
|
|
25499
|
+
"../shared/persistence/src/db/agent-sessions.ts"() {
|
|
24841
25500
|
"use strict";
|
|
24842
25501
|
init_result_mapper();
|
|
24843
25502
|
init_queries();
|
|
@@ -24845,18 +25504,19 @@ var init_agent_sessions = __esm({
|
|
|
24845
25504
|
init_exit_codes();
|
|
24846
25505
|
NOTE_ORPHAN_PREFIX = "orphaned by liveness sweep";
|
|
24847
25506
|
INSTANCE_COMMAND = "session-instance";
|
|
25507
|
+
SAFE_VENDOR_SESSION_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/;
|
|
24848
25508
|
}
|
|
24849
25509
|
});
|
|
24850
25510
|
|
|
24851
|
-
// src/
|
|
25511
|
+
// ../shared/persistence/src/db/maintenance.ts
|
|
24852
25512
|
import {
|
|
24853
|
-
existsSync as
|
|
24854
|
-
readdirSync as
|
|
25513
|
+
existsSync as existsSync8,
|
|
25514
|
+
readdirSync as readdirSync2,
|
|
24855
25515
|
statSync,
|
|
24856
25516
|
unlinkSync as unlinkSync3,
|
|
24857
25517
|
copyFileSync
|
|
24858
25518
|
} from "node:fs";
|
|
24859
|
-
import { dirname as dirname6, join as
|
|
25519
|
+
import { dirname as dirname6, join as join10, basename as basename3 } from "node:path";
|
|
24860
25520
|
function withForeignKeysDisabled(db, fn) {
|
|
24861
25521
|
db.pragma("foreign_keys = OFF");
|
|
24862
25522
|
try {
|
|
@@ -24883,7 +25543,7 @@ function foreignKeyViolationGroups(db) {
|
|
|
24883
25543
|
function scanOrphanTempFiles(dataDir) {
|
|
24884
25544
|
let entries;
|
|
24885
25545
|
try {
|
|
24886
|
-
entries =
|
|
25546
|
+
entries = readdirSync2(dataDir);
|
|
24887
25547
|
} catch {
|
|
24888
25548
|
return [];
|
|
24889
25549
|
}
|
|
@@ -24894,7 +25554,7 @@ function scanOrphanTempFiles(dataDir) {
|
|
|
24894
25554
|
const pid = Number(m[1]);
|
|
24895
25555
|
let ageMs = 0;
|
|
24896
25556
|
try {
|
|
24897
|
-
ageMs = Date.now() - statSync(
|
|
25557
|
+
ageMs = Date.now() - statSync(join10(dataDir, name)).mtimeMs;
|
|
24898
25558
|
} catch {
|
|
24899
25559
|
continue;
|
|
24900
25560
|
}
|
|
@@ -24913,7 +25573,7 @@ function scanOrphanTempFiles(dataDir) {
|
|
|
24913
25573
|
function scanBackupFiles(dataDir, dbBase) {
|
|
24914
25574
|
let entries;
|
|
24915
25575
|
try {
|
|
24916
|
-
entries =
|
|
25576
|
+
entries = readdirSync2(dataDir);
|
|
24917
25577
|
} catch {
|
|
24918
25578
|
return [];
|
|
24919
25579
|
}
|
|
@@ -24921,7 +25581,7 @@ function scanBackupFiles(dataDir, dbBase) {
|
|
|
24921
25581
|
for (const name of entries) {
|
|
24922
25582
|
if (!name.startsWith(`${dbBase}.bak`)) continue;
|
|
24923
25583
|
try {
|
|
24924
|
-
out.push({ name, sizeBytes: statSync(
|
|
25584
|
+
out.push({ name, sizeBytes: statSync(join10(dataDir, name)).size });
|
|
24925
25585
|
} catch {
|
|
24926
25586
|
}
|
|
24927
25587
|
}
|
|
@@ -24929,7 +25589,7 @@ function scanBackupFiles(dataDir, dbBase) {
|
|
|
24929
25589
|
}
|
|
24930
25590
|
function collectDbHealth(db, dbPath) {
|
|
24931
25591
|
const dataDir = dirname6(dbPath);
|
|
24932
|
-
const dbBase =
|
|
25592
|
+
const dbBase = basename3(dbPath);
|
|
24933
25593
|
const pageSize = scalarInt(db, "PRAGMA page_size");
|
|
24934
25594
|
const pageCount = scalarInt(db, "PRAGMA page_count");
|
|
24935
25595
|
const freelistCount = scalarInt(db, "PRAGMA freelist_count");
|
|
@@ -24941,7 +25601,7 @@ function collectDbHealth(db, dbPath) {
|
|
|
24941
25601
|
const protectedFkViolations = allGroups.filter(
|
|
24942
25602
|
(g) => PROTECTED_TABLES.has(g.table)
|
|
24943
25603
|
);
|
|
24944
|
-
const fileSizeBytes =
|
|
25604
|
+
const fileSizeBytes = existsSync8(dbPath) ? statSync(dbPath).size : 0;
|
|
24945
25605
|
return {
|
|
24946
25606
|
dbPath,
|
|
24947
25607
|
fileSizeBytes,
|
|
@@ -24969,7 +25629,7 @@ function collectDbHealth(db, dbPath) {
|
|
|
24969
25629
|
}
|
|
24970
25630
|
function snapshotDb(db, dbPath, label = "doctor") {
|
|
24971
25631
|
try {
|
|
24972
|
-
if (!
|
|
25632
|
+
if (!existsSync8(dbPath) || statSync(dbPath).size === 0) return null;
|
|
24973
25633
|
db.pragma("wal_checkpoint(TRUNCATE)");
|
|
24974
25634
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
24975
25635
|
const bakPath = `${dbPath}.bak.${label}.${ts}`;
|
|
@@ -24984,7 +25644,7 @@ function reapOrphanDbFiles(dataDir) {
|
|
|
24984
25644
|
for (const f of scanOrphanTempFiles(dataDir)) {
|
|
24985
25645
|
if (!f.reapable) continue;
|
|
24986
25646
|
try {
|
|
24987
|
-
unlinkSync3(
|
|
25647
|
+
unlinkSync3(join10(dataDir, f.name));
|
|
24988
25648
|
reaped.push(f.name);
|
|
24989
25649
|
} catch {
|
|
24990
25650
|
}
|
|
@@ -24994,7 +25654,7 @@ function reapOrphanDbFiles(dataDir) {
|
|
|
24994
25654
|
function reapStaleExecLogs(execLogsDir, maxAgeMs = SEVEN_DAYS_MS) {
|
|
24995
25655
|
let entries;
|
|
24996
25656
|
try {
|
|
24997
|
-
entries =
|
|
25657
|
+
entries = readdirSync2(execLogsDir);
|
|
24998
25658
|
} catch {
|
|
24999
25659
|
return [];
|
|
25000
25660
|
}
|
|
@@ -25002,7 +25662,7 @@ function reapStaleExecLogs(execLogsDir, maxAgeMs = SEVEN_DAYS_MS) {
|
|
|
25002
25662
|
const reaped = [];
|
|
25003
25663
|
for (const name of entries) {
|
|
25004
25664
|
if (!name.endsWith(".log")) continue;
|
|
25005
|
-
const full =
|
|
25665
|
+
const full = join10(execLogsDir, name);
|
|
25006
25666
|
try {
|
|
25007
25667
|
if (statSync(full).mtimeMs > cutoff) continue;
|
|
25008
25668
|
unlinkSync3(full);
|
|
@@ -25020,11 +25680,11 @@ function pruneBackups(dataDir, dbPath, opts = {}) {
|
|
|
25020
25680
|
);
|
|
25021
25681
|
}
|
|
25022
25682
|
const dryRun = opts.dryRun ?? false;
|
|
25023
|
-
const dbBase =
|
|
25683
|
+
const dbBase = basename3(dbPath);
|
|
25024
25684
|
const withMtime = [];
|
|
25025
25685
|
for (const file of scanBackupFiles(dataDir, dbBase)) {
|
|
25026
25686
|
try {
|
|
25027
|
-
withMtime.push({ file, mtimeMs: statSync(
|
|
25687
|
+
withMtime.push({ file, mtimeMs: statSync(join10(dataDir, file.name)).mtimeMs });
|
|
25028
25688
|
} catch {
|
|
25029
25689
|
}
|
|
25030
25690
|
}
|
|
@@ -25035,7 +25695,7 @@ function pruneBackups(dataDir, dbPath, opts = {}) {
|
|
|
25035
25695
|
if (!dryRun) {
|
|
25036
25696
|
for (const b of toDelete) {
|
|
25037
25697
|
try {
|
|
25038
|
-
unlinkSync3(
|
|
25698
|
+
unlinkSync3(join10(dataDir, b.name));
|
|
25039
25699
|
deleted.push(b);
|
|
25040
25700
|
} catch {
|
|
25041
25701
|
}
|
|
@@ -25051,7 +25711,7 @@ function pruneBackups(dataDir, dbPath, opts = {}) {
|
|
|
25051
25711
|
}
|
|
25052
25712
|
function fixDb(db, dbPath, opts = {}) {
|
|
25053
25713
|
const dataDir = dirname6(dbPath);
|
|
25054
|
-
const sizeBeforeBytes =
|
|
25714
|
+
const sizeBeforeBytes = existsSync8(dbPath) ? statSync(dbPath).size : 0;
|
|
25055
25715
|
const snapshotPath = opts.snapshot === false ? null : snapshotDb(db, dbPath, "doctor");
|
|
25056
25716
|
const fkOrphansDeleted = [];
|
|
25057
25717
|
withForeignKeysDisabled(db, () => {
|
|
@@ -25095,12 +25755,12 @@ function fixDb(db, dbPath, opts = {}) {
|
|
|
25095
25755
|
};
|
|
25096
25756
|
}
|
|
25097
25757
|
function vacuumDb(db, dbPath, opts = {}) {
|
|
25098
|
-
const sizeBeforeBytes =
|
|
25758
|
+
const sizeBeforeBytes = existsSync8(dbPath) ? statSync(dbPath).size : 0;
|
|
25099
25759
|
const snapshotPath = opts.snapshot === false ? null : snapshotDb(db, dbPath, "vacuum");
|
|
25100
25760
|
db.pragma("wal_checkpoint(TRUNCATE)");
|
|
25101
25761
|
db.run("VACUUM");
|
|
25102
25762
|
db.pragma("wal_checkpoint(TRUNCATE)");
|
|
25103
|
-
const sizeAfterBytes =
|
|
25763
|
+
const sizeAfterBytes = existsSync8(dbPath) ? statSync(dbPath).size : 0;
|
|
25104
25764
|
return {
|
|
25105
25765
|
snapshotPath,
|
|
25106
25766
|
sizeBeforeBytes,
|
|
@@ -25180,7 +25840,7 @@ function pruneDb(db, dbPath, opts = {}) {
|
|
|
25180
25840
|
}
|
|
25181
25841
|
var PROTECTED_TABLES, ORPHAN_SWEEPS, MARKDOWN_DEDUP_SQL, ONE_HOUR_MS, SEVEN_DAYS_MS;
|
|
25182
25842
|
var init_maintenance = __esm({
|
|
25183
|
-
"src/
|
|
25843
|
+
"../shared/persistence/src/db/maintenance.ts"() {
|
|
25184
25844
|
"use strict";
|
|
25185
25845
|
init_src();
|
|
25186
25846
|
PROTECTED_TABLES = /* @__PURE__ */ new Set([
|
|
@@ -25255,24 +25915,24 @@ var init_maintenance = __esm({
|
|
|
25255
25915
|
}
|
|
25256
25916
|
});
|
|
25257
25917
|
|
|
25258
|
-
// src/
|
|
25259
|
-
import { appendFileSync, existsSync as
|
|
25260
|
-
import { dirname as dirname7, join as
|
|
25918
|
+
// ../shared/persistence/src/db/command-log.ts
|
|
25919
|
+
import { appendFileSync, existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync7, renameSync, writeFileSync as writeFileSync6 } from "node:fs";
|
|
25920
|
+
import { dirname as dirname7, join as join11 } from "node:path";
|
|
25261
25921
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
25262
25922
|
function generateCommandUid() {
|
|
25263
25923
|
return randomUUID2();
|
|
25264
25924
|
}
|
|
25265
25925
|
function cacheDir(ocrDir) {
|
|
25266
|
-
return
|
|
25926
|
+
return join11(ocrDir, "data", CACHE_DIR);
|
|
25267
25927
|
}
|
|
25268
25928
|
function commandLogPath(ocrDir) {
|
|
25269
|
-
return
|
|
25929
|
+
return join11(cacheDir(ocrDir), FILENAME);
|
|
25270
25930
|
}
|
|
25271
25931
|
function appendCommandLog(ocrDir, entry) {
|
|
25272
25932
|
try {
|
|
25273
25933
|
const filePath = commandLogPath(ocrDir);
|
|
25274
25934
|
const dir = dirname7(filePath);
|
|
25275
|
-
if (!
|
|
25935
|
+
if (!existsSync9(dir)) mkdirSync4(dir, { recursive: true });
|
|
25276
25936
|
const line = JSON.stringify(entry) + "\n";
|
|
25277
25937
|
appendFileSync(filePath, line, { encoding: "utf-8" });
|
|
25278
25938
|
if (approxLineCount >= 0) approxLineCount++;
|
|
@@ -25282,8 +25942,8 @@ function appendCommandLog(ocrDir, entry) {
|
|
|
25282
25942
|
}
|
|
25283
25943
|
function readCommandLog(ocrDir) {
|
|
25284
25944
|
const filePath = commandLogPath(ocrDir);
|
|
25285
|
-
if (!
|
|
25286
|
-
const content =
|
|
25945
|
+
if (!existsSync9(filePath)) return [];
|
|
25946
|
+
const content = readFileSync7(filePath, "utf-8");
|
|
25287
25947
|
const entries = [];
|
|
25288
25948
|
for (const line of content.split("\n")) {
|
|
25289
25949
|
if (!line.trim()) continue;
|
|
@@ -25334,7 +25994,7 @@ function replayCommandLog(db, ocrDir) {
|
|
|
25334
25994
|
function rotateIfNeeded(filePath) {
|
|
25335
25995
|
try {
|
|
25336
25996
|
if (approxLineCount >= 0 && approxLineCount <= MAX_LINES) return;
|
|
25337
|
-
const content =
|
|
25997
|
+
const content = readFileSync7(filePath, "utf-8");
|
|
25338
25998
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
25339
25999
|
approxLineCount = lines.length;
|
|
25340
26000
|
if (approxLineCount <= MAX_LINES) return;
|
|
@@ -25348,7 +26008,7 @@ function rotateIfNeeded(filePath) {
|
|
|
25348
26008
|
}
|
|
25349
26009
|
var CACHE_DIR, FILENAME, MAX_LINES, KEEP_LINES, approxLineCount;
|
|
25350
26010
|
var init_command_log = __esm({
|
|
25351
|
-
"src/
|
|
26011
|
+
"../shared/persistence/src/db/command-log.ts"() {
|
|
25352
26012
|
"use strict";
|
|
25353
26013
|
CACHE_DIR = ".cache";
|
|
25354
26014
|
FILENAME = "command-history.jsonl";
|
|
@@ -25358,7 +26018,7 @@ var init_command_log = __esm({
|
|
|
25358
26018
|
}
|
|
25359
26019
|
});
|
|
25360
26020
|
|
|
25361
|
-
// src/
|
|
26021
|
+
// ../shared/persistence/src/db/index.ts
|
|
25362
26022
|
var db_exports = {};
|
|
25363
26023
|
__export(db_exports, {
|
|
25364
26024
|
CANCELLED_EXIT_CODE: () => CANCELLED_EXIT_CODE,
|
|
@@ -25366,6 +26026,7 @@ __export(db_exports, {
|
|
|
25366
26026
|
MIGRATIONS: () => MIGRATIONS,
|
|
25367
26027
|
ORPHAN_EXIT_CODE: () => ORPHAN_EXIT_CODE,
|
|
25368
26028
|
PID_REUSE_GUARD_MS: () => PID_REUSE_GUARD_MS,
|
|
26029
|
+
SAFE_VENDOR_SESSION_ID: () => SAFE_VENDOR_SESSION_ID,
|
|
25369
26030
|
STATE_EXIT: () => STATE_EXIT,
|
|
25370
26031
|
StateError: () => StateError,
|
|
25371
26032
|
WATCHDOG_DEADLINE_EXIT_CODE: () => WATCHDOG_DEADLINE_EXIT_CODE,
|
|
@@ -25398,6 +26059,7 @@ __export(db_exports, {
|
|
|
25398
26059
|
insertEvent: () => insertEvent,
|
|
25399
26060
|
insertSession: () => insertSession,
|
|
25400
26061
|
isBusyError: () => isBusyError,
|
|
26062
|
+
isSafeVendorSessionId: () => isSafeVendorSessionId,
|
|
25401
26063
|
linkDashboardInvocationToWorkflow: () => linkDashboardInvocationToWorkflow,
|
|
25402
26064
|
listAgentSessionsForWorkflow: () => listAgentSessionsForWorkflow,
|
|
25403
26065
|
openDatabase: () => openDatabase,
|
|
@@ -25428,7 +26090,7 @@ __export(db_exports, {
|
|
|
25428
26090
|
withForeignKeysDisabled: () => withForeignKeysDisabled
|
|
25429
26091
|
});
|
|
25430
26092
|
import {
|
|
25431
|
-
existsSync as
|
|
26093
|
+
existsSync as existsSync10,
|
|
25432
26094
|
mkdirSync as mkdirSync5,
|
|
25433
26095
|
copyFileSync as copyFileSync2,
|
|
25434
26096
|
statSync as statSync2,
|
|
@@ -25436,13 +26098,13 @@ import {
|
|
|
25436
26098
|
rmSync
|
|
25437
26099
|
} from "node:fs";
|
|
25438
26100
|
import { tmpdir } from "node:os";
|
|
25439
|
-
import { dirname as dirname8, join as
|
|
26101
|
+
import { dirname as dirname8, join as join12 } from "node:path";
|
|
25440
26102
|
function maybeSnapshotBeforeUpgrade(db, dbPath, fromVersion) {
|
|
25441
26103
|
if (fromVersion < 1 || fromVersion >= V2_SCHEMA_VERSION) return null;
|
|
25442
26104
|
const bakPath = `${dbPath}.bak.v${fromVersion}`;
|
|
25443
|
-
if (
|
|
26105
|
+
if (existsSync10(bakPath)) return bakPath;
|
|
25444
26106
|
try {
|
|
25445
|
-
if (!
|
|
26107
|
+
if (!existsSync10(dbPath) || statSync2(dbPath).size === 0) return null;
|
|
25446
26108
|
db.pragma("wal_checkpoint(TRUNCATE)");
|
|
25447
26109
|
copyFileSync2(dbPath, bakPath);
|
|
25448
26110
|
return bakPath;
|
|
@@ -25478,7 +26140,7 @@ async function openDatabase(dbPath) {
|
|
|
25478
26140
|
return cached;
|
|
25479
26141
|
}
|
|
25480
26142
|
const dir = dirname8(dbPath);
|
|
25481
|
-
if (!
|
|
26143
|
+
if (!existsSync10(dir)) {
|
|
25482
26144
|
mkdirSync5(dir, { recursive: true });
|
|
25483
26145
|
}
|
|
25484
26146
|
const db = openEngine(dbPath);
|
|
@@ -25486,15 +26148,15 @@ async function openDatabase(dbPath) {
|
|
|
25486
26148
|
return db;
|
|
25487
26149
|
}
|
|
25488
26150
|
async function getDb(ocrDir) {
|
|
25489
|
-
const dbPath =
|
|
26151
|
+
const dbPath = join12(ocrDir, "data", "ocr.db");
|
|
25490
26152
|
return openDatabase(dbPath);
|
|
25491
26153
|
}
|
|
25492
26154
|
async function ensureDatabase(ocrDir) {
|
|
25493
|
-
const dataDir =
|
|
25494
|
-
if (!
|
|
26155
|
+
const dataDir = join12(ocrDir, "data");
|
|
26156
|
+
if (!existsSync10(dataDir)) {
|
|
25495
26157
|
mkdirSync5(dataDir, { recursive: true });
|
|
25496
26158
|
}
|
|
25497
|
-
const dbPath =
|
|
26159
|
+
const dbPath = join12(dataDir, "ocr.db");
|
|
25498
26160
|
const db = await openDatabase(dbPath);
|
|
25499
26161
|
let before = 0;
|
|
25500
26162
|
try {
|
|
@@ -25522,7 +26184,7 @@ async function ensureDatabase(ocrDir) {
|
|
|
25522
26184
|
return db;
|
|
25523
26185
|
}
|
|
25524
26186
|
function walCheckpointTruncate(dbPath) {
|
|
25525
|
-
if (!
|
|
26187
|
+
if (!existsSync10(dbPath)) {
|
|
25526
26188
|
return "skipped";
|
|
25527
26189
|
}
|
|
25528
26190
|
const cached = connections.get(dbPath);
|
|
@@ -25564,8 +26226,8 @@ function closeAllDatabases() {
|
|
|
25564
26226
|
function probeWrite() {
|
|
25565
26227
|
let dir;
|
|
25566
26228
|
try {
|
|
25567
|
-
dir = mkdtempSync(
|
|
25568
|
-
const db = openEngine(
|
|
26229
|
+
dir = mkdtempSync(join12(tmpdir(), "ocr-probe-"));
|
|
26230
|
+
const db = openEngine(join12(dir, "probe.db"));
|
|
25569
26231
|
try {
|
|
25570
26232
|
db.run("CREATE TABLE _probe_write (id INTEGER PRIMARY KEY, v TEXT)");
|
|
25571
26233
|
db.transaction(() => {
|
|
@@ -25598,7 +26260,7 @@ function rmDirBestEffort(dir) {
|
|
|
25598
26260
|
}
|
|
25599
26261
|
var V2_SCHEMA_VERSION, connections;
|
|
25600
26262
|
var init_db = __esm({
|
|
25601
|
-
"src/
|
|
26263
|
+
"../shared/persistence/src/db/index.ts"() {
|
|
25602
26264
|
"use strict";
|
|
25603
26265
|
init_engine();
|
|
25604
26266
|
init_migrations();
|
|
@@ -26367,7 +27029,7 @@ if (process.platform === "linux") {
|
|
|
26367
27029
|
// ../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.js
|
|
26368
27030
|
var processOk = (process13) => !!process13 && typeof process13 === "object" && typeof process13.removeListener === "function" && typeof process13.emit === "function" && typeof process13.reallyExit === "function" && typeof process13.listeners === "function" && typeof process13.kill === "function" && typeof process13.pid === "number" && typeof process13.on === "function";
|
|
26369
27031
|
var kExitEmitter = Symbol.for("signal-exit emitter");
|
|
26370
|
-
var
|
|
27032
|
+
var global2 = globalThis;
|
|
26371
27033
|
var ObjectDefineProperty = Object.defineProperty.bind(Object);
|
|
26372
27034
|
var Emitter = class {
|
|
26373
27035
|
emitted = {
|
|
@@ -26381,10 +27043,10 @@ var Emitter = class {
|
|
|
26381
27043
|
count = 0;
|
|
26382
27044
|
id = Math.random();
|
|
26383
27045
|
constructor() {
|
|
26384
|
-
if (
|
|
26385
|
-
return
|
|
27046
|
+
if (global2[kExitEmitter]) {
|
|
27047
|
+
return global2[kExitEmitter];
|
|
26386
27048
|
}
|
|
26387
|
-
ObjectDefineProperty(
|
|
27049
|
+
ObjectDefineProperty(global2, kExitEmitter, {
|
|
26388
27050
|
value: this,
|
|
26389
27051
|
writable: false,
|
|
26390
27052
|
enumerable: false,
|
|
@@ -29358,10 +30020,11 @@ function ensureGitignore(ocrDir) {
|
|
|
29358
30020
|
writeFileSync2(gitignorePath, content);
|
|
29359
30021
|
}
|
|
29360
30022
|
|
|
29361
|
-
// src/
|
|
30023
|
+
// ../shared/config/src/team-config.ts
|
|
29362
30024
|
var import_yaml = __toESM(require_dist(), 1);
|
|
29363
30025
|
import { existsSync as existsSync2, readFileSync as readFileSync3 } from "node:fs";
|
|
29364
30026
|
import { join as join2 } from "node:path";
|
|
30027
|
+
var MAX_INSTANCES_PER_PERSONA = 50;
|
|
29365
30028
|
function loadTeamConfig(ocrDir) {
|
|
29366
30029
|
const configPath = join2(ocrDir, "config.yaml");
|
|
29367
30030
|
if (!existsSync2(configPath)) {
|
|
@@ -29403,6 +30066,9 @@ function parseTeamConfigYaml(content) {
|
|
|
29403
30066
|
aliases,
|
|
29404
30067
|
defaultModel
|
|
29405
30068
|
);
|
|
30069
|
+
if (resolvedModel !== null) {
|
|
30070
|
+
assertSafeModelId(resolvedModel, `default_team.${persona}[${i}]`);
|
|
30071
|
+
}
|
|
29406
30072
|
team.push({
|
|
29407
30073
|
persona,
|
|
29408
30074
|
instance_index: i + 1,
|
|
@@ -29420,6 +30086,11 @@ function parseEntry(persona, entry) {
|
|
|
29420
30086
|
`default_team.${persona}: count must be a positive integer (got ${entry})`
|
|
29421
30087
|
);
|
|
29422
30088
|
}
|
|
30089
|
+
if (entry > MAX_INSTANCES_PER_PERSONA) {
|
|
30090
|
+
throw new Error(
|
|
30091
|
+
`default_team.${persona}: count must be <= ${MAX_INSTANCES_PER_PERSONA} (got ${entry})`
|
|
30092
|
+
);
|
|
30093
|
+
}
|
|
29423
30094
|
return Array.from({ length: entry }, () => ({}));
|
|
29424
30095
|
}
|
|
29425
30096
|
if (Array.isArray(entry)) {
|
|
@@ -29428,6 +30099,11 @@ function parseEntry(persona, entry) {
|
|
|
29428
30099
|
`default_team.${persona}: list form must contain at least one instance`
|
|
29429
30100
|
);
|
|
29430
30101
|
}
|
|
30102
|
+
if (entry.length > MAX_INSTANCES_PER_PERSONA) {
|
|
30103
|
+
throw new Error(
|
|
30104
|
+
`default_team.${persona}: list form must contain <= ${MAX_INSTANCES_PER_PERSONA} instances (got ${entry.length})`
|
|
30105
|
+
);
|
|
30106
|
+
}
|
|
29431
30107
|
return entry.map((item, idx) => parseListItem(persona, idx, item));
|
|
29432
30108
|
}
|
|
29433
30109
|
if (entry && typeof entry === "object") {
|
|
@@ -29449,6 +30125,11 @@ function parseEntry(persona, entry) {
|
|
|
29449
30125
|
`default_team.${persona}: count must be a positive integer (got ${String(count)})`
|
|
29450
30126
|
);
|
|
29451
30127
|
}
|
|
30128
|
+
if (count > MAX_INSTANCES_PER_PERSONA) {
|
|
30129
|
+
throw new Error(
|
|
30130
|
+
`default_team.${persona}: count must be <= ${MAX_INSTANCES_PER_PERSONA} (got ${count})`
|
|
30131
|
+
);
|
|
30132
|
+
}
|
|
29452
30133
|
const teamModel = readOptionalString(obj, "model", `default_team.${persona}.model`);
|
|
29453
30134
|
return Array.from({ length: count }, () => ({ teamModel }));
|
|
29454
30135
|
}
|
|
@@ -29483,6 +30164,16 @@ function readOptionalString(obj, key, pathLabel) {
|
|
|
29483
30164
|
}
|
|
29484
30165
|
return value;
|
|
29485
30166
|
}
|
|
30167
|
+
var SAFE_MODEL_ID = /^[A-Za-z0-9][A-Za-z0-9._/:@[\]+-]{0,255}$/;
|
|
30168
|
+
function assertSafeModelId(value, pathLabel) {
|
|
30169
|
+
if (SAFE_MODEL_ID.test(value)) return;
|
|
30170
|
+
const allowed = /[A-Za-z0-9._/:@[\]+-]/;
|
|
30171
|
+
const offending = [...value].find((ch) => !allowed.test(ch));
|
|
30172
|
+
const detail = value.length === 0 ? "empty string" : value.length > 256 ? "longer than 256 characters" : offending !== void 0 ? `contains ${JSON.stringify(offending)}` : `starts with ${JSON.stringify(value[0])}`;
|
|
30173
|
+
throw new Error(
|
|
30174
|
+
`${pathLabel}: model id ${detail} \u2014 no vendor model id uses that. Allowed: letters and digits plus . _ / : @ [ ] + - (max 256 chars).`
|
|
30175
|
+
);
|
|
30176
|
+
}
|
|
29486
30177
|
function readAliases(root) {
|
|
29487
30178
|
const models = root["models"];
|
|
29488
30179
|
if (!models || typeof models !== "object" || Array.isArray(models)) return {};
|
|
@@ -29524,10 +30215,78 @@ function resolveTeamComposition(team, override) {
|
|
|
29524
30215
|
result.push(inst);
|
|
29525
30216
|
}
|
|
29526
30217
|
for (const inst of override) {
|
|
30218
|
+
if (inst.model !== null) {
|
|
30219
|
+
assertSafeModelId(inst.model, `override ${inst.persona}#${inst.instance_index}`);
|
|
30220
|
+
}
|
|
29527
30221
|
result.push(inst);
|
|
29528
30222
|
}
|
|
29529
30223
|
return result;
|
|
29530
30224
|
}
|
|
30225
|
+
var REVIEWER_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
30226
|
+
function parseTeamSpec(spec, aliases = {}, defaultModel = null) {
|
|
30227
|
+
const trimmed = spec.trim();
|
|
30228
|
+
if (trimmed.length === 0) {
|
|
30229
|
+
throw new Error(
|
|
30230
|
+
"--team spec is empty; expected reviewer-id:count[,reviewer-id:count...]"
|
|
30231
|
+
);
|
|
30232
|
+
}
|
|
30233
|
+
const model = resolveModel(null, null, aliases, defaultModel);
|
|
30234
|
+
if (model !== null) assertSafeModelId(model, "--team");
|
|
30235
|
+
const seen = /* @__PURE__ */ new Set();
|
|
30236
|
+
const result = [];
|
|
30237
|
+
for (const rawEntry of trimmed.split(",")) {
|
|
30238
|
+
const entry = rawEntry.trim();
|
|
30239
|
+
if (entry.length === 0) {
|
|
30240
|
+
throw new Error(
|
|
30241
|
+
`--team has an empty entry (stray or trailing comma) in "${spec}"`
|
|
30242
|
+
);
|
|
30243
|
+
}
|
|
30244
|
+
const colon = entry.indexOf(":");
|
|
30245
|
+
if (colon === -1) {
|
|
30246
|
+
throw new Error(
|
|
30247
|
+
`--team entry "${entry}" must be "reviewer-id:count" \u2014 the :count is required`
|
|
30248
|
+
);
|
|
30249
|
+
}
|
|
30250
|
+
const persona = entry.slice(0, colon).trim();
|
|
30251
|
+
const countRaw = entry.slice(colon + 1).trim();
|
|
30252
|
+
if (!REVIEWER_ID_PATTERN.test(persona)) {
|
|
30253
|
+
throw new Error(
|
|
30254
|
+
`--team reviewer id "${persona}" is invalid; expected lowercase letters, digits, and single hyphens (e.g. principal, martin-fowler)`
|
|
30255
|
+
);
|
|
30256
|
+
}
|
|
30257
|
+
if (seen.has(persona)) {
|
|
30258
|
+
throw new Error(
|
|
30259
|
+
`--team lists "${persona}" more than once; combine its instances into a single entry (e.g. ${persona}:2)`
|
|
30260
|
+
);
|
|
30261
|
+
}
|
|
30262
|
+
if (!/^[0-9]+$/.test(countRaw)) {
|
|
30263
|
+
throw new Error(
|
|
30264
|
+
`--team count for "${persona}" must be a positive integer (got "${countRaw}")`
|
|
30265
|
+
);
|
|
30266
|
+
}
|
|
30267
|
+
const count = Number(countRaw);
|
|
30268
|
+
if (count < 1) {
|
|
30269
|
+
throw new Error(
|
|
30270
|
+
`--team count for "${persona}" must be a positive integer (got ${count})`
|
|
30271
|
+
);
|
|
30272
|
+
}
|
|
30273
|
+
if (count > MAX_INSTANCES_PER_PERSONA) {
|
|
30274
|
+
throw new Error(
|
|
30275
|
+
`--team count for "${persona}" must be <= ${MAX_INSTANCES_PER_PERSONA} (got ${count})`
|
|
30276
|
+
);
|
|
30277
|
+
}
|
|
30278
|
+
seen.add(persona);
|
|
30279
|
+
for (let i = 0; i < count; i++) {
|
|
30280
|
+
result.push({
|
|
30281
|
+
persona,
|
|
30282
|
+
instance_index: i + 1,
|
|
30283
|
+
name: `${persona}-${i + 1}`,
|
|
30284
|
+
model
|
|
30285
|
+
});
|
|
30286
|
+
}
|
|
30287
|
+
}
|
|
30288
|
+
return result;
|
|
30289
|
+
}
|
|
29531
30290
|
|
|
29532
30291
|
// src/lib/installer.ts
|
|
29533
30292
|
init_src();
|
|
@@ -30092,7 +30851,7 @@ ${hint}
|
|
|
30092
30851
|
}
|
|
30093
30852
|
|
|
30094
30853
|
// src/lib/version.ts
|
|
30095
|
-
var CLI_VERSION = true ? "2.
|
|
30854
|
+
var CLI_VERSION = true ? "2.4.0" : createRequire(import.meta.url)("../../package.json").version;
|
|
30096
30855
|
|
|
30097
30856
|
// src/lib/deps.ts
|
|
30098
30857
|
init_src();
|
|
@@ -33026,12 +33785,12 @@ function getStrategy(workflowType) {
|
|
|
33026
33785
|
}
|
|
33027
33786
|
|
|
33028
33787
|
// src/lib/progress/detector.ts
|
|
33029
|
-
import { existsSync as
|
|
33030
|
-
import { join as
|
|
33788
|
+
import { existsSync as existsSync11, readdirSync as readdirSync3 } from "node:fs";
|
|
33789
|
+
import { join as join13, basename as basename5 } from "node:path";
|
|
33031
33790
|
|
|
33032
33791
|
// src/lib/progress/session-reader.ts
|
|
33033
|
-
|
|
33034
|
-
import { basename as
|
|
33792
|
+
init_db();
|
|
33793
|
+
import { basename as basename4 } from "node:path";
|
|
33035
33794
|
var cachedDb = null;
|
|
33036
33795
|
function setProgressDb(db) {
|
|
33037
33796
|
cachedDb = db;
|
|
@@ -33050,7 +33809,7 @@ function readSessionState(sessionPath) {
|
|
|
33050
33809
|
}
|
|
33051
33810
|
}
|
|
33052
33811
|
function readFromSqlite(sessionPath, db) {
|
|
33053
|
-
const sessionId =
|
|
33812
|
+
const sessionId = basename4(sessionPath);
|
|
33054
33813
|
let row = resultToRow(
|
|
33055
33814
|
db.exec("SELECT * FROM sessions WHERE id = ?", [sessionId])
|
|
33056
33815
|
);
|
|
@@ -33085,7 +33844,7 @@ function detectWorkflowType(sessionPath, explicitType) {
|
|
|
33085
33844
|
const db = getProgressDb();
|
|
33086
33845
|
if (db) {
|
|
33087
33846
|
try {
|
|
33088
|
-
const sessionId =
|
|
33847
|
+
const sessionId = basename5(sessionPath);
|
|
33089
33848
|
const result = db.exec(
|
|
33090
33849
|
"SELECT workflow_type FROM sessions WHERE id = ?",
|
|
33091
33850
|
[sessionId]
|
|
@@ -33098,8 +33857,8 @@ function detectWorkflowType(sessionPath, explicitType) {
|
|
|
33098
33857
|
} catch {
|
|
33099
33858
|
}
|
|
33100
33859
|
}
|
|
33101
|
-
const hasMapDir =
|
|
33102
|
-
const hasRoundsDir =
|
|
33860
|
+
const hasMapDir = existsSync11(join13(sessionPath, "map"));
|
|
33861
|
+
const hasRoundsDir = existsSync11(join13(sessionPath, "rounds"));
|
|
33103
33862
|
if (hasMapDir && !hasRoundsDir) {
|
|
33104
33863
|
return "map";
|
|
33105
33864
|
}
|
|
@@ -33109,7 +33868,7 @@ function detectWorkflowType(sessionPath, explicitType) {
|
|
|
33109
33868
|
if (hasMapDir && hasRoundsDir) {
|
|
33110
33869
|
if (db) {
|
|
33111
33870
|
try {
|
|
33112
|
-
const sessionId =
|
|
33871
|
+
const sessionId = basename5(sessionPath);
|
|
33113
33872
|
const result = db.exec(
|
|
33114
33873
|
"SELECT current_phase FROM sessions WHERE id = ?",
|
|
33115
33874
|
[sessionId]
|
|
@@ -33133,7 +33892,7 @@ function isSessionActive(sessionPath) {
|
|
|
33133
33892
|
const db = getProgressDb();
|
|
33134
33893
|
if (db) {
|
|
33135
33894
|
try {
|
|
33136
|
-
const sessionId =
|
|
33895
|
+
const sessionId = basename5(sessionPath);
|
|
33137
33896
|
const result = db.exec(
|
|
33138
33897
|
"SELECT status, current_phase FROM sessions WHERE id = ?",
|
|
33139
33898
|
[sessionId]
|
|
@@ -33155,28 +33914,28 @@ function isSessionActive(sessionPath) {
|
|
|
33155
33914
|
}
|
|
33156
33915
|
function detectActiveWorkflows(sessionPath) {
|
|
33157
33916
|
const activeWorkflows = [];
|
|
33158
|
-
const hasRoundsDir =
|
|
33917
|
+
const hasRoundsDir = existsSync11(join13(sessionPath, "rounds"));
|
|
33159
33918
|
if (hasRoundsDir) {
|
|
33160
|
-
const roundsDir =
|
|
33161
|
-
const rounds =
|
|
33919
|
+
const roundsDir = join13(sessionPath, "rounds");
|
|
33920
|
+
const rounds = existsSync11(roundsDir) ? readdirSync3(roundsDir).filter((d) => d.match(/^round-\d+$/)).sort() : [];
|
|
33162
33921
|
if (rounds.length > 0) {
|
|
33163
33922
|
const latestRound = rounds[rounds.length - 1];
|
|
33164
|
-
const finalPath =
|
|
33165
|
-
if (!
|
|
33923
|
+
const finalPath = join13(roundsDir, latestRound, "final.md");
|
|
33924
|
+
if (!existsSync11(finalPath)) {
|
|
33166
33925
|
activeWorkflows.push("review");
|
|
33167
33926
|
}
|
|
33168
33927
|
} else {
|
|
33169
33928
|
activeWorkflows.push("review");
|
|
33170
33929
|
}
|
|
33171
33930
|
}
|
|
33172
|
-
const hasMapDir =
|
|
33931
|
+
const hasMapDir = existsSync11(join13(sessionPath, "map"));
|
|
33173
33932
|
if (hasMapDir) {
|
|
33174
|
-
const runsDir =
|
|
33175
|
-
const runs =
|
|
33933
|
+
const runsDir = join13(sessionPath, "map", "runs");
|
|
33934
|
+
const runs = existsSync11(runsDir) ? readdirSync3(runsDir).filter((d) => d.match(/^run-\d+$/)).sort() : [];
|
|
33176
33935
|
if (runs.length > 0) {
|
|
33177
33936
|
const latestRun = runs[runs.length - 1];
|
|
33178
|
-
const mapPath =
|
|
33179
|
-
if (!
|
|
33937
|
+
const mapPath = join13(runsDir, latestRun, "map.md");
|
|
33938
|
+
if (!existsSync11(mapPath)) {
|
|
33180
33939
|
activeWorkflows.push("map");
|
|
33181
33940
|
}
|
|
33182
33941
|
} else {
|
|
@@ -33187,7 +33946,7 @@ function detectActiveWorkflows(sessionPath) {
|
|
|
33187
33946
|
const db = getProgressDb();
|
|
33188
33947
|
if (db) {
|
|
33189
33948
|
try {
|
|
33190
|
-
const sessionId =
|
|
33949
|
+
const sessionId = basename5(sessionPath);
|
|
33191
33950
|
const result = db.exec(
|
|
33192
33951
|
"SELECT workflow_type, current_phase FROM sessions WHERE id = ?",
|
|
33193
33952
|
[sessionId]
|
|
@@ -33255,8 +34014,8 @@ function padLines(lines) {
|
|
|
33255
34014
|
}
|
|
33256
34015
|
|
|
33257
34016
|
// src/lib/progress/review-strategy.ts
|
|
33258
|
-
import { existsSync as
|
|
33259
|
-
import { join as
|
|
34017
|
+
import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync8 } from "node:fs";
|
|
34018
|
+
import { join as join14, basename as basename6 } from "node:path";
|
|
33260
34019
|
var REVIEW_PHASES = [
|
|
33261
34020
|
{ key: "context", label: "Context Discovery" },
|
|
33262
34021
|
{ key: "change-context", label: "Change Context" },
|
|
@@ -33268,10 +34027,10 @@ var REVIEW_PHASES = [
|
|
|
33268
34027
|
{ key: "complete", label: "Complete" }
|
|
33269
34028
|
];
|
|
33270
34029
|
function countFindings(filePath) {
|
|
33271
|
-
if (!
|
|
34030
|
+
if (!existsSync12(filePath)) {
|
|
33272
34031
|
return 0;
|
|
33273
34032
|
}
|
|
33274
|
-
const content =
|
|
34033
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
33275
34034
|
const findingMatches = content.match(/^##\s+(Finding|Issue|Suggestion)/gm);
|
|
33276
34035
|
return findingMatches?.length ?? 0;
|
|
33277
34036
|
}
|
|
@@ -33285,27 +34044,27 @@ function formatReviewerName(filename) {
|
|
|
33285
34044
|
return base.charAt(0).toUpperCase() + base.slice(1);
|
|
33286
34045
|
}
|
|
33287
34046
|
function deriveRoundsFromFilesystem(roundsDir) {
|
|
33288
|
-
if (!
|
|
34047
|
+
if (!existsSync12(roundsDir)) {
|
|
33289
34048
|
return [];
|
|
33290
34049
|
}
|
|
33291
|
-
const roundDirs =
|
|
34050
|
+
const roundDirs = readdirSync4(roundsDir).filter((d) => d.match(/^round-\d+$/)).sort((a, b) => {
|
|
33292
34051
|
const numA = parseInt(a.replace("round-", ""));
|
|
33293
34052
|
const numB = parseInt(b.replace("round-", ""));
|
|
33294
34053
|
return numA - numB;
|
|
33295
34054
|
});
|
|
33296
34055
|
return roundDirs.map((dir) => {
|
|
33297
34056
|
const roundNum = parseInt(dir.replace("round-", ""));
|
|
33298
|
-
const roundPath =
|
|
33299
|
-
const reviewsPath =
|
|
33300
|
-
const finalPath =
|
|
34057
|
+
const roundPath = join14(roundsDir, dir);
|
|
34058
|
+
const reviewsPath = join14(roundPath, "reviews");
|
|
34059
|
+
const finalPath = join14(roundPath, "final.md");
|
|
33301
34060
|
const reviewers = [];
|
|
33302
|
-
if (
|
|
33303
|
-
const files =
|
|
34061
|
+
if (existsSync12(reviewsPath)) {
|
|
34062
|
+
const files = readdirSync4(reviewsPath).filter((f) => f.endsWith(".md"));
|
|
33304
34063
|
reviewers.push(...files.map((f) => f.replace(".md", "")));
|
|
33305
34064
|
}
|
|
33306
34065
|
return {
|
|
33307
34066
|
round: roundNum,
|
|
33308
|
-
isComplete:
|
|
34067
|
+
isComplete: existsSync12(finalPath),
|
|
33309
34068
|
reviewers
|
|
33310
34069
|
};
|
|
33311
34070
|
});
|
|
@@ -33315,7 +34074,7 @@ var ReviewProgressStrategy = class {
|
|
|
33315
34074
|
phases = REVIEW_PHASES;
|
|
33316
34075
|
totalPhases = 8;
|
|
33317
34076
|
parseState(sessionPath, preservedStartTime) {
|
|
33318
|
-
const session =
|
|
34077
|
+
const session = basename6(sessionPath);
|
|
33319
34078
|
const state = readSessionState(sessionPath);
|
|
33320
34079
|
if (!state) {
|
|
33321
34080
|
return null;
|
|
@@ -33334,19 +34093,19 @@ var ReviewProgressStrategy = class {
|
|
|
33334
34093
|
parseFromState(session, state, sessionPath, preservedStartTime) {
|
|
33335
34094
|
const effectiveStartTime = state.round_started_at ?? state.started_at;
|
|
33336
34095
|
const startTime = preservedStartTime ?? (effectiveStartTime ? new Date(effectiveStartTime).getTime() : Date.now());
|
|
33337
|
-
const roundsDir =
|
|
34096
|
+
const roundsDir = join14(sessionPath, "rounds");
|
|
33338
34097
|
const rounds = deriveRoundsFromFilesystem(roundsDir);
|
|
33339
34098
|
const highestExistingRound = rounds.length > 0 ? Math.max(...rounds.map((r) => r.round)) : 1;
|
|
33340
34099
|
const stateRound = state.current_round ?? 1;
|
|
33341
34100
|
const currentRound = Math.min(stateRound, highestExistingRound);
|
|
33342
|
-
const currentRoundDir =
|
|
33343
|
-
const reviewsDir =
|
|
34101
|
+
const currentRoundDir = join14(roundsDir, `round-${currentRound}`);
|
|
34102
|
+
const reviewsDir = join14(currentRoundDir, "reviews");
|
|
33344
34103
|
const reviewers = [];
|
|
33345
|
-
if (
|
|
33346
|
-
const entries =
|
|
34104
|
+
if (existsSync12(reviewsDir)) {
|
|
34105
|
+
const entries = readdirSync4(reviewsDir);
|
|
33347
34106
|
const reviewFiles = entries.filter((f) => f.endsWith(".md"));
|
|
33348
34107
|
for (const file of reviewFiles) {
|
|
33349
|
-
const reviewPath =
|
|
34108
|
+
const reviewPath = join14(reviewsDir, file);
|
|
33350
34109
|
const findings = countFindings(reviewPath);
|
|
33351
34110
|
reviewers.push({
|
|
33352
34111
|
name: file.replace(".md", ""),
|
|
@@ -33356,14 +34115,14 @@ var ReviewProgressStrategy = class {
|
|
|
33356
34115
|
});
|
|
33357
34116
|
}
|
|
33358
34117
|
}
|
|
33359
|
-
const contextComplete =
|
|
33360
|
-
|
|
34118
|
+
const contextComplete = existsSync12(
|
|
34119
|
+
join14(sessionPath, "discovered-standards.md")
|
|
33361
34120
|
);
|
|
33362
|
-
const changeContextComplete =
|
|
34121
|
+
const changeContextComplete = existsSync12(join14(sessionPath, "context.md"));
|
|
33363
34122
|
const analysisComplete = changeContextComplete;
|
|
33364
34123
|
const reviewsComplete = state.phase_number > 4;
|
|
33365
|
-
const discourseComplete =
|
|
33366
|
-
const synthesisComplete =
|
|
34124
|
+
const discourseComplete = existsSync12(join14(currentRoundDir, "discourse.md"));
|
|
34125
|
+
const synthesisComplete = existsSync12(join14(currentRoundDir, "final.md"));
|
|
33367
34126
|
return {
|
|
33368
34127
|
workflowType: "review",
|
|
33369
34128
|
session,
|
|
@@ -33495,8 +34254,8 @@ var ReviewProgressStrategy = class {
|
|
|
33495
34254
|
var reviewStrategy = new ReviewProgressStrategy();
|
|
33496
34255
|
|
|
33497
34256
|
// src/lib/progress/map-strategy.ts
|
|
33498
|
-
import { existsSync as
|
|
33499
|
-
import { join as
|
|
34257
|
+
import { existsSync as existsSync13, readdirSync as readdirSync5, readFileSync as readFileSync9 } from "node:fs";
|
|
34258
|
+
import { join as join15, basename as basename7 } from "node:path";
|
|
33500
34259
|
var MAP_PHASES = [
|
|
33501
34260
|
{ key: "map-context", label: "Context Discovery" },
|
|
33502
34261
|
{ key: "topology", label: "Topology Analysis" },
|
|
@@ -33506,23 +34265,23 @@ var MAP_PHASES = [
|
|
|
33506
34265
|
{ key: "complete", label: "Complete" }
|
|
33507
34266
|
];
|
|
33508
34267
|
function deriveRunsFromFilesystem(mapDir) {
|
|
33509
|
-
const runsDir =
|
|
33510
|
-
if (!
|
|
34268
|
+
const runsDir = join15(mapDir, "runs");
|
|
34269
|
+
if (!existsSync13(runsDir)) {
|
|
33511
34270
|
return [];
|
|
33512
34271
|
}
|
|
33513
|
-
const runDirs =
|
|
34272
|
+
const runDirs = readdirSync5(runsDir).filter((d) => d.match(/^run-\d+$/)).sort((a, b) => {
|
|
33514
34273
|
const numA = parseInt(a.replace("run-", ""));
|
|
33515
34274
|
const numB = parseInt(b.replace("run-", ""));
|
|
33516
34275
|
return numA - numB;
|
|
33517
34276
|
});
|
|
33518
34277
|
return runDirs.map((dir) => {
|
|
33519
34278
|
const runNum = parseInt(dir.replace("run-", ""));
|
|
33520
|
-
const runPath =
|
|
33521
|
-
const mapPath =
|
|
34279
|
+
const runPath = join15(runsDir, dir);
|
|
34280
|
+
const mapPath = join15(runPath, "map.md");
|
|
33522
34281
|
let fileCount = 0;
|
|
33523
|
-
const topologyPath =
|
|
33524
|
-
if (
|
|
33525
|
-
const content =
|
|
34282
|
+
const topologyPath = join15(runPath, "topology.md");
|
|
34283
|
+
if (existsSync13(topologyPath)) {
|
|
34284
|
+
const content = readFileSync9(topologyPath, "utf-8");
|
|
33526
34285
|
const fileListMatch = content.match(
|
|
33527
34286
|
/## Canonical File List[\s\S]*?```([\s\S]*?)```/
|
|
33528
34287
|
);
|
|
@@ -33532,7 +34291,7 @@ function deriveRunsFromFilesystem(mapDir) {
|
|
|
33532
34291
|
}
|
|
33533
34292
|
return {
|
|
33534
34293
|
run: runNum,
|
|
33535
|
-
isComplete:
|
|
34294
|
+
isComplete: existsSync13(mapPath),
|
|
33536
34295
|
fileCount
|
|
33537
34296
|
};
|
|
33538
34297
|
});
|
|
@@ -33542,7 +34301,7 @@ var MapProgressStrategy = class {
|
|
|
33542
34301
|
phases = MAP_PHASES;
|
|
33543
34302
|
totalPhases = 6;
|
|
33544
34303
|
parseState(sessionPath, preservedStartTime) {
|
|
33545
|
-
const session =
|
|
34304
|
+
const session = basename7(sessionPath);
|
|
33546
34305
|
const state = readSessionState(sessionPath);
|
|
33547
34306
|
if (!state) {
|
|
33548
34307
|
return null;
|
|
@@ -33564,24 +34323,24 @@ var MapProgressStrategy = class {
|
|
|
33564
34323
|
parseFromState(session, state, sessionPath, preservedStartTime) {
|
|
33565
34324
|
const effectiveStartTime = state.map_started_at ?? state.started_at;
|
|
33566
34325
|
const startTime = preservedStartTime ?? (effectiveStartTime ? new Date(effectiveStartTime).getTime() : Date.now());
|
|
33567
|
-
const mapDir =
|
|
34326
|
+
const mapDir = join15(sessionPath, "map");
|
|
33568
34327
|
const runs = deriveRunsFromFilesystem(mapDir);
|
|
33569
34328
|
const highestExistingRun = runs.length > 0 ? Math.max(...runs.map((r) => r.run)) : 1;
|
|
33570
34329
|
const stateRun = state.current_map_run ?? 1;
|
|
33571
34330
|
const currentRun = Math.min(stateRun, highestExistingRun);
|
|
33572
|
-
const currentRunDir =
|
|
33573
|
-
const contextComplete =
|
|
33574
|
-
|
|
34331
|
+
const currentRunDir = join15(mapDir, "runs", `run-${currentRun}`);
|
|
34332
|
+
const contextComplete = existsSync13(
|
|
34333
|
+
join15(sessionPath, "discovered-standards.md")
|
|
33575
34334
|
);
|
|
33576
|
-
const topologyComplete =
|
|
33577
|
-
const flowAnalysisComplete =
|
|
33578
|
-
|
|
34335
|
+
const topologyComplete = existsSync13(join15(currentRunDir, "topology.md"));
|
|
34336
|
+
const flowAnalysisComplete = existsSync13(
|
|
34337
|
+
join15(currentRunDir, "flow-analysis.md")
|
|
33579
34338
|
);
|
|
33580
|
-
const requirementsMappingComplete =
|
|
33581
|
-
|
|
34339
|
+
const requirementsMappingComplete = existsSync13(
|
|
34340
|
+
join15(currentRunDir, "requirements-mapping.md")
|
|
33582
34341
|
);
|
|
33583
|
-
const synthesisComplete =
|
|
33584
|
-
const hasRequirements =
|
|
34342
|
+
const synthesisComplete = existsSync13(join15(currentRunDir, "map.md"));
|
|
34343
|
+
const hasRequirements = existsSync13(join15(sessionPath, "requirements.md"));
|
|
33585
34344
|
const flowAnalysts = flowAnalysisComplete ? [
|
|
33586
34345
|
{
|
|
33587
34346
|
name: "flow-analyst",
|
|
@@ -34036,10 +34795,10 @@ function renderCombinedProgress(sessionPath, preservedStartTimes, ocrDir) {
|
|
|
34036
34795
|
}
|
|
34037
34796
|
|
|
34038
34797
|
// src/commands/state.ts
|
|
34039
|
-
import { existsSync as
|
|
34040
|
-
import { join as
|
|
34798
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync7, readFileSync as readFileSync12, readdirSync as readdirSync8 } from "node:fs";
|
|
34799
|
+
import { join as join19 } from "node:path";
|
|
34041
34800
|
|
|
34042
|
-
// src/
|
|
34801
|
+
// ../shared/persistence/src/state/index.ts
|
|
34043
34802
|
init_db();
|
|
34044
34803
|
init_exit_codes();
|
|
34045
34804
|
import {
|
|
@@ -34052,7 +34811,7 @@ import {
|
|
|
34052
34811
|
} from "node:fs";
|
|
34053
34812
|
import { join as join17 } from "node:path";
|
|
34054
34813
|
|
|
34055
|
-
// src/
|
|
34814
|
+
// ../shared/persistence/src/state/phase-graph.ts
|
|
34056
34815
|
init_exit_codes();
|
|
34057
34816
|
var REVIEW_PHASE_NUMBERS = {
|
|
34058
34817
|
context: 1,
|
|
@@ -34134,7 +34893,7 @@ function validatePhaseTransition(workflowType, source, target, isRoundBoundary)
|
|
|
34134
34893
|
}
|
|
34135
34894
|
}
|
|
34136
34895
|
|
|
34137
|
-
// src/
|
|
34896
|
+
// ../shared/persistence/src/state/meta-util.ts
|
|
34138
34897
|
var DEFAULT_METADATA_MAX_LEN = 4096;
|
|
34139
34898
|
function sanitizeMetadataString(s, opts = {}) {
|
|
34140
34899
|
const maxLen = opts.maxLen ?? DEFAULT_METADATA_MAX_LEN;
|
|
@@ -34144,9 +34903,11 @@ function sanitizeMetadataString(s, opts = {}) {
|
|
|
34144
34903
|
return out;
|
|
34145
34904
|
}
|
|
34146
34905
|
|
|
34147
|
-
// src/
|
|
34906
|
+
// ../shared/persistence/src/state/round-meta.ts
|
|
34907
|
+
init_src();
|
|
34148
34908
|
var VALID_CATEGORIES = /* @__PURE__ */ new Set(["blocker", "should_fix", "suggestion", "style"]);
|
|
34149
34909
|
var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "high", "medium", "low", "info"]);
|
|
34910
|
+
var MIN_TITLE_LEN = 8;
|
|
34150
34911
|
function validateRoundMeta(meta) {
|
|
34151
34912
|
if (!meta || typeof meta !== "object") {
|
|
34152
34913
|
throw new Error("round-meta.json must be a JSON object");
|
|
@@ -34157,10 +34918,16 @@ function validateRoundMeta(meta) {
|
|
|
34157
34918
|
`Unsupported schema_version: ${String(obj.schema_version)}. Expected 1.`
|
|
34158
34919
|
);
|
|
34159
34920
|
}
|
|
34160
|
-
if (typeof obj.verdict !== "string"
|
|
34161
|
-
throw new Error("round-meta.json must contain a
|
|
34921
|
+
if (typeof obj.verdict !== "string") {
|
|
34922
|
+
throw new Error("round-meta.json must contain a verdict string");
|
|
34162
34923
|
}
|
|
34163
|
-
|
|
34924
|
+
const verdict = sanitizeMetadataString(obj.verdict).trim();
|
|
34925
|
+
if (!isCanonicalVerdict(verdict)) {
|
|
34926
|
+
throw new Error(
|
|
34927
|
+
`round-meta.json verdict "${String(obj.verdict)}" is not one of: ${CANONICAL_VERDICTS.join(", ")}`
|
|
34928
|
+
);
|
|
34929
|
+
}
|
|
34930
|
+
obj.verdict = verdict;
|
|
34164
34931
|
if (!Array.isArray(obj.reviewers)) {
|
|
34165
34932
|
throw new Error("round-meta.json must contain a reviewers array");
|
|
34166
34933
|
}
|
|
@@ -34183,8 +34950,10 @@ function validateRoundMeta(meta) {
|
|
|
34183
34950
|
throw new Error("Each finding must be an object");
|
|
34184
34951
|
}
|
|
34185
34952
|
const f = finding;
|
|
34186
|
-
if (typeof f.title !== "string" || f.title.trim().length
|
|
34187
|
-
throw new Error(
|
|
34953
|
+
if (typeof f.title !== "string" || f.title.trim().length < MIN_TITLE_LEN) {
|
|
34954
|
+
throw new Error(
|
|
34955
|
+
`Each finding title must be at least ${MIN_TITLE_LEN} characters; got "${String(f.title)}"`
|
|
34956
|
+
);
|
|
34188
34957
|
}
|
|
34189
34958
|
f.title = sanitizeMetadataString(f.title);
|
|
34190
34959
|
if (typeof f.category !== "string" || !VALID_CATEGORIES.has(f.category)) {
|
|
@@ -34229,25 +34998,144 @@ function validateRoundMeta(meta) {
|
|
|
34229
34998
|
if (typeof sc.suggestions !== "number" || sc.suggestions < 0) {
|
|
34230
34999
|
throw new Error("synthesis_counts.suggestions must be a non-negative number");
|
|
34231
35000
|
}
|
|
35001
|
+
const allFindings = obj.reviewers.flatMap((reviewer) => reviewer.findings);
|
|
35002
|
+
const derived = deriveCounts(allFindings);
|
|
35003
|
+
if (sc.blockers > derived.blocker) {
|
|
35004
|
+
throw new Error(
|
|
35005
|
+
`synthesis_counts.blockers (${sc.blockers}) exceeds the ${derived.blocker} blocker finding(s) present`
|
|
35006
|
+
);
|
|
35007
|
+
}
|
|
35008
|
+
if (sc.should_fix > derived.should_fix) {
|
|
35009
|
+
throw new Error(
|
|
35010
|
+
`synthesis_counts.should_fix (${sc.should_fix}) exceeds the ${derived.should_fix} should_fix finding(s) present`
|
|
35011
|
+
);
|
|
35012
|
+
}
|
|
35013
|
+
if (sc.suggestions > derived.suggestion) {
|
|
35014
|
+
throw new Error(
|
|
35015
|
+
`synthesis_counts.suggestions (${sc.suggestions}) exceeds the ${derived.suggestion} suggestion finding(s) present`
|
|
35016
|
+
);
|
|
35017
|
+
}
|
|
35018
|
+
}
|
|
35019
|
+
const { blockerCount } = resolveRoundCounts(obj);
|
|
35020
|
+
if (verdict === "APPROVE" && blockerCount > 0) {
|
|
35021
|
+
throw new Error(
|
|
35022
|
+
`round-meta.json verdict "APPROVE" is inconsistent with ${blockerCount} blocker finding(s); APPROVE requires zero blockers (use "REQUEST CHANGES", or carry residual work as should_fix/suggestion/style)`
|
|
35023
|
+
);
|
|
35024
|
+
}
|
|
35025
|
+
if (verdict === "REQUEST CHANGES" && blockerCount === 0) {
|
|
35026
|
+
throw new Error(
|
|
35027
|
+
`round-meta.json verdict "REQUEST CHANGES" requires at least one blocker finding; found ${blockerCount} (use "APPROVE" if there is nothing to block on, or "NEEDS DISCUSSION")`
|
|
35028
|
+
);
|
|
34232
35029
|
}
|
|
34233
35030
|
return meta;
|
|
34234
35031
|
}
|
|
34235
35032
|
function computeRoundCounts(meta) {
|
|
34236
|
-
|
|
34237
|
-
|
|
34238
|
-
|
|
35033
|
+
return resolveRoundCounts(meta);
|
|
35034
|
+
}
|
|
35035
|
+
|
|
35036
|
+
// ../shared/persistence/src/state/forward-resume.ts
|
|
35037
|
+
init_db();
|
|
35038
|
+
init_liveness();
|
|
35039
|
+
var FORWARD_RESUME_KIND = "forward_resume";
|
|
35040
|
+
var FORWARD_RESUME_EXHAUSTED_REASON = "forward_resume_exhausted";
|
|
35041
|
+
function parseLeaseMetadata(e) {
|
|
35042
|
+
if (e.event_type !== "session_resumed" || !e.metadata) return null;
|
|
35043
|
+
try {
|
|
35044
|
+
return JSON.parse(e.metadata);
|
|
35045
|
+
} catch {
|
|
35046
|
+
return null;
|
|
35047
|
+
}
|
|
35048
|
+
}
|
|
35049
|
+
function remainingPhasesAfter(workflowType, currentPhase) {
|
|
35050
|
+
const numbers = workflowType === "map" ? MAP_PHASE_NUMBERS : REVIEW_PHASE_NUMBERS;
|
|
35051
|
+
const cur = numbers[currentPhase];
|
|
35052
|
+
if (cur === void 0) return [];
|
|
35053
|
+
return Object.entries(numbers).filter(([, n]) => n > cur).sort((a, b) => a[1] - b[1]).map(([phase]) => phase);
|
|
35054
|
+
}
|
|
35055
|
+
function countForwardResumeLeases(events, round) {
|
|
35056
|
+
return events.filter((e) => parseLeaseMetadata(e)?.kind === FORWARD_RESUME_KIND && parseLeaseMetadata(e)?.round === round).length;
|
|
35057
|
+
}
|
|
35058
|
+
function forwardResumeLeaseState(events, round, leaseMs, nowMs) {
|
|
35059
|
+
const leases = events.filter(
|
|
35060
|
+
(e) => parseLeaseMetadata(e)?.kind === FORWARD_RESUME_KIND && parseLeaseMetadata(e)?.round === round
|
|
35061
|
+
);
|
|
35062
|
+
if (leases.length === 0) return { leaseCount: 0, activeLeaseHeld: false };
|
|
35063
|
+
const latestLease = leases[leases.length - 1];
|
|
35064
|
+
const latestLeaseMs = sqliteUtcMs(latestLease.created_at);
|
|
35065
|
+
let effectiveMs = latestLeaseMs;
|
|
35066
|
+
for (const e of events) {
|
|
35067
|
+
if (e.event_type === "phase_transition" && (e.round == null || e.round === round)) {
|
|
35068
|
+
const t = sqliteUtcMs(e.created_at);
|
|
35069
|
+
if (t >= latestLeaseMs && t > effectiveMs) effectiveMs = t;
|
|
35070
|
+
}
|
|
34239
35071
|
}
|
|
34240
|
-
const sc = meta.synthesis_counts;
|
|
34241
35072
|
return {
|
|
34242
|
-
|
|
34243
|
-
|
|
34244
|
-
|
|
34245
|
-
|
|
34246
|
-
|
|
35073
|
+
leaseCount: leases.length,
|
|
35074
|
+
activeLeaseHeld: nowMs - effectiveMs < leaseMs
|
|
35075
|
+
};
|
|
35076
|
+
}
|
|
35077
|
+
function tryAcquireForwardResumeLease(db, sessionId, round, opts) {
|
|
35078
|
+
const nowMs = opts.nowMs ?? Date.now();
|
|
35079
|
+
return db.transaction(() => {
|
|
35080
|
+
const events = getEventsForSession(db, sessionId);
|
|
35081
|
+
const { leaseCount, activeLeaseHeld } = forwardResumeLeaseState(
|
|
35082
|
+
events,
|
|
35083
|
+
round,
|
|
35084
|
+
opts.leaseMs,
|
|
35085
|
+
nowMs
|
|
35086
|
+
);
|
|
35087
|
+
if (leaseCount >= opts.maxAttempts) {
|
|
35088
|
+
return { acquired: false, reason: "cap_exhausted", attemptsUsed: leaseCount };
|
|
35089
|
+
}
|
|
35090
|
+
if (activeLeaseHeld) {
|
|
35091
|
+
return { acquired: false, reason: "lease_held", attemptsUsed: leaseCount };
|
|
35092
|
+
}
|
|
35093
|
+
insertEvent(db, {
|
|
35094
|
+
session_id: sessionId,
|
|
35095
|
+
event_type: "session_resumed",
|
|
35096
|
+
metadata: JSON.stringify({ kind: FORWARD_RESUME_KIND, round })
|
|
35097
|
+
});
|
|
35098
|
+
return { acquired: true, attemptsUsed: leaseCount + 1 };
|
|
35099
|
+
});
|
|
35100
|
+
}
|
|
35101
|
+
function hasLiveOwningTurn(db, sessionId, heartbeatMs, nowMs) {
|
|
35102
|
+
const instances = listAgentSessionsForWorkflow(db, sessionId);
|
|
35103
|
+
return instances.some(
|
|
35104
|
+
(s) => s.ended_at == null && nowMs - sqliteUtcMs(s.last_heartbeat_at) <= heartbeatMs
|
|
35105
|
+
);
|
|
35106
|
+
}
|
|
35107
|
+
function deriveStrandedStatus(db, session, cfg) {
|
|
35108
|
+
const nowMs = cfg.nowMs ?? Date.now();
|
|
35109
|
+
if (hasLiveOwningTurn(db, session.id, cfg.heartbeatMs, nowMs)) return null;
|
|
35110
|
+
return strandedActionByCap(db, session, cfg.maxAttempts);
|
|
35111
|
+
}
|
|
35112
|
+
function strandedActionByCap(db, session, maxAttempts) {
|
|
35113
|
+
const events = getEventsForSession(db, session.id);
|
|
35114
|
+
const leaseCount = countForwardResumeLeases(events, session.current_round);
|
|
35115
|
+
const workflowType = session.workflow_type === "map" ? "map" : "review";
|
|
35116
|
+
return {
|
|
35117
|
+
action: leaseCount >= maxAttempts ? "abort_or_fresh" : "forward_resume",
|
|
35118
|
+
remainingPhases: remainingPhasesAfter(workflowType, session.current_phase),
|
|
35119
|
+
attemptsRemaining: Math.max(0, maxAttempts - leaseCount)
|
|
34247
35120
|
};
|
|
34248
35121
|
}
|
|
35122
|
+
function closeForwardResumeExhausted(db, sessionId, attempts) {
|
|
35123
|
+
commitReasonClose(
|
|
35124
|
+
db,
|
|
35125
|
+
sessionId,
|
|
35126
|
+
{
|
|
35127
|
+
event_type: "session_auto_closed_stale",
|
|
35128
|
+
phase: "complete",
|
|
35129
|
+
metadata: JSON.stringify({
|
|
35130
|
+
reason: FORWARD_RESUME_EXHAUSTED_REASON,
|
|
35131
|
+
attempts
|
|
35132
|
+
})
|
|
35133
|
+
},
|
|
35134
|
+
{ status: "closed", current_phase: "complete" }
|
|
35135
|
+
);
|
|
35136
|
+
}
|
|
34249
35137
|
|
|
34250
|
-
// src/
|
|
35138
|
+
// ../shared/persistence/src/state/map-meta.ts
|
|
34251
35139
|
function validateMapMeta(meta) {
|
|
34252
35140
|
if (!meta || typeof meta !== "object") {
|
|
34253
35141
|
throw new Error("map-meta.json must be a JSON object");
|
|
@@ -34314,7 +35202,7 @@ function computeMapCounts(meta) {
|
|
|
34314
35202
|
};
|
|
34315
35203
|
}
|
|
34316
35204
|
|
|
34317
|
-
// src/
|
|
35205
|
+
// ../shared/persistence/src/state/projection.ts
|
|
34318
35206
|
init_db();
|
|
34319
35207
|
var REASON_EVENT_TYPES = [
|
|
34320
35208
|
"session_aborted",
|
|
@@ -34344,7 +35232,7 @@ function getCompletenessState(db, sessionId) {
|
|
|
34344
35232
|
return r[0]?.values[0]?.[0] ?? null;
|
|
34345
35233
|
}
|
|
34346
35234
|
|
|
34347
|
-
// src/
|
|
35235
|
+
// ../shared/persistence/src/state/index.ts
|
|
34348
35236
|
init_exit_codes();
|
|
34349
35237
|
function deriveNextRound(db, sessionId, fallbackRound) {
|
|
34350
35238
|
const result = db.exec(
|
|
@@ -34399,6 +35287,12 @@ async function stateInit(params) {
|
|
|
34399
35287
|
`Cannot re-open session ${sessionId} as workflow_type "${workflowType}": existing workflow_type is "${existing.workflow_type}". Maps and reviews have disjoint phase graphs.`
|
|
34400
35288
|
);
|
|
34401
35289
|
}
|
|
35290
|
+
if (existing.status === "active" && !hasCompletionInvariant(db, existing)) {
|
|
35291
|
+
throw new StateError(
|
|
35292
|
+
STATE_EXIT.INVARIANT_UNMET,
|
|
35293
|
+
`Session ${sessionId} is active and its current round is not complete \u2014 'begin' would reset it to "${initialPhaseFor(workflowType)}" and lose progress. Forward-resume instead: re-run the review (it continues from current_phase via 'ocr state status --json'), or 'ocr review --resume ${sessionId}'.`
|
|
35294
|
+
);
|
|
35295
|
+
}
|
|
34402
35296
|
const nextRound = deriveNextRound(db, sessionId, existing.current_round);
|
|
34403
35297
|
const initialPhase2 = workflowType === "map" ? "map-context" : "context";
|
|
34404
35298
|
db.transaction(() => {
|
|
@@ -34698,18 +35592,19 @@ async function stateCompleteRound(params) {
|
|
|
34698
35592
|
}
|
|
34699
35593
|
const resolved = resolveSession(db, params.sessionId);
|
|
34700
35594
|
const roundNumber = params.round ?? resolved.current_round;
|
|
34701
|
-
const
|
|
34702
|
-
|
|
34703
|
-
|
|
34704
|
-
|
|
34705
|
-
|
|
34706
|
-
|
|
35595
|
+
const roundDir = join17(resolved.session_dir, "rounds", `round-${roundNumber}`);
|
|
35596
|
+
const roundMetaPath = join17(roundDir, "round-meta.json");
|
|
35597
|
+
const materializeArtifact = () => {
|
|
35598
|
+
mkdirSync6(roundDir, { recursive: true });
|
|
35599
|
+
writeFileSync7(roundMetaPath, JSON.stringify(meta, null, 2));
|
|
35600
|
+
};
|
|
34707
35601
|
const already = db.exec(
|
|
34708
35602
|
`SELECT 1 FROM orchestration_events
|
|
34709
35603
|
WHERE session_id = ? AND event_type = 'round_completed' AND round = ? LIMIT 1`,
|
|
34710
35604
|
[resolved.id, roundNumber]
|
|
34711
35605
|
);
|
|
34712
35606
|
if ((already[0]?.values.length ?? 0) > 0) {
|
|
35607
|
+
if (!existsSync15(roundMetaPath)) materializeArtifact();
|
|
34713
35608
|
return { sessionId: resolved.id, round: roundNumber, metaPath: roundMetaPath, schema_version: 1 };
|
|
34714
35609
|
}
|
|
34715
35610
|
if (resolved.current_phase !== "synthesis") {
|
|
@@ -34719,7 +35614,7 @@ async function stateCompleteRound(params) {
|
|
|
34719
35614
|
);
|
|
34720
35615
|
}
|
|
34721
35616
|
if (params.requireFinal) {
|
|
34722
|
-
const finalPath = join17(
|
|
35617
|
+
const finalPath = join17(roundDir, "final.md");
|
|
34723
35618
|
if (!existsSync15(finalPath)) {
|
|
34724
35619
|
throw new StateError(
|
|
34725
35620
|
STATE_EXIT.INVARIANT_UNMET,
|
|
@@ -34727,13 +35622,8 @@ async function stateCompleteRound(params) {
|
|
|
34727
35622
|
);
|
|
34728
35623
|
}
|
|
34729
35624
|
}
|
|
34730
|
-
|
|
34731
|
-
|
|
34732
|
-
const roundDir = join17(resolved.session_dir, "rounds", `round-${roundNumber}`);
|
|
34733
|
-
mkdirSync6(roundDir, { recursive: true });
|
|
34734
|
-
metaPath = roundMetaPath;
|
|
34735
|
-
writeFileSync7(metaPath, JSON.stringify(meta, null, 2));
|
|
34736
|
-
}
|
|
35625
|
+
materializeArtifact();
|
|
35626
|
+
const metaPath = roundMetaPath;
|
|
34737
35627
|
db.transaction(() => {
|
|
34738
35628
|
insertEvent(db, {
|
|
34739
35629
|
session_id: resolved.id,
|
|
@@ -34784,19 +35674,19 @@ async function stateCompleteMap(params) {
|
|
|
34784
35674
|
}
|
|
34785
35675
|
const resolved = resolveSession(db, params.sessionId);
|
|
34786
35676
|
const mapRunNumber = params.mapRun ?? resolved.current_map_run;
|
|
34787
|
-
const
|
|
34788
|
-
|
|
34789
|
-
|
|
34790
|
-
|
|
34791
|
-
|
|
34792
|
-
|
|
34793
|
-
);
|
|
35677
|
+
const runDir = join17(resolved.session_dir, "map", "runs", `run-${mapRunNumber}`);
|
|
35678
|
+
const mapMetaPath = join17(runDir, "map-meta.json");
|
|
35679
|
+
const materializeArtifact = () => {
|
|
35680
|
+
mkdirSync6(runDir, { recursive: true });
|
|
35681
|
+
writeFileSync7(mapMetaPath, JSON.stringify(meta, null, 2));
|
|
35682
|
+
};
|
|
34794
35683
|
const already = db.exec(
|
|
34795
35684
|
`SELECT 1 FROM orchestration_events
|
|
34796
35685
|
WHERE session_id = ? AND event_type = 'map_completed' AND round = ? LIMIT 1`,
|
|
34797
35686
|
[resolved.id, mapRunNumber]
|
|
34798
35687
|
);
|
|
34799
35688
|
if ((already[0]?.values.length ?? 0) > 0) {
|
|
35689
|
+
if (!existsSync15(mapMetaPath)) materializeArtifact();
|
|
34800
35690
|
return { sessionId: resolved.id, mapRun: mapRunNumber, metaPath: mapMetaPath, schema_version: 1 };
|
|
34801
35691
|
}
|
|
34802
35692
|
if (resolved.current_phase !== "synthesis") {
|
|
@@ -34805,13 +35695,8 @@ async function stateCompleteMap(params) {
|
|
|
34805
35695
|
`Cannot complete map: workflow is at "${resolved.current_phase}", not "synthesis". Advance first.`
|
|
34806
35696
|
);
|
|
34807
35697
|
}
|
|
34808
|
-
|
|
34809
|
-
|
|
34810
|
-
const runDir = join17(resolved.session_dir, "map", "runs", `run-${mapRunNumber}`);
|
|
34811
|
-
mkdirSync6(runDir, { recursive: true });
|
|
34812
|
-
metaPath = mapMetaPath;
|
|
34813
|
-
writeFileSync7(metaPath, JSON.stringify(meta, null, 2));
|
|
34814
|
-
}
|
|
35698
|
+
materializeArtifact();
|
|
35699
|
+
const metaPath = mapMetaPath;
|
|
34815
35700
|
db.transaction(() => {
|
|
34816
35701
|
insertEvent(db, {
|
|
34817
35702
|
session_id: resolved.id,
|
|
@@ -34837,7 +35722,7 @@ async function stateCompleteMap(params) {
|
|
|
34837
35722
|
});
|
|
34838
35723
|
return { sessionId: resolved.id, mapRun: mapRunNumber, metaPath, schema_version: 1 };
|
|
34839
35724
|
}
|
|
34840
|
-
async function stateStatus(ocrDir, sessionId) {
|
|
35725
|
+
async function stateStatus(ocrDir, sessionId, forwardResume) {
|
|
34841
35726
|
const db = await ensureDatabase(ocrDir);
|
|
34842
35727
|
const resolved = resolveSession(db, sessionId);
|
|
34843
35728
|
const view = db.exec(
|
|
@@ -34850,6 +35735,8 @@ async function stateStatus(ocrDir, sessionId) {
|
|
|
34850
35735
|
const hasTerminalArtifact = row?.[1] === 1;
|
|
34851
35736
|
let nextAction;
|
|
34852
35737
|
let nextActionKind;
|
|
35738
|
+
let remainingPhases;
|
|
35739
|
+
let attemptsRemaining;
|
|
34853
35740
|
switch (completenessState) {
|
|
34854
35741
|
case "complete":
|
|
34855
35742
|
nextAction = "none \u2014 session is complete";
|
|
@@ -34867,12 +35754,25 @@ async function stateStatus(ocrDir, sessionId) {
|
|
|
34867
35754
|
if (hasTerminalArtifact) {
|
|
34868
35755
|
nextAction = "run 'ocr state finish' to close the workflow";
|
|
34869
35756
|
nextActionKind = "finish";
|
|
34870
|
-
} else if (resolved.current_phase === "synthesis") {
|
|
34871
|
-
nextAction = "pipe round metadata to 'ocr state complete-round --stdin'";
|
|
34872
|
-
nextActionKind = "complete_round";
|
|
34873
35757
|
} else {
|
|
34874
|
-
|
|
34875
|
-
|
|
35758
|
+
const stranded = forwardResume && resolved.status === "active" ? deriveStrandedStatus(db, resolved, forwardResume) : null;
|
|
35759
|
+
if (stranded) {
|
|
35760
|
+
remainingPhases = stranded.remainingPhases;
|
|
35761
|
+
attemptsRemaining = stranded.attemptsRemaining;
|
|
35762
|
+
if (stranded.action === "forward_resume") {
|
|
35763
|
+
nextAction = `forward-resume from '${resolved.current_phase}': re-run the review (it continues via 'ocr state status --json'), or 'ocr review --resume ${resolved.id}'`;
|
|
35764
|
+
nextActionKind = "forward_resume";
|
|
35765
|
+
} else {
|
|
35766
|
+
nextAction = "forward-resume attempts exhausted \u2014 abort with 'ocr state finish --abort' or start a fresh review";
|
|
35767
|
+
nextActionKind = "abort_or_fresh";
|
|
35768
|
+
}
|
|
35769
|
+
} else if (resolved.current_phase === "synthesis") {
|
|
35770
|
+
nextAction = "pipe round metadata to 'ocr state complete-round --stdin'";
|
|
35771
|
+
nextActionKind = "complete_round";
|
|
35772
|
+
} else {
|
|
35773
|
+
nextAction = "advance through the phases, then 'ocr state complete-round'";
|
|
35774
|
+
nextActionKind = "advance";
|
|
35775
|
+
}
|
|
34876
35776
|
}
|
|
34877
35777
|
}
|
|
34878
35778
|
return {
|
|
@@ -34888,7 +35788,9 @@ async function stateStatus(ocrDir, sessionId) {
|
|
|
34888
35788
|
marked_closed: row?.[2] === 1,
|
|
34889
35789
|
dependents_settled: row?.[3] === 1,
|
|
34890
35790
|
next_action: nextAction,
|
|
34891
|
-
next_action_kind: nextActionKind
|
|
35791
|
+
next_action_kind: nextActionKind,
|
|
35792
|
+
...remainingPhases ? { remaining_phases: remainingPhases } : {},
|
|
35793
|
+
...attemptsRemaining !== void 0 ? { forward_resume_attempts_remaining: attemptsRemaining } : {}
|
|
34892
35794
|
};
|
|
34893
35795
|
}
|
|
34894
35796
|
async function stateSync(ocrDir) {
|
|
@@ -34976,14 +35878,73 @@ async function stateSync(ocrDir) {
|
|
|
34976
35878
|
}
|
|
34977
35879
|
|
|
34978
35880
|
// src/commands/state.ts
|
|
34979
|
-
init_command_log();
|
|
34980
35881
|
init_db();
|
|
34981
35882
|
init_db();
|
|
34982
|
-
|
|
34983
|
-
|
|
35883
|
+
|
|
35884
|
+
// ../shared/config/src/runtime-config.ts
|
|
35885
|
+
import { existsSync as existsSync16, readFileSync as readFileSync11 } from "node:fs";
|
|
35886
|
+
import { join as join18 } from "node:path";
|
|
35887
|
+
var DEFAULT_AGENT_HEARTBEAT_SECONDS = 60;
|
|
35888
|
+
var DEFAULT_FORWARD_RESUME_MAX_ATTEMPTS = 2;
|
|
35889
|
+
var DEFAULT_FORWARD_RESUME_LEASE_SECONDS = 1800;
|
|
35890
|
+
function readRuntimePositiveInt(ocrDir, key, defaultValue) {
|
|
35891
|
+
const configPath = join18(ocrDir, "config.yaml");
|
|
35892
|
+
if (!existsSync16(configPath)) return defaultValue;
|
|
35893
|
+
let content;
|
|
35894
|
+
try {
|
|
35895
|
+
content = readFileSync11(configPath, "utf-8");
|
|
35896
|
+
} catch {
|
|
35897
|
+
return defaultValue;
|
|
35898
|
+
}
|
|
35899
|
+
const blockMatch = content.match(
|
|
35900
|
+
new RegExp(
|
|
35901
|
+
String.raw`^runtime:\s*\n(?:\s+[^\n]*\n)*?\s+${key}:\s*([^\s#\n]+)`,
|
|
35902
|
+
"m"
|
|
35903
|
+
)
|
|
35904
|
+
);
|
|
35905
|
+
const inlineMatch = content.match(
|
|
35906
|
+
new RegExp(String.raw`^runtime:\s*\{[^}]*\b${key}:\s*([^\s,}]+)`, "m")
|
|
35907
|
+
);
|
|
35908
|
+
const raw = blockMatch?.[1] ?? inlineMatch?.[1];
|
|
35909
|
+
if (!raw) return defaultValue;
|
|
35910
|
+
const parsed = Number(raw);
|
|
35911
|
+
if (!Number.isFinite(parsed) || parsed <= 0 || !Number.isInteger(parsed)) {
|
|
35912
|
+
process.stderr.write(
|
|
35913
|
+
`[ocr] runtime.${key} is not a positive integer (got "${raw}"); falling back to ${defaultValue}.
|
|
35914
|
+
`
|
|
35915
|
+
);
|
|
35916
|
+
return defaultValue;
|
|
35917
|
+
}
|
|
35918
|
+
return parsed;
|
|
35919
|
+
}
|
|
35920
|
+
function getAgentHeartbeatSeconds(ocrDir) {
|
|
35921
|
+
return readRuntimePositiveInt(
|
|
35922
|
+
ocrDir,
|
|
35923
|
+
"agent_heartbeat_seconds",
|
|
35924
|
+
DEFAULT_AGENT_HEARTBEAT_SECONDS
|
|
35925
|
+
);
|
|
35926
|
+
}
|
|
35927
|
+
function getForwardResumeMaxAttempts(ocrDir) {
|
|
35928
|
+
return readRuntimePositiveInt(
|
|
35929
|
+
ocrDir,
|
|
35930
|
+
"forward_resume_max_attempts",
|
|
35931
|
+
DEFAULT_FORWARD_RESUME_MAX_ATTEMPTS
|
|
35932
|
+
);
|
|
35933
|
+
}
|
|
35934
|
+
function getForwardResumeLeaseMs(ocrDir) {
|
|
35935
|
+
return readRuntimePositiveInt(
|
|
35936
|
+
ocrDir,
|
|
35937
|
+
"forward_resume_lease_seconds",
|
|
35938
|
+
DEFAULT_FORWARD_RESUME_LEASE_SECONDS
|
|
35939
|
+
) * 1e3;
|
|
35940
|
+
}
|
|
35941
|
+
|
|
35942
|
+
// src/commands/state.ts
|
|
35943
|
+
init_db();
|
|
35944
|
+
function readMarkerFile(path2) {
|
|
34984
35945
|
let raw;
|
|
34985
35946
|
try {
|
|
34986
|
-
raw =
|
|
35947
|
+
raw = readFileSync12(path2, "utf-8");
|
|
34987
35948
|
} catch {
|
|
34988
35949
|
return null;
|
|
34989
35950
|
}
|
|
@@ -35004,6 +35965,30 @@ function readDashboardSpawnMarker(ocrDir) {
|
|
|
35004
35965
|
}
|
|
35005
35966
|
return marker;
|
|
35006
35967
|
}
|
|
35968
|
+
function readDashboardSpawnMarker(ocrDir) {
|
|
35969
|
+
const dir = join19(ocrDir, "data", "dashboard-active-spawn");
|
|
35970
|
+
let entries = [];
|
|
35971
|
+
try {
|
|
35972
|
+
entries = readdirSync8(dir).filter((f) => f.endsWith(".json"));
|
|
35973
|
+
} catch {
|
|
35974
|
+
entries = [];
|
|
35975
|
+
}
|
|
35976
|
+
const live = [];
|
|
35977
|
+
for (const entry of entries) {
|
|
35978
|
+
const marker = readMarkerFile(join19(dir, entry));
|
|
35979
|
+
if (marker) live.push(marker);
|
|
35980
|
+
}
|
|
35981
|
+
if (live.length === 1) return live[0] ?? null;
|
|
35982
|
+
if (live.length > 1) {
|
|
35983
|
+
console.error(
|
|
35984
|
+
source_default.gray(
|
|
35985
|
+
`[state] ${live.length} concurrent dashboard spawns live; marker fallback is ambiguous \u2014 pass --dashboard-uid for linkage`
|
|
35986
|
+
)
|
|
35987
|
+
);
|
|
35988
|
+
return null;
|
|
35989
|
+
}
|
|
35990
|
+
return readMarkerFile(join19(ocrDir, "data", "dashboard-active-spawn.json"));
|
|
35991
|
+
}
|
|
35007
35992
|
async function readStdin() {
|
|
35008
35993
|
const chunks = [];
|
|
35009
35994
|
for await (const chunk of process.stdin) {
|
|
@@ -35045,7 +36030,7 @@ async function linkDashboardInvocation(ocrDir, sessionId, explicitUid, label) {
|
|
|
35045
36030
|
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) => {
|
|
35046
36031
|
const targetDir = process.cwd();
|
|
35047
36032
|
requireOcrSetup(targetDir);
|
|
35048
|
-
const ocrDir =
|
|
36033
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35049
36034
|
try {
|
|
35050
36035
|
const result = await stateShow(ocrDir, options.sessionId);
|
|
35051
36036
|
if (!result) {
|
|
@@ -35114,7 +36099,7 @@ var showSubcommand = new Command("show").description("Show current session state
|
|
|
35114
36099
|
var syncSubcommand = new Command("sync").description("Rebuild session state from filesystem artifacts").action(async () => {
|
|
35115
36100
|
const targetDir = process.cwd();
|
|
35116
36101
|
requireOcrSetup(targetDir);
|
|
35117
|
-
const ocrDir =
|
|
36102
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35118
36103
|
try {
|
|
35119
36104
|
const synced = await stateSync(ocrDir);
|
|
35120
36105
|
console.log(`Synced ${synced} session${synced !== 1 ? "s" : ""} from filesystem.`);
|
|
@@ -35141,7 +36126,7 @@ var reconcileSubcommand = new Command("reconcile").description(
|
|
|
35141
36126
|
).option("--dry-run", "Print the repair plan without writing anything").option("--json", "Output the result as JSON").action(async (options) => {
|
|
35142
36127
|
const targetDir = process.cwd();
|
|
35143
36128
|
requireOcrSetup(targetDir);
|
|
35144
|
-
const ocrDir =
|
|
36129
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35145
36130
|
try {
|
|
35146
36131
|
const db = await ensureDatabase(ocrDir);
|
|
35147
36132
|
const result = reconcileLegacyState(db, ocrDir, { dryRun: options.dryRun });
|
|
@@ -35200,9 +36185,9 @@ var beginSubcommand = new Command("begin").description("Start or resume a workfl
|
|
|
35200
36185
|
async (options) => {
|
|
35201
36186
|
const targetDir = process.cwd();
|
|
35202
36187
|
requireOcrSetup(targetDir);
|
|
35203
|
-
const ocrDir =
|
|
35204
|
-
const sessionDir = options.sessionDir ??
|
|
35205
|
-
if (!
|
|
36188
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
36189
|
+
const sessionDir = options.sessionDir ?? join19(ocrDir, "sessions", options.sessionId);
|
|
36190
|
+
if (!existsSync17(sessionDir)) mkdirSync7(sessionDir, { recursive: true });
|
|
35206
36191
|
try {
|
|
35207
36192
|
const result = await stateBegin({
|
|
35208
36193
|
sessionId: options.sessionId,
|
|
@@ -35224,7 +36209,7 @@ var advanceSubcommand = new Command("advance").description("Advance the workflow
|
|
|
35224
36209
|
async (options) => {
|
|
35225
36210
|
const targetDir = process.cwd();
|
|
35226
36211
|
requireOcrSetup(targetDir);
|
|
35227
|
-
const ocrDir =
|
|
36212
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35228
36213
|
try {
|
|
35229
36214
|
const { id: sessionId } = await resolveActiveSession(ocrDir, options.sessionId);
|
|
35230
36215
|
await stateAdvance({
|
|
@@ -35244,7 +36229,7 @@ var completeRoundSubcommand = new Command("complete-round").description("Atomica
|
|
|
35244
36229
|
async (options) => {
|
|
35245
36230
|
const targetDir = process.cwd();
|
|
35246
36231
|
requireOcrSetup(targetDir);
|
|
35247
|
-
const ocrDir =
|
|
36232
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35248
36233
|
try {
|
|
35249
36234
|
const base = options.stdin ? { source: "stdin", data: await readStdin() } : options.file ? { source: "file", filePath: options.file } : (() => {
|
|
35250
36235
|
throw new StateError(STATE_EXIT.USAGE, "Provide --stdin or --file with round metadata");
|
|
@@ -35268,7 +36253,7 @@ var completeMapSubcommand = new Command("complete-map").description("Atomically
|
|
|
35268
36253
|
async (options) => {
|
|
35269
36254
|
const targetDir = process.cwd();
|
|
35270
36255
|
requireOcrSetup(targetDir);
|
|
35271
|
-
const ocrDir =
|
|
36256
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35272
36257
|
try {
|
|
35273
36258
|
const base = options.stdin ? { source: "stdin", data: await readStdin() } : options.file ? { source: "file", filePath: options.file } : (() => {
|
|
35274
36259
|
throw new StateError(STATE_EXIT.USAGE, "Provide --stdin or --file with map metadata");
|
|
@@ -35290,7 +36275,7 @@ var completeMapSubcommand = new Command("complete-map").description("Atomically
|
|
|
35290
36275
|
var finishSubcommand = new Command("finish").description("Close a workflow (refuses unless the current round/run is complete)").option("--session-id <id>", "Session ID (auto-detects active if omitted)").option("--abort", "Abandon the session \u2014 records a distinct, non-success terminal").action(async (options) => {
|
|
35291
36276
|
const targetDir = process.cwd();
|
|
35292
36277
|
requireOcrSetup(targetDir);
|
|
35293
|
-
const ocrDir =
|
|
36278
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35294
36279
|
try {
|
|
35295
36280
|
const { id: sessionId } = await resolveActiveSession(ocrDir, options.sessionId);
|
|
35296
36281
|
await stateClose({ sessionId, ocrDir, abort: options.abort });
|
|
@@ -35302,14 +36287,20 @@ var finishSubcommand = new Command("finish").description("Close a workflow (refu
|
|
|
35302
36287
|
var statusSubcommand = new Command("status").description("Report whether a session is complete and, if not, what's missing").option("--session-id <id>", "Session ID (auto-detects active if omitted)").option("--json", "Output the result as JSON").action(async (options) => {
|
|
35303
36288
|
const targetDir = process.cwd();
|
|
35304
36289
|
requireOcrSetup(targetDir);
|
|
35305
|
-
const ocrDir =
|
|
36290
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35306
36291
|
try {
|
|
35307
|
-
const result = await stateStatus(ocrDir, options.sessionId
|
|
36292
|
+
const result = await stateStatus(ocrDir, options.sessionId, {
|
|
36293
|
+
maxAttempts: getForwardResumeMaxAttempts(ocrDir),
|
|
36294
|
+
heartbeatMs: getAgentHeartbeatSeconds(ocrDir) * 1e3
|
|
36295
|
+
});
|
|
35308
36296
|
if (options.json) {
|
|
35309
36297
|
console.log(JSON.stringify(result, null, 2));
|
|
35310
36298
|
} else {
|
|
35311
36299
|
console.log(`${result.session_id}: ${result.completeness_state}`);
|
|
35312
36300
|
console.log(source_default.dim(` next: ${result.next_action}`));
|
|
36301
|
+
if (result.remaining_phases?.length) {
|
|
36302
|
+
console.log(source_default.dim(` remaining: ${result.remaining_phases.join(" \u2192 ")}`));
|
|
36303
|
+
}
|
|
35313
36304
|
}
|
|
35314
36305
|
} catch (error) {
|
|
35315
36306
|
exitFromStateError(error, "Failed to read status");
|
|
@@ -35333,50 +36324,6 @@ var stateCommand = new Command("state").description("Manage OCR session state").
|
|
|
35333
36324
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
35334
36325
|
import { join as join20 } from "node:path";
|
|
35335
36326
|
init_db();
|
|
35336
|
-
|
|
35337
|
-
// src/lib/runtime-config.ts
|
|
35338
|
-
import { existsSync as existsSync17, readFileSync as readFileSync12 } from "node:fs";
|
|
35339
|
-
import { join as join19 } from "node:path";
|
|
35340
|
-
var DEFAULT_AGENT_HEARTBEAT_SECONDS = 60;
|
|
35341
|
-
function readRuntimePositiveInt(ocrDir, key, defaultValue) {
|
|
35342
|
-
const configPath = join19(ocrDir, "config.yaml");
|
|
35343
|
-
if (!existsSync17(configPath)) return defaultValue;
|
|
35344
|
-
let content;
|
|
35345
|
-
try {
|
|
35346
|
-
content = readFileSync12(configPath, "utf-8");
|
|
35347
|
-
} catch {
|
|
35348
|
-
return defaultValue;
|
|
35349
|
-
}
|
|
35350
|
-
const blockMatch = content.match(
|
|
35351
|
-
new RegExp(
|
|
35352
|
-
String.raw`^runtime:\s*\n(?:\s+[^\n]*\n)*?\s+${key}:\s*([^\s#\n]+)`,
|
|
35353
|
-
"m"
|
|
35354
|
-
)
|
|
35355
|
-
);
|
|
35356
|
-
const inlineMatch = content.match(
|
|
35357
|
-
new RegExp(String.raw`^runtime:\s*\{[^}]*\b${key}:\s*([^\s,}]+)`, "m")
|
|
35358
|
-
);
|
|
35359
|
-
const raw = blockMatch?.[1] ?? inlineMatch?.[1];
|
|
35360
|
-
if (!raw) return defaultValue;
|
|
35361
|
-
const parsed = Number(raw);
|
|
35362
|
-
if (!Number.isFinite(parsed) || parsed <= 0 || !Number.isInteger(parsed)) {
|
|
35363
|
-
process.stderr.write(
|
|
35364
|
-
`[ocr] runtime.${key} is not a positive integer (got "${raw}"); falling back to ${defaultValue}.
|
|
35365
|
-
`
|
|
35366
|
-
);
|
|
35367
|
-
return defaultValue;
|
|
35368
|
-
}
|
|
35369
|
-
return parsed;
|
|
35370
|
-
}
|
|
35371
|
-
function getAgentHeartbeatSeconds(ocrDir) {
|
|
35372
|
-
return readRuntimePositiveInt(
|
|
35373
|
-
ocrDir,
|
|
35374
|
-
"agent_heartbeat_seconds",
|
|
35375
|
-
DEFAULT_AGENT_HEARTBEAT_SECONDS
|
|
35376
|
-
);
|
|
35377
|
-
}
|
|
35378
|
-
|
|
35379
|
-
// src/commands/session.ts
|
|
35380
36327
|
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
35381
36328
|
"done",
|
|
35382
36329
|
"crashed",
|
|
@@ -35427,6 +36374,11 @@ var startInstanceSubcommand = new Command("start-instance").description("Journal
|
|
|
35427
36374
|
}
|
|
35428
36375
|
);
|
|
35429
36376
|
var bindVendorIdSubcommand = new Command("bind-vendor-id").description("Bind the underlying CLI's session id to an OCR agent session").argument("<agent-session-id>", "OCR agent session id").argument("<vendor-session-id>", "Underlying CLI's session id").action(async (agentId, vendorId) => {
|
|
36377
|
+
if (!SAFE_VENDOR_SESSION_ID.test(vendorId)) {
|
|
36378
|
+
fail(
|
|
36379
|
+
`vendor-session-id ${JSON.stringify(vendorId)} is not a plausible vendor session id (allowed: letters and digits plus . _ : - , max 256 chars). Nothing was bound \u2014 retry with the id the vendor CLI actually emitted.`
|
|
36380
|
+
);
|
|
36381
|
+
}
|
|
35430
36382
|
const { ocrDir } = await setup();
|
|
35431
36383
|
const db = await ensureDatabase(ocrDir);
|
|
35432
36384
|
try {
|
|
@@ -35524,7 +36476,7 @@ var listSubcommand = new Command("list").description("List agent sessions for a
|
|
|
35524
36476
|
});
|
|
35525
36477
|
var sessionCommand = new Command("session").description("Manage agent-CLI session lifecycle journal").addCommand(startInstanceSubcommand).addCommand(bindVendorIdSubcommand).addCommand(beatSubcommand).addCommand(endInstanceSubcommand).addCommand(listSubcommand);
|
|
35526
36478
|
|
|
35527
|
-
// src/
|
|
36479
|
+
// ../shared/config/src/models.ts
|
|
35528
36480
|
init_src();
|
|
35529
36481
|
function parseOpenCodeModelList(stdout) {
|
|
35530
36482
|
const models = [];
|
|
@@ -35770,6 +36722,9 @@ function parseSessionOverride(raw) {
|
|
|
35770
36722
|
return result;
|
|
35771
36723
|
}
|
|
35772
36724
|
var resolveSubcommand = new Command("resolve").description("Resolve and print the team composition for the active workspace").option(
|
|
36725
|
+
"--team <spec>",
|
|
36726
|
+
"Session team override replacing default_team. Format: reviewer-id:count[,reviewer-id:count...] (e.g. principal:2,architect:1)"
|
|
36727
|
+
).option(
|
|
35773
36728
|
"--session-override <json>",
|
|
35774
36729
|
"JSON array of ReviewerInstance overrides applied on top of disk config"
|
|
35775
36730
|
).option("--session-override-stdin", "Read --session-override JSON from stdin").option("--json", "Emit JSON for programmatic consumption (the AI workflow uses this)").action(
|
|
@@ -35778,7 +36733,8 @@ var resolveSubcommand = new Command("resolve").description("Resolve and print th
|
|
|
35778
36733
|
requireOcrSetup(targetDir);
|
|
35779
36734
|
const ocrDir = join21(targetDir, ".ocr");
|
|
35780
36735
|
try {
|
|
35781
|
-
const { team } = loadTeamConfig(ocrDir);
|
|
36736
|
+
const { team, aliases, defaultModel } = loadTeamConfig(ocrDir);
|
|
36737
|
+
const baseTeam = options.team ? parseTeamSpec(options.team, aliases, defaultModel) : team;
|
|
35782
36738
|
let override;
|
|
35783
36739
|
if (options.sessionOverride) {
|
|
35784
36740
|
override = parseSessionOverride(options.sessionOverride);
|
|
@@ -35788,7 +36744,7 @@ var resolveSubcommand = new Command("resolve").description("Resolve and print th
|
|
|
35788
36744
|
override = parseSessionOverride(raw);
|
|
35789
36745
|
}
|
|
35790
36746
|
}
|
|
35791
|
-
const resolved = resolveTeamComposition(
|
|
36747
|
+
const resolved = resolveTeamComposition(baseTeam, override);
|
|
35792
36748
|
if (options.json) {
|
|
35793
36749
|
console.log(JSON.stringify(resolved, null, 2));
|
|
35794
36750
|
return;
|
|
@@ -35926,11 +36882,11 @@ function pairKey(pair) {
|
|
|
35926
36882
|
var teamCommand = new Command("team").description("Resolve and persist team composition").addCommand(resolveSubcommand).addCommand(setSubcommand);
|
|
35927
36883
|
|
|
35928
36884
|
// src/commands/review.ts
|
|
35929
|
-
|
|
36885
|
+
init_src();
|
|
35930
36886
|
import { join as join22 } from "node:path";
|
|
35931
36887
|
init_db();
|
|
35932
36888
|
|
|
35933
|
-
// src/
|
|
36889
|
+
// ../shared/persistence/src/vendor-resume.ts
|
|
35934
36890
|
var VENDOR_BINARIES = {
|
|
35935
36891
|
claude: "claude",
|
|
35936
36892
|
opencode: "opencode"
|
|
@@ -35952,6 +36908,7 @@ function fail3(message) {
|
|
|
35952
36908
|
console.error(source_default.red(`Error: ${message}`));
|
|
35953
36909
|
process.exit(1);
|
|
35954
36910
|
}
|
|
36911
|
+
var CONTROL_PROMPT = "Resume this OCR review: run `ocr state status --json` and act on `next_action`, continuing forward from `current_phase` without redoing completed phases.";
|
|
35955
36912
|
var reviewCommand = new Command("review").description("Run or resume an OCR review").option("--resume <workflow-id>", "Resume a prior review by its workflow session id").action(async (options) => {
|
|
35956
36913
|
if (!options.resume) {
|
|
35957
36914
|
console.error(
|
|
@@ -35968,21 +36925,89 @@ var reviewCommand = new Command("review").description("Run or resume an OCR revi
|
|
|
35968
36925
|
requireOcrSetup(targetDir);
|
|
35969
36926
|
const ocrDir = join22(targetDir, ".ocr");
|
|
35970
36927
|
const db = await ensureDatabase(ocrDir);
|
|
35971
|
-
const
|
|
36928
|
+
const workflowId = options.resume;
|
|
36929
|
+
const session = getSession(db, workflowId);
|
|
35972
36930
|
if (!session) {
|
|
35973
|
-
fail3(`Workflow session not found: ${
|
|
36931
|
+
fail3(`Workflow session not found: ${workflowId}`);
|
|
36932
|
+
}
|
|
36933
|
+
const maxAttempts = getForwardResumeMaxAttempts(ocrDir);
|
|
36934
|
+
const leaseMs = getForwardResumeLeaseMs(ocrDir);
|
|
36935
|
+
const heartbeatMs = getAgentHeartbeatSeconds(ocrDir) * 1e3;
|
|
36936
|
+
const status = await stateStatus(ocrDir, workflowId, {
|
|
36937
|
+
maxAttempts,
|
|
36938
|
+
heartbeatMs
|
|
36939
|
+
});
|
|
36940
|
+
switch (status.next_action_kind) {
|
|
36941
|
+
case "none":
|
|
36942
|
+
console.error(source_default.green(`Workflow ${workflowId} is already complete \u2014 nothing to resume.`));
|
|
36943
|
+
process.exit(0);
|
|
36944
|
+
break;
|
|
36945
|
+
case "finish":
|
|
36946
|
+
console.error(
|
|
36947
|
+
source_default.yellow(`Workflow ${workflowId}'s round is complete but the session is still open.`)
|
|
36948
|
+
);
|
|
36949
|
+
console.error(source_default.dim("Run `ocr state finish` to close it."));
|
|
36950
|
+
process.exit(0);
|
|
36951
|
+
break;
|
|
36952
|
+
case "abort_or_fresh": {
|
|
36953
|
+
closeForwardResumeExhausted(db, workflowId, maxAttempts);
|
|
36954
|
+
fail3(
|
|
36955
|
+
`Forward-resume attempts exhausted for workflow ${workflowId} (cap ${maxAttempts}). Closed non-success (artifacts preserved). Start a fresh review, or run \`ocr state finish --abort\` if it was already closed.`
|
|
36956
|
+
);
|
|
36957
|
+
break;
|
|
36958
|
+
}
|
|
36959
|
+
case "advance":
|
|
36960
|
+
case "complete_round":
|
|
36961
|
+
case "wait":
|
|
36962
|
+
console.error(
|
|
36963
|
+
source_default.yellow(
|
|
36964
|
+
`Workflow ${workflowId} appears to still be running (phase "${status.current_phase}"). Nothing to resume yet.`
|
|
36965
|
+
)
|
|
36966
|
+
);
|
|
36967
|
+
process.exit(0);
|
|
36968
|
+
break;
|
|
36969
|
+
case "reopen":
|
|
36970
|
+
console.error(
|
|
36971
|
+
source_default.yellow(`Workflow ${workflowId} was closed without a completed round.`)
|
|
36972
|
+
);
|
|
36973
|
+
console.error(source_default.dim("Re-invoke the review skill to finalize it."));
|
|
36974
|
+
process.exit(0);
|
|
36975
|
+
break;
|
|
35974
36976
|
}
|
|
35975
|
-
const
|
|
35976
|
-
|
|
36977
|
+
const lease = tryAcquireForwardResumeLease(db, workflowId, session.current_round, {
|
|
36978
|
+
leaseMs,
|
|
36979
|
+
maxAttempts
|
|
36980
|
+
});
|
|
36981
|
+
if (!lease.acquired) {
|
|
36982
|
+
if (lease.reason === "cap_exhausted") {
|
|
36983
|
+
closeForwardResumeExhausted(db, workflowId, lease.attemptsUsed);
|
|
36984
|
+
fail3(
|
|
36985
|
+
`Forward-resume attempts exhausted for workflow ${workflowId} (cap ${maxAttempts}). Closed non-success (artifacts preserved). Start a fresh review.`
|
|
36986
|
+
);
|
|
36987
|
+
}
|
|
35977
36988
|
fail3(
|
|
35978
|
-
`
|
|
36989
|
+
`A forward-resume is already in progress for workflow ${workflowId} (lease held). Wait for it to finish or retry after the lease expires.`
|
|
35979
36990
|
);
|
|
35980
36991
|
}
|
|
35981
|
-
|
|
35982
|
-
|
|
35983
|
-
|
|
35984
|
-
|
|
36992
|
+
console.error(
|
|
36993
|
+
source_default.dim(
|
|
36994
|
+
`Forward-resuming workflow ${session.id} on branch ${session.branch} from phase "${status.current_phase}" (${status.forward_resume_attempts_remaining ?? "?"} attempt(s) left).`
|
|
36995
|
+
)
|
|
36996
|
+
);
|
|
36997
|
+
const latest = getLatestAgentSessionWithVendorId(db, workflowId);
|
|
36998
|
+
const binary = latest?.vendor ? VENDOR_BINARIES[latest.vendor] : void 0;
|
|
36999
|
+
if (!latest || !latest.vendor_session_id || !binary) {
|
|
37000
|
+
console.error(
|
|
37001
|
+
source_default.yellow(
|
|
37002
|
+
`No resumable vendor session is captured for workflow ${workflowId}.`
|
|
37003
|
+
)
|
|
35985
37004
|
);
|
|
37005
|
+
console.error(
|
|
37006
|
+
source_default.dim(
|
|
37007
|
+
`Continue it by re-invoking the review skill (\`/ocr-review\`) in your AI CLI \u2014 its Phase 0 reads \`ocr state status --json\` and continues forward from "${status.current_phase}". (${CONTROL_PROMPT})`
|
|
37008
|
+
)
|
|
37009
|
+
);
|
|
37010
|
+
process.exit(0);
|
|
35986
37011
|
}
|
|
35987
37012
|
let args;
|
|
35988
37013
|
try {
|
|
@@ -35990,12 +37015,8 @@ var reviewCommand = new Command("review").description("Run or resume an OCR revi
|
|
|
35990
37015
|
} catch (err) {
|
|
35991
37016
|
fail3(err instanceof Error ? err.message : String(err));
|
|
35992
37017
|
}
|
|
35993
|
-
console.error(
|
|
35994
|
-
|
|
35995
|
-
`Resuming workflow ${session.id} on branch ${session.branch} via ${binary}\u2026`
|
|
35996
|
-
)
|
|
35997
|
-
);
|
|
35998
|
-
const child = spawn3(binary, args, {
|
|
37018
|
+
console.error(source_default.dim(`Resuming via ${binary} (continue forward from "${status.current_phase}")\u2026`));
|
|
37019
|
+
const child = spawnBinary(binary, args, {
|
|
35999
37020
|
stdio: "inherit",
|
|
36000
37021
|
cwd: targetDir
|
|
36001
37022
|
});
|