@open-code-review/cli 2.2.1 → 2.3.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 +910 -461
- package/dist/index.js +1257 -321
- package/package.json +6 -39
- 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,7 +30020,7 @@ 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";
|
|
@@ -29403,6 +30065,9 @@ function parseTeamConfigYaml(content) {
|
|
|
29403
30065
|
aliases,
|
|
29404
30066
|
defaultModel
|
|
29405
30067
|
);
|
|
30068
|
+
if (resolvedModel !== null) {
|
|
30069
|
+
assertSafeModelId(resolvedModel, `default_team.${persona}[${i}]`);
|
|
30070
|
+
}
|
|
29406
30071
|
team.push({
|
|
29407
30072
|
persona,
|
|
29408
30073
|
instance_index: i + 1,
|
|
@@ -29483,6 +30148,16 @@ function readOptionalString(obj, key, pathLabel) {
|
|
|
29483
30148
|
}
|
|
29484
30149
|
return value;
|
|
29485
30150
|
}
|
|
30151
|
+
var SAFE_MODEL_ID = /^[A-Za-z0-9][A-Za-z0-9._/:@[\]+-]{0,255}$/;
|
|
30152
|
+
function assertSafeModelId(value, pathLabel) {
|
|
30153
|
+
if (SAFE_MODEL_ID.test(value)) return;
|
|
30154
|
+
const allowed = /[A-Za-z0-9._/:@[\]+-]/;
|
|
30155
|
+
const offending = [...value].find((ch) => !allowed.test(ch));
|
|
30156
|
+
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])}`;
|
|
30157
|
+
throw new Error(
|
|
30158
|
+
`${pathLabel}: model id ${detail} \u2014 no vendor model id uses that. Allowed: letters and digits plus . _ / : @ [ ] + - (max 256 chars).`
|
|
30159
|
+
);
|
|
30160
|
+
}
|
|
29486
30161
|
function readAliases(root) {
|
|
29487
30162
|
const models = root["models"];
|
|
29488
30163
|
if (!models || typeof models !== "object" || Array.isArray(models)) return {};
|
|
@@ -29524,6 +30199,9 @@ function resolveTeamComposition(team, override) {
|
|
|
29524
30199
|
result.push(inst);
|
|
29525
30200
|
}
|
|
29526
30201
|
for (const inst of override) {
|
|
30202
|
+
if (inst.model !== null) {
|
|
30203
|
+
assertSafeModelId(inst.model, `override ${inst.persona}#${inst.instance_index}`);
|
|
30204
|
+
}
|
|
29527
30205
|
result.push(inst);
|
|
29528
30206
|
}
|
|
29529
30207
|
return result;
|
|
@@ -30092,7 +30770,7 @@ ${hint}
|
|
|
30092
30770
|
}
|
|
30093
30771
|
|
|
30094
30772
|
// src/lib/version.ts
|
|
30095
|
-
var CLI_VERSION = true ? "2.
|
|
30773
|
+
var CLI_VERSION = true ? "2.3.0" : createRequire(import.meta.url)("../../package.json").version;
|
|
30096
30774
|
|
|
30097
30775
|
// src/lib/deps.ts
|
|
30098
30776
|
init_src();
|
|
@@ -33026,12 +33704,12 @@ function getStrategy(workflowType) {
|
|
|
33026
33704
|
}
|
|
33027
33705
|
|
|
33028
33706
|
// src/lib/progress/detector.ts
|
|
33029
|
-
import { existsSync as
|
|
33030
|
-
import { join as
|
|
33707
|
+
import { existsSync as existsSync11, readdirSync as readdirSync3 } from "node:fs";
|
|
33708
|
+
import { join as join13, basename as basename5 } from "node:path";
|
|
33031
33709
|
|
|
33032
33710
|
// src/lib/progress/session-reader.ts
|
|
33033
|
-
|
|
33034
|
-
import { basename as
|
|
33711
|
+
init_db();
|
|
33712
|
+
import { basename as basename4 } from "node:path";
|
|
33035
33713
|
var cachedDb = null;
|
|
33036
33714
|
function setProgressDb(db) {
|
|
33037
33715
|
cachedDb = db;
|
|
@@ -33050,7 +33728,7 @@ function readSessionState(sessionPath) {
|
|
|
33050
33728
|
}
|
|
33051
33729
|
}
|
|
33052
33730
|
function readFromSqlite(sessionPath, db) {
|
|
33053
|
-
const sessionId =
|
|
33731
|
+
const sessionId = basename4(sessionPath);
|
|
33054
33732
|
let row = resultToRow(
|
|
33055
33733
|
db.exec("SELECT * FROM sessions WHERE id = ?", [sessionId])
|
|
33056
33734
|
);
|
|
@@ -33085,7 +33763,7 @@ function detectWorkflowType(sessionPath, explicitType) {
|
|
|
33085
33763
|
const db = getProgressDb();
|
|
33086
33764
|
if (db) {
|
|
33087
33765
|
try {
|
|
33088
|
-
const sessionId =
|
|
33766
|
+
const sessionId = basename5(sessionPath);
|
|
33089
33767
|
const result = db.exec(
|
|
33090
33768
|
"SELECT workflow_type FROM sessions WHERE id = ?",
|
|
33091
33769
|
[sessionId]
|
|
@@ -33098,8 +33776,8 @@ function detectWorkflowType(sessionPath, explicitType) {
|
|
|
33098
33776
|
} catch {
|
|
33099
33777
|
}
|
|
33100
33778
|
}
|
|
33101
|
-
const hasMapDir =
|
|
33102
|
-
const hasRoundsDir =
|
|
33779
|
+
const hasMapDir = existsSync11(join13(sessionPath, "map"));
|
|
33780
|
+
const hasRoundsDir = existsSync11(join13(sessionPath, "rounds"));
|
|
33103
33781
|
if (hasMapDir && !hasRoundsDir) {
|
|
33104
33782
|
return "map";
|
|
33105
33783
|
}
|
|
@@ -33109,7 +33787,7 @@ function detectWorkflowType(sessionPath, explicitType) {
|
|
|
33109
33787
|
if (hasMapDir && hasRoundsDir) {
|
|
33110
33788
|
if (db) {
|
|
33111
33789
|
try {
|
|
33112
|
-
const sessionId =
|
|
33790
|
+
const sessionId = basename5(sessionPath);
|
|
33113
33791
|
const result = db.exec(
|
|
33114
33792
|
"SELECT current_phase FROM sessions WHERE id = ?",
|
|
33115
33793
|
[sessionId]
|
|
@@ -33133,7 +33811,7 @@ function isSessionActive(sessionPath) {
|
|
|
33133
33811
|
const db = getProgressDb();
|
|
33134
33812
|
if (db) {
|
|
33135
33813
|
try {
|
|
33136
|
-
const sessionId =
|
|
33814
|
+
const sessionId = basename5(sessionPath);
|
|
33137
33815
|
const result = db.exec(
|
|
33138
33816
|
"SELECT status, current_phase FROM sessions WHERE id = ?",
|
|
33139
33817
|
[sessionId]
|
|
@@ -33155,28 +33833,28 @@ function isSessionActive(sessionPath) {
|
|
|
33155
33833
|
}
|
|
33156
33834
|
function detectActiveWorkflows(sessionPath) {
|
|
33157
33835
|
const activeWorkflows = [];
|
|
33158
|
-
const hasRoundsDir =
|
|
33836
|
+
const hasRoundsDir = existsSync11(join13(sessionPath, "rounds"));
|
|
33159
33837
|
if (hasRoundsDir) {
|
|
33160
|
-
const roundsDir =
|
|
33161
|
-
const rounds =
|
|
33838
|
+
const roundsDir = join13(sessionPath, "rounds");
|
|
33839
|
+
const rounds = existsSync11(roundsDir) ? readdirSync3(roundsDir).filter((d) => d.match(/^round-\d+$/)).sort() : [];
|
|
33162
33840
|
if (rounds.length > 0) {
|
|
33163
33841
|
const latestRound = rounds[rounds.length - 1];
|
|
33164
|
-
const finalPath =
|
|
33165
|
-
if (!
|
|
33842
|
+
const finalPath = join13(roundsDir, latestRound, "final.md");
|
|
33843
|
+
if (!existsSync11(finalPath)) {
|
|
33166
33844
|
activeWorkflows.push("review");
|
|
33167
33845
|
}
|
|
33168
33846
|
} else {
|
|
33169
33847
|
activeWorkflows.push("review");
|
|
33170
33848
|
}
|
|
33171
33849
|
}
|
|
33172
|
-
const hasMapDir =
|
|
33850
|
+
const hasMapDir = existsSync11(join13(sessionPath, "map"));
|
|
33173
33851
|
if (hasMapDir) {
|
|
33174
|
-
const runsDir =
|
|
33175
|
-
const runs =
|
|
33852
|
+
const runsDir = join13(sessionPath, "map", "runs");
|
|
33853
|
+
const runs = existsSync11(runsDir) ? readdirSync3(runsDir).filter((d) => d.match(/^run-\d+$/)).sort() : [];
|
|
33176
33854
|
if (runs.length > 0) {
|
|
33177
33855
|
const latestRun = runs[runs.length - 1];
|
|
33178
|
-
const mapPath =
|
|
33179
|
-
if (!
|
|
33856
|
+
const mapPath = join13(runsDir, latestRun, "map.md");
|
|
33857
|
+
if (!existsSync11(mapPath)) {
|
|
33180
33858
|
activeWorkflows.push("map");
|
|
33181
33859
|
}
|
|
33182
33860
|
} else {
|
|
@@ -33187,7 +33865,7 @@ function detectActiveWorkflows(sessionPath) {
|
|
|
33187
33865
|
const db = getProgressDb();
|
|
33188
33866
|
if (db) {
|
|
33189
33867
|
try {
|
|
33190
|
-
const sessionId =
|
|
33868
|
+
const sessionId = basename5(sessionPath);
|
|
33191
33869
|
const result = db.exec(
|
|
33192
33870
|
"SELECT workflow_type, current_phase FROM sessions WHERE id = ?",
|
|
33193
33871
|
[sessionId]
|
|
@@ -33255,8 +33933,8 @@ function padLines(lines) {
|
|
|
33255
33933
|
}
|
|
33256
33934
|
|
|
33257
33935
|
// src/lib/progress/review-strategy.ts
|
|
33258
|
-
import { existsSync as
|
|
33259
|
-
import { join as
|
|
33936
|
+
import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync8 } from "node:fs";
|
|
33937
|
+
import { join as join14, basename as basename6 } from "node:path";
|
|
33260
33938
|
var REVIEW_PHASES = [
|
|
33261
33939
|
{ key: "context", label: "Context Discovery" },
|
|
33262
33940
|
{ key: "change-context", label: "Change Context" },
|
|
@@ -33268,10 +33946,10 @@ var REVIEW_PHASES = [
|
|
|
33268
33946
|
{ key: "complete", label: "Complete" }
|
|
33269
33947
|
];
|
|
33270
33948
|
function countFindings(filePath) {
|
|
33271
|
-
if (!
|
|
33949
|
+
if (!existsSync12(filePath)) {
|
|
33272
33950
|
return 0;
|
|
33273
33951
|
}
|
|
33274
|
-
const content =
|
|
33952
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
33275
33953
|
const findingMatches = content.match(/^##\s+(Finding|Issue|Suggestion)/gm);
|
|
33276
33954
|
return findingMatches?.length ?? 0;
|
|
33277
33955
|
}
|
|
@@ -33285,27 +33963,27 @@ function formatReviewerName(filename) {
|
|
|
33285
33963
|
return base.charAt(0).toUpperCase() + base.slice(1);
|
|
33286
33964
|
}
|
|
33287
33965
|
function deriveRoundsFromFilesystem(roundsDir) {
|
|
33288
|
-
if (!
|
|
33966
|
+
if (!existsSync12(roundsDir)) {
|
|
33289
33967
|
return [];
|
|
33290
33968
|
}
|
|
33291
|
-
const roundDirs =
|
|
33969
|
+
const roundDirs = readdirSync4(roundsDir).filter((d) => d.match(/^round-\d+$/)).sort((a, b) => {
|
|
33292
33970
|
const numA = parseInt(a.replace("round-", ""));
|
|
33293
33971
|
const numB = parseInt(b.replace("round-", ""));
|
|
33294
33972
|
return numA - numB;
|
|
33295
33973
|
});
|
|
33296
33974
|
return roundDirs.map((dir) => {
|
|
33297
33975
|
const roundNum = parseInt(dir.replace("round-", ""));
|
|
33298
|
-
const roundPath =
|
|
33299
|
-
const reviewsPath =
|
|
33300
|
-
const finalPath =
|
|
33976
|
+
const roundPath = join14(roundsDir, dir);
|
|
33977
|
+
const reviewsPath = join14(roundPath, "reviews");
|
|
33978
|
+
const finalPath = join14(roundPath, "final.md");
|
|
33301
33979
|
const reviewers = [];
|
|
33302
|
-
if (
|
|
33303
|
-
const files =
|
|
33980
|
+
if (existsSync12(reviewsPath)) {
|
|
33981
|
+
const files = readdirSync4(reviewsPath).filter((f) => f.endsWith(".md"));
|
|
33304
33982
|
reviewers.push(...files.map((f) => f.replace(".md", "")));
|
|
33305
33983
|
}
|
|
33306
33984
|
return {
|
|
33307
33985
|
round: roundNum,
|
|
33308
|
-
isComplete:
|
|
33986
|
+
isComplete: existsSync12(finalPath),
|
|
33309
33987
|
reviewers
|
|
33310
33988
|
};
|
|
33311
33989
|
});
|
|
@@ -33315,7 +33993,7 @@ var ReviewProgressStrategy = class {
|
|
|
33315
33993
|
phases = REVIEW_PHASES;
|
|
33316
33994
|
totalPhases = 8;
|
|
33317
33995
|
parseState(sessionPath, preservedStartTime) {
|
|
33318
|
-
const session =
|
|
33996
|
+
const session = basename6(sessionPath);
|
|
33319
33997
|
const state = readSessionState(sessionPath);
|
|
33320
33998
|
if (!state) {
|
|
33321
33999
|
return null;
|
|
@@ -33334,19 +34012,19 @@ var ReviewProgressStrategy = class {
|
|
|
33334
34012
|
parseFromState(session, state, sessionPath, preservedStartTime) {
|
|
33335
34013
|
const effectiveStartTime = state.round_started_at ?? state.started_at;
|
|
33336
34014
|
const startTime = preservedStartTime ?? (effectiveStartTime ? new Date(effectiveStartTime).getTime() : Date.now());
|
|
33337
|
-
const roundsDir =
|
|
34015
|
+
const roundsDir = join14(sessionPath, "rounds");
|
|
33338
34016
|
const rounds = deriveRoundsFromFilesystem(roundsDir);
|
|
33339
34017
|
const highestExistingRound = rounds.length > 0 ? Math.max(...rounds.map((r) => r.round)) : 1;
|
|
33340
34018
|
const stateRound = state.current_round ?? 1;
|
|
33341
34019
|
const currentRound = Math.min(stateRound, highestExistingRound);
|
|
33342
|
-
const currentRoundDir =
|
|
33343
|
-
const reviewsDir =
|
|
34020
|
+
const currentRoundDir = join14(roundsDir, `round-${currentRound}`);
|
|
34021
|
+
const reviewsDir = join14(currentRoundDir, "reviews");
|
|
33344
34022
|
const reviewers = [];
|
|
33345
|
-
if (
|
|
33346
|
-
const entries =
|
|
34023
|
+
if (existsSync12(reviewsDir)) {
|
|
34024
|
+
const entries = readdirSync4(reviewsDir);
|
|
33347
34025
|
const reviewFiles = entries.filter((f) => f.endsWith(".md"));
|
|
33348
34026
|
for (const file of reviewFiles) {
|
|
33349
|
-
const reviewPath =
|
|
34027
|
+
const reviewPath = join14(reviewsDir, file);
|
|
33350
34028
|
const findings = countFindings(reviewPath);
|
|
33351
34029
|
reviewers.push({
|
|
33352
34030
|
name: file.replace(".md", ""),
|
|
@@ -33356,14 +34034,14 @@ var ReviewProgressStrategy = class {
|
|
|
33356
34034
|
});
|
|
33357
34035
|
}
|
|
33358
34036
|
}
|
|
33359
|
-
const contextComplete =
|
|
33360
|
-
|
|
34037
|
+
const contextComplete = existsSync12(
|
|
34038
|
+
join14(sessionPath, "discovered-standards.md")
|
|
33361
34039
|
);
|
|
33362
|
-
const changeContextComplete =
|
|
34040
|
+
const changeContextComplete = existsSync12(join14(sessionPath, "context.md"));
|
|
33363
34041
|
const analysisComplete = changeContextComplete;
|
|
33364
34042
|
const reviewsComplete = state.phase_number > 4;
|
|
33365
|
-
const discourseComplete =
|
|
33366
|
-
const synthesisComplete =
|
|
34043
|
+
const discourseComplete = existsSync12(join14(currentRoundDir, "discourse.md"));
|
|
34044
|
+
const synthesisComplete = existsSync12(join14(currentRoundDir, "final.md"));
|
|
33367
34045
|
return {
|
|
33368
34046
|
workflowType: "review",
|
|
33369
34047
|
session,
|
|
@@ -33495,8 +34173,8 @@ var ReviewProgressStrategy = class {
|
|
|
33495
34173
|
var reviewStrategy = new ReviewProgressStrategy();
|
|
33496
34174
|
|
|
33497
34175
|
// src/lib/progress/map-strategy.ts
|
|
33498
|
-
import { existsSync as
|
|
33499
|
-
import { join as
|
|
34176
|
+
import { existsSync as existsSync13, readdirSync as readdirSync5, readFileSync as readFileSync9 } from "node:fs";
|
|
34177
|
+
import { join as join15, basename as basename7 } from "node:path";
|
|
33500
34178
|
var MAP_PHASES = [
|
|
33501
34179
|
{ key: "map-context", label: "Context Discovery" },
|
|
33502
34180
|
{ key: "topology", label: "Topology Analysis" },
|
|
@@ -33506,23 +34184,23 @@ var MAP_PHASES = [
|
|
|
33506
34184
|
{ key: "complete", label: "Complete" }
|
|
33507
34185
|
];
|
|
33508
34186
|
function deriveRunsFromFilesystem(mapDir) {
|
|
33509
|
-
const runsDir =
|
|
33510
|
-
if (!
|
|
34187
|
+
const runsDir = join15(mapDir, "runs");
|
|
34188
|
+
if (!existsSync13(runsDir)) {
|
|
33511
34189
|
return [];
|
|
33512
34190
|
}
|
|
33513
|
-
const runDirs =
|
|
34191
|
+
const runDirs = readdirSync5(runsDir).filter((d) => d.match(/^run-\d+$/)).sort((a, b) => {
|
|
33514
34192
|
const numA = parseInt(a.replace("run-", ""));
|
|
33515
34193
|
const numB = parseInt(b.replace("run-", ""));
|
|
33516
34194
|
return numA - numB;
|
|
33517
34195
|
});
|
|
33518
34196
|
return runDirs.map((dir) => {
|
|
33519
34197
|
const runNum = parseInt(dir.replace("run-", ""));
|
|
33520
|
-
const runPath =
|
|
33521
|
-
const mapPath =
|
|
34198
|
+
const runPath = join15(runsDir, dir);
|
|
34199
|
+
const mapPath = join15(runPath, "map.md");
|
|
33522
34200
|
let fileCount = 0;
|
|
33523
|
-
const topologyPath =
|
|
33524
|
-
if (
|
|
33525
|
-
const content =
|
|
34201
|
+
const topologyPath = join15(runPath, "topology.md");
|
|
34202
|
+
if (existsSync13(topologyPath)) {
|
|
34203
|
+
const content = readFileSync9(topologyPath, "utf-8");
|
|
33526
34204
|
const fileListMatch = content.match(
|
|
33527
34205
|
/## Canonical File List[\s\S]*?```([\s\S]*?)```/
|
|
33528
34206
|
);
|
|
@@ -33532,7 +34210,7 @@ function deriveRunsFromFilesystem(mapDir) {
|
|
|
33532
34210
|
}
|
|
33533
34211
|
return {
|
|
33534
34212
|
run: runNum,
|
|
33535
|
-
isComplete:
|
|
34213
|
+
isComplete: existsSync13(mapPath),
|
|
33536
34214
|
fileCount
|
|
33537
34215
|
};
|
|
33538
34216
|
});
|
|
@@ -33542,7 +34220,7 @@ var MapProgressStrategy = class {
|
|
|
33542
34220
|
phases = MAP_PHASES;
|
|
33543
34221
|
totalPhases = 6;
|
|
33544
34222
|
parseState(sessionPath, preservedStartTime) {
|
|
33545
|
-
const session =
|
|
34223
|
+
const session = basename7(sessionPath);
|
|
33546
34224
|
const state = readSessionState(sessionPath);
|
|
33547
34225
|
if (!state) {
|
|
33548
34226
|
return null;
|
|
@@ -33564,24 +34242,24 @@ var MapProgressStrategy = class {
|
|
|
33564
34242
|
parseFromState(session, state, sessionPath, preservedStartTime) {
|
|
33565
34243
|
const effectiveStartTime = state.map_started_at ?? state.started_at;
|
|
33566
34244
|
const startTime = preservedStartTime ?? (effectiveStartTime ? new Date(effectiveStartTime).getTime() : Date.now());
|
|
33567
|
-
const mapDir =
|
|
34245
|
+
const mapDir = join15(sessionPath, "map");
|
|
33568
34246
|
const runs = deriveRunsFromFilesystem(mapDir);
|
|
33569
34247
|
const highestExistingRun = runs.length > 0 ? Math.max(...runs.map((r) => r.run)) : 1;
|
|
33570
34248
|
const stateRun = state.current_map_run ?? 1;
|
|
33571
34249
|
const currentRun = Math.min(stateRun, highestExistingRun);
|
|
33572
|
-
const currentRunDir =
|
|
33573
|
-
const contextComplete =
|
|
33574
|
-
|
|
34250
|
+
const currentRunDir = join15(mapDir, "runs", `run-${currentRun}`);
|
|
34251
|
+
const contextComplete = existsSync13(
|
|
34252
|
+
join15(sessionPath, "discovered-standards.md")
|
|
33575
34253
|
);
|
|
33576
|
-
const topologyComplete =
|
|
33577
|
-
const flowAnalysisComplete =
|
|
33578
|
-
|
|
34254
|
+
const topologyComplete = existsSync13(join15(currentRunDir, "topology.md"));
|
|
34255
|
+
const flowAnalysisComplete = existsSync13(
|
|
34256
|
+
join15(currentRunDir, "flow-analysis.md")
|
|
33579
34257
|
);
|
|
33580
|
-
const requirementsMappingComplete =
|
|
33581
|
-
|
|
34258
|
+
const requirementsMappingComplete = existsSync13(
|
|
34259
|
+
join15(currentRunDir, "requirements-mapping.md")
|
|
33582
34260
|
);
|
|
33583
|
-
const synthesisComplete =
|
|
33584
|
-
const hasRequirements =
|
|
34261
|
+
const synthesisComplete = existsSync13(join15(currentRunDir, "map.md"));
|
|
34262
|
+
const hasRequirements = existsSync13(join15(sessionPath, "requirements.md"));
|
|
33585
34263
|
const flowAnalysts = flowAnalysisComplete ? [
|
|
33586
34264
|
{
|
|
33587
34265
|
name: "flow-analyst",
|
|
@@ -34036,10 +34714,10 @@ function renderCombinedProgress(sessionPath, preservedStartTimes, ocrDir) {
|
|
|
34036
34714
|
}
|
|
34037
34715
|
|
|
34038
34716
|
// src/commands/state.ts
|
|
34039
|
-
import { existsSync as
|
|
34040
|
-
import { join as
|
|
34717
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync7, readFileSync as readFileSync12, readdirSync as readdirSync8 } from "node:fs";
|
|
34718
|
+
import { join as join19 } from "node:path";
|
|
34041
34719
|
|
|
34042
|
-
// src/
|
|
34720
|
+
// ../shared/persistence/src/state/index.ts
|
|
34043
34721
|
init_db();
|
|
34044
34722
|
init_exit_codes();
|
|
34045
34723
|
import {
|
|
@@ -34052,7 +34730,7 @@ import {
|
|
|
34052
34730
|
} from "node:fs";
|
|
34053
34731
|
import { join as join17 } from "node:path";
|
|
34054
34732
|
|
|
34055
|
-
// src/
|
|
34733
|
+
// ../shared/persistence/src/state/phase-graph.ts
|
|
34056
34734
|
init_exit_codes();
|
|
34057
34735
|
var REVIEW_PHASE_NUMBERS = {
|
|
34058
34736
|
context: 1,
|
|
@@ -34134,7 +34812,7 @@ function validatePhaseTransition(workflowType, source, target, isRoundBoundary)
|
|
|
34134
34812
|
}
|
|
34135
34813
|
}
|
|
34136
34814
|
|
|
34137
|
-
// src/
|
|
34815
|
+
// ../shared/persistence/src/state/meta-util.ts
|
|
34138
34816
|
var DEFAULT_METADATA_MAX_LEN = 4096;
|
|
34139
34817
|
function sanitizeMetadataString(s, opts = {}) {
|
|
34140
34818
|
const maxLen = opts.maxLen ?? DEFAULT_METADATA_MAX_LEN;
|
|
@@ -34144,9 +34822,11 @@ function sanitizeMetadataString(s, opts = {}) {
|
|
|
34144
34822
|
return out;
|
|
34145
34823
|
}
|
|
34146
34824
|
|
|
34147
|
-
// src/
|
|
34825
|
+
// ../shared/persistence/src/state/round-meta.ts
|
|
34826
|
+
init_src();
|
|
34148
34827
|
var VALID_CATEGORIES = /* @__PURE__ */ new Set(["blocker", "should_fix", "suggestion", "style"]);
|
|
34149
34828
|
var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "high", "medium", "low", "info"]);
|
|
34829
|
+
var MIN_TITLE_LEN = 8;
|
|
34150
34830
|
function validateRoundMeta(meta) {
|
|
34151
34831
|
if (!meta || typeof meta !== "object") {
|
|
34152
34832
|
throw new Error("round-meta.json must be a JSON object");
|
|
@@ -34157,10 +34837,16 @@ function validateRoundMeta(meta) {
|
|
|
34157
34837
|
`Unsupported schema_version: ${String(obj.schema_version)}. Expected 1.`
|
|
34158
34838
|
);
|
|
34159
34839
|
}
|
|
34160
|
-
if (typeof obj.verdict !== "string"
|
|
34161
|
-
throw new Error("round-meta.json must contain a
|
|
34840
|
+
if (typeof obj.verdict !== "string") {
|
|
34841
|
+
throw new Error("round-meta.json must contain a verdict string");
|
|
34162
34842
|
}
|
|
34163
|
-
|
|
34843
|
+
const verdict = sanitizeMetadataString(obj.verdict).trim();
|
|
34844
|
+
if (!isCanonicalVerdict(verdict)) {
|
|
34845
|
+
throw new Error(
|
|
34846
|
+
`round-meta.json verdict "${String(obj.verdict)}" is not one of: ${CANONICAL_VERDICTS.join(", ")}`
|
|
34847
|
+
);
|
|
34848
|
+
}
|
|
34849
|
+
obj.verdict = verdict;
|
|
34164
34850
|
if (!Array.isArray(obj.reviewers)) {
|
|
34165
34851
|
throw new Error("round-meta.json must contain a reviewers array");
|
|
34166
34852
|
}
|
|
@@ -34183,8 +34869,10 @@ function validateRoundMeta(meta) {
|
|
|
34183
34869
|
throw new Error("Each finding must be an object");
|
|
34184
34870
|
}
|
|
34185
34871
|
const f = finding;
|
|
34186
|
-
if (typeof f.title !== "string" || f.title.trim().length
|
|
34187
|
-
throw new Error(
|
|
34872
|
+
if (typeof f.title !== "string" || f.title.trim().length < MIN_TITLE_LEN) {
|
|
34873
|
+
throw new Error(
|
|
34874
|
+
`Each finding title must be at least ${MIN_TITLE_LEN} characters; got "${String(f.title)}"`
|
|
34875
|
+
);
|
|
34188
34876
|
}
|
|
34189
34877
|
f.title = sanitizeMetadataString(f.title);
|
|
34190
34878
|
if (typeof f.category !== "string" || !VALID_CATEGORIES.has(f.category)) {
|
|
@@ -34229,25 +34917,144 @@ function validateRoundMeta(meta) {
|
|
|
34229
34917
|
if (typeof sc.suggestions !== "number" || sc.suggestions < 0) {
|
|
34230
34918
|
throw new Error("synthesis_counts.suggestions must be a non-negative number");
|
|
34231
34919
|
}
|
|
34920
|
+
const allFindings = obj.reviewers.flatMap((reviewer) => reviewer.findings);
|
|
34921
|
+
const derived = deriveCounts(allFindings);
|
|
34922
|
+
if (sc.blockers > derived.blocker) {
|
|
34923
|
+
throw new Error(
|
|
34924
|
+
`synthesis_counts.blockers (${sc.blockers}) exceeds the ${derived.blocker} blocker finding(s) present`
|
|
34925
|
+
);
|
|
34926
|
+
}
|
|
34927
|
+
if (sc.should_fix > derived.should_fix) {
|
|
34928
|
+
throw new Error(
|
|
34929
|
+
`synthesis_counts.should_fix (${sc.should_fix}) exceeds the ${derived.should_fix} should_fix finding(s) present`
|
|
34930
|
+
);
|
|
34931
|
+
}
|
|
34932
|
+
if (sc.suggestions > derived.suggestion) {
|
|
34933
|
+
throw new Error(
|
|
34934
|
+
`synthesis_counts.suggestions (${sc.suggestions}) exceeds the ${derived.suggestion} suggestion finding(s) present`
|
|
34935
|
+
);
|
|
34936
|
+
}
|
|
34937
|
+
}
|
|
34938
|
+
const { blockerCount } = resolveRoundCounts(obj);
|
|
34939
|
+
if (verdict === "APPROVE" && blockerCount > 0) {
|
|
34940
|
+
throw new Error(
|
|
34941
|
+
`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)`
|
|
34942
|
+
);
|
|
34943
|
+
}
|
|
34944
|
+
if (verdict === "REQUEST CHANGES" && blockerCount === 0) {
|
|
34945
|
+
throw new Error(
|
|
34946
|
+
`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")`
|
|
34947
|
+
);
|
|
34232
34948
|
}
|
|
34233
34949
|
return meta;
|
|
34234
34950
|
}
|
|
34235
34951
|
function computeRoundCounts(meta) {
|
|
34236
|
-
|
|
34237
|
-
|
|
34238
|
-
|
|
34952
|
+
return resolveRoundCounts(meta);
|
|
34953
|
+
}
|
|
34954
|
+
|
|
34955
|
+
// ../shared/persistence/src/state/forward-resume.ts
|
|
34956
|
+
init_db();
|
|
34957
|
+
init_liveness();
|
|
34958
|
+
var FORWARD_RESUME_KIND = "forward_resume";
|
|
34959
|
+
var FORWARD_RESUME_EXHAUSTED_REASON = "forward_resume_exhausted";
|
|
34960
|
+
function parseLeaseMetadata(e) {
|
|
34961
|
+
if (e.event_type !== "session_resumed" || !e.metadata) return null;
|
|
34962
|
+
try {
|
|
34963
|
+
return JSON.parse(e.metadata);
|
|
34964
|
+
} catch {
|
|
34965
|
+
return null;
|
|
34966
|
+
}
|
|
34967
|
+
}
|
|
34968
|
+
function remainingPhasesAfter(workflowType, currentPhase) {
|
|
34969
|
+
const numbers = workflowType === "map" ? MAP_PHASE_NUMBERS : REVIEW_PHASE_NUMBERS;
|
|
34970
|
+
const cur = numbers[currentPhase];
|
|
34971
|
+
if (cur === void 0) return [];
|
|
34972
|
+
return Object.entries(numbers).filter(([, n]) => n > cur).sort((a, b) => a[1] - b[1]).map(([phase]) => phase);
|
|
34973
|
+
}
|
|
34974
|
+
function countForwardResumeLeases(events, round) {
|
|
34975
|
+
return events.filter((e) => parseLeaseMetadata(e)?.kind === FORWARD_RESUME_KIND && parseLeaseMetadata(e)?.round === round).length;
|
|
34976
|
+
}
|
|
34977
|
+
function forwardResumeLeaseState(events, round, leaseMs, nowMs) {
|
|
34978
|
+
const leases = events.filter(
|
|
34979
|
+
(e) => parseLeaseMetadata(e)?.kind === FORWARD_RESUME_KIND && parseLeaseMetadata(e)?.round === round
|
|
34980
|
+
);
|
|
34981
|
+
if (leases.length === 0) return { leaseCount: 0, activeLeaseHeld: false };
|
|
34982
|
+
const latestLease = leases[leases.length - 1];
|
|
34983
|
+
const latestLeaseMs = sqliteUtcMs(latestLease.created_at);
|
|
34984
|
+
let effectiveMs = latestLeaseMs;
|
|
34985
|
+
for (const e of events) {
|
|
34986
|
+
if (e.event_type === "phase_transition" && (e.round == null || e.round === round)) {
|
|
34987
|
+
const t = sqliteUtcMs(e.created_at);
|
|
34988
|
+
if (t >= latestLeaseMs && t > effectiveMs) effectiveMs = t;
|
|
34989
|
+
}
|
|
34239
34990
|
}
|
|
34240
|
-
const sc = meta.synthesis_counts;
|
|
34241
34991
|
return {
|
|
34242
|
-
|
|
34243
|
-
|
|
34244
|
-
|
|
34245
|
-
|
|
34246
|
-
|
|
34992
|
+
leaseCount: leases.length,
|
|
34993
|
+
activeLeaseHeld: nowMs - effectiveMs < leaseMs
|
|
34994
|
+
};
|
|
34995
|
+
}
|
|
34996
|
+
function tryAcquireForwardResumeLease(db, sessionId, round, opts) {
|
|
34997
|
+
const nowMs = opts.nowMs ?? Date.now();
|
|
34998
|
+
return db.transaction(() => {
|
|
34999
|
+
const events = getEventsForSession(db, sessionId);
|
|
35000
|
+
const { leaseCount, activeLeaseHeld } = forwardResumeLeaseState(
|
|
35001
|
+
events,
|
|
35002
|
+
round,
|
|
35003
|
+
opts.leaseMs,
|
|
35004
|
+
nowMs
|
|
35005
|
+
);
|
|
35006
|
+
if (leaseCount >= opts.maxAttempts) {
|
|
35007
|
+
return { acquired: false, reason: "cap_exhausted", attemptsUsed: leaseCount };
|
|
35008
|
+
}
|
|
35009
|
+
if (activeLeaseHeld) {
|
|
35010
|
+
return { acquired: false, reason: "lease_held", attemptsUsed: leaseCount };
|
|
35011
|
+
}
|
|
35012
|
+
insertEvent(db, {
|
|
35013
|
+
session_id: sessionId,
|
|
35014
|
+
event_type: "session_resumed",
|
|
35015
|
+
metadata: JSON.stringify({ kind: FORWARD_RESUME_KIND, round })
|
|
35016
|
+
});
|
|
35017
|
+
return { acquired: true, attemptsUsed: leaseCount + 1 };
|
|
35018
|
+
});
|
|
35019
|
+
}
|
|
35020
|
+
function hasLiveOwningTurn(db, sessionId, heartbeatMs, nowMs) {
|
|
35021
|
+
const instances = listAgentSessionsForWorkflow(db, sessionId);
|
|
35022
|
+
return instances.some(
|
|
35023
|
+
(s) => s.ended_at == null && nowMs - sqliteUtcMs(s.last_heartbeat_at) <= heartbeatMs
|
|
35024
|
+
);
|
|
35025
|
+
}
|
|
35026
|
+
function deriveStrandedStatus(db, session, cfg) {
|
|
35027
|
+
const nowMs = cfg.nowMs ?? Date.now();
|
|
35028
|
+
if (hasLiveOwningTurn(db, session.id, cfg.heartbeatMs, nowMs)) return null;
|
|
35029
|
+
return strandedActionByCap(db, session, cfg.maxAttempts);
|
|
35030
|
+
}
|
|
35031
|
+
function strandedActionByCap(db, session, maxAttempts) {
|
|
35032
|
+
const events = getEventsForSession(db, session.id);
|
|
35033
|
+
const leaseCount = countForwardResumeLeases(events, session.current_round);
|
|
35034
|
+
const workflowType = session.workflow_type === "map" ? "map" : "review";
|
|
35035
|
+
return {
|
|
35036
|
+
action: leaseCount >= maxAttempts ? "abort_or_fresh" : "forward_resume",
|
|
35037
|
+
remainingPhases: remainingPhasesAfter(workflowType, session.current_phase),
|
|
35038
|
+
attemptsRemaining: Math.max(0, maxAttempts - leaseCount)
|
|
34247
35039
|
};
|
|
34248
35040
|
}
|
|
35041
|
+
function closeForwardResumeExhausted(db, sessionId, attempts) {
|
|
35042
|
+
commitReasonClose(
|
|
35043
|
+
db,
|
|
35044
|
+
sessionId,
|
|
35045
|
+
{
|
|
35046
|
+
event_type: "session_auto_closed_stale",
|
|
35047
|
+
phase: "complete",
|
|
35048
|
+
metadata: JSON.stringify({
|
|
35049
|
+
reason: FORWARD_RESUME_EXHAUSTED_REASON,
|
|
35050
|
+
attempts
|
|
35051
|
+
})
|
|
35052
|
+
},
|
|
35053
|
+
{ status: "closed", current_phase: "complete" }
|
|
35054
|
+
);
|
|
35055
|
+
}
|
|
34249
35056
|
|
|
34250
|
-
// src/
|
|
35057
|
+
// ../shared/persistence/src/state/map-meta.ts
|
|
34251
35058
|
function validateMapMeta(meta) {
|
|
34252
35059
|
if (!meta || typeof meta !== "object") {
|
|
34253
35060
|
throw new Error("map-meta.json must be a JSON object");
|
|
@@ -34314,7 +35121,7 @@ function computeMapCounts(meta) {
|
|
|
34314
35121
|
};
|
|
34315
35122
|
}
|
|
34316
35123
|
|
|
34317
|
-
// src/
|
|
35124
|
+
// ../shared/persistence/src/state/projection.ts
|
|
34318
35125
|
init_db();
|
|
34319
35126
|
var REASON_EVENT_TYPES = [
|
|
34320
35127
|
"session_aborted",
|
|
@@ -34344,7 +35151,7 @@ function getCompletenessState(db, sessionId) {
|
|
|
34344
35151
|
return r[0]?.values[0]?.[0] ?? null;
|
|
34345
35152
|
}
|
|
34346
35153
|
|
|
34347
|
-
// src/
|
|
35154
|
+
// ../shared/persistence/src/state/index.ts
|
|
34348
35155
|
init_exit_codes();
|
|
34349
35156
|
function deriveNextRound(db, sessionId, fallbackRound) {
|
|
34350
35157
|
const result = db.exec(
|
|
@@ -34399,6 +35206,12 @@ async function stateInit(params) {
|
|
|
34399
35206
|
`Cannot re-open session ${sessionId} as workflow_type "${workflowType}": existing workflow_type is "${existing.workflow_type}". Maps and reviews have disjoint phase graphs.`
|
|
34400
35207
|
);
|
|
34401
35208
|
}
|
|
35209
|
+
if (existing.status === "active" && !hasCompletionInvariant(db, existing)) {
|
|
35210
|
+
throw new StateError(
|
|
35211
|
+
STATE_EXIT.INVARIANT_UNMET,
|
|
35212
|
+
`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}'.`
|
|
35213
|
+
);
|
|
35214
|
+
}
|
|
34402
35215
|
const nextRound = deriveNextRound(db, sessionId, existing.current_round);
|
|
34403
35216
|
const initialPhase2 = workflowType === "map" ? "map-context" : "context";
|
|
34404
35217
|
db.transaction(() => {
|
|
@@ -34698,18 +35511,19 @@ async function stateCompleteRound(params) {
|
|
|
34698
35511
|
}
|
|
34699
35512
|
const resolved = resolveSession(db, params.sessionId);
|
|
34700
35513
|
const roundNumber = params.round ?? resolved.current_round;
|
|
34701
|
-
const
|
|
34702
|
-
|
|
34703
|
-
|
|
34704
|
-
|
|
34705
|
-
|
|
34706
|
-
|
|
35514
|
+
const roundDir = join17(resolved.session_dir, "rounds", `round-${roundNumber}`);
|
|
35515
|
+
const roundMetaPath = join17(roundDir, "round-meta.json");
|
|
35516
|
+
const materializeArtifact = () => {
|
|
35517
|
+
mkdirSync6(roundDir, { recursive: true });
|
|
35518
|
+
writeFileSync7(roundMetaPath, JSON.stringify(meta, null, 2));
|
|
35519
|
+
};
|
|
34707
35520
|
const already = db.exec(
|
|
34708
35521
|
`SELECT 1 FROM orchestration_events
|
|
34709
35522
|
WHERE session_id = ? AND event_type = 'round_completed' AND round = ? LIMIT 1`,
|
|
34710
35523
|
[resolved.id, roundNumber]
|
|
34711
35524
|
);
|
|
34712
35525
|
if ((already[0]?.values.length ?? 0) > 0) {
|
|
35526
|
+
if (!existsSync15(roundMetaPath)) materializeArtifact();
|
|
34713
35527
|
return { sessionId: resolved.id, round: roundNumber, metaPath: roundMetaPath, schema_version: 1 };
|
|
34714
35528
|
}
|
|
34715
35529
|
if (resolved.current_phase !== "synthesis") {
|
|
@@ -34719,7 +35533,7 @@ async function stateCompleteRound(params) {
|
|
|
34719
35533
|
);
|
|
34720
35534
|
}
|
|
34721
35535
|
if (params.requireFinal) {
|
|
34722
|
-
const finalPath = join17(
|
|
35536
|
+
const finalPath = join17(roundDir, "final.md");
|
|
34723
35537
|
if (!existsSync15(finalPath)) {
|
|
34724
35538
|
throw new StateError(
|
|
34725
35539
|
STATE_EXIT.INVARIANT_UNMET,
|
|
@@ -34727,13 +35541,8 @@ async function stateCompleteRound(params) {
|
|
|
34727
35541
|
);
|
|
34728
35542
|
}
|
|
34729
35543
|
}
|
|
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
|
-
}
|
|
35544
|
+
materializeArtifact();
|
|
35545
|
+
const metaPath = roundMetaPath;
|
|
34737
35546
|
db.transaction(() => {
|
|
34738
35547
|
insertEvent(db, {
|
|
34739
35548
|
session_id: resolved.id,
|
|
@@ -34784,19 +35593,19 @@ async function stateCompleteMap(params) {
|
|
|
34784
35593
|
}
|
|
34785
35594
|
const resolved = resolveSession(db, params.sessionId);
|
|
34786
35595
|
const mapRunNumber = params.mapRun ?? resolved.current_map_run;
|
|
34787
|
-
const
|
|
34788
|
-
|
|
34789
|
-
|
|
34790
|
-
|
|
34791
|
-
|
|
34792
|
-
|
|
34793
|
-
);
|
|
35596
|
+
const runDir = join17(resolved.session_dir, "map", "runs", `run-${mapRunNumber}`);
|
|
35597
|
+
const mapMetaPath = join17(runDir, "map-meta.json");
|
|
35598
|
+
const materializeArtifact = () => {
|
|
35599
|
+
mkdirSync6(runDir, { recursive: true });
|
|
35600
|
+
writeFileSync7(mapMetaPath, JSON.stringify(meta, null, 2));
|
|
35601
|
+
};
|
|
34794
35602
|
const already = db.exec(
|
|
34795
35603
|
`SELECT 1 FROM orchestration_events
|
|
34796
35604
|
WHERE session_id = ? AND event_type = 'map_completed' AND round = ? LIMIT 1`,
|
|
34797
35605
|
[resolved.id, mapRunNumber]
|
|
34798
35606
|
);
|
|
34799
35607
|
if ((already[0]?.values.length ?? 0) > 0) {
|
|
35608
|
+
if (!existsSync15(mapMetaPath)) materializeArtifact();
|
|
34800
35609
|
return { sessionId: resolved.id, mapRun: mapRunNumber, metaPath: mapMetaPath, schema_version: 1 };
|
|
34801
35610
|
}
|
|
34802
35611
|
if (resolved.current_phase !== "synthesis") {
|
|
@@ -34805,13 +35614,8 @@ async function stateCompleteMap(params) {
|
|
|
34805
35614
|
`Cannot complete map: workflow is at "${resolved.current_phase}", not "synthesis". Advance first.`
|
|
34806
35615
|
);
|
|
34807
35616
|
}
|
|
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
|
-
}
|
|
35617
|
+
materializeArtifact();
|
|
35618
|
+
const metaPath = mapMetaPath;
|
|
34815
35619
|
db.transaction(() => {
|
|
34816
35620
|
insertEvent(db, {
|
|
34817
35621
|
session_id: resolved.id,
|
|
@@ -34837,7 +35641,7 @@ async function stateCompleteMap(params) {
|
|
|
34837
35641
|
});
|
|
34838
35642
|
return { sessionId: resolved.id, mapRun: mapRunNumber, metaPath, schema_version: 1 };
|
|
34839
35643
|
}
|
|
34840
|
-
async function stateStatus(ocrDir, sessionId) {
|
|
35644
|
+
async function stateStatus(ocrDir, sessionId, forwardResume) {
|
|
34841
35645
|
const db = await ensureDatabase(ocrDir);
|
|
34842
35646
|
const resolved = resolveSession(db, sessionId);
|
|
34843
35647
|
const view = db.exec(
|
|
@@ -34850,6 +35654,8 @@ async function stateStatus(ocrDir, sessionId) {
|
|
|
34850
35654
|
const hasTerminalArtifact = row?.[1] === 1;
|
|
34851
35655
|
let nextAction;
|
|
34852
35656
|
let nextActionKind;
|
|
35657
|
+
let remainingPhases;
|
|
35658
|
+
let attemptsRemaining;
|
|
34853
35659
|
switch (completenessState) {
|
|
34854
35660
|
case "complete":
|
|
34855
35661
|
nextAction = "none \u2014 session is complete";
|
|
@@ -34867,12 +35673,25 @@ async function stateStatus(ocrDir, sessionId) {
|
|
|
34867
35673
|
if (hasTerminalArtifact) {
|
|
34868
35674
|
nextAction = "run 'ocr state finish' to close the workflow";
|
|
34869
35675
|
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
35676
|
} else {
|
|
34874
|
-
|
|
34875
|
-
|
|
35677
|
+
const stranded = forwardResume && resolved.status === "active" ? deriveStrandedStatus(db, resolved, forwardResume) : null;
|
|
35678
|
+
if (stranded) {
|
|
35679
|
+
remainingPhases = stranded.remainingPhases;
|
|
35680
|
+
attemptsRemaining = stranded.attemptsRemaining;
|
|
35681
|
+
if (stranded.action === "forward_resume") {
|
|
35682
|
+
nextAction = `forward-resume from '${resolved.current_phase}': re-run the review (it continues via 'ocr state status --json'), or 'ocr review --resume ${resolved.id}'`;
|
|
35683
|
+
nextActionKind = "forward_resume";
|
|
35684
|
+
} else {
|
|
35685
|
+
nextAction = "forward-resume attempts exhausted \u2014 abort with 'ocr state finish --abort' or start a fresh review";
|
|
35686
|
+
nextActionKind = "abort_or_fresh";
|
|
35687
|
+
}
|
|
35688
|
+
} else if (resolved.current_phase === "synthesis") {
|
|
35689
|
+
nextAction = "pipe round metadata to 'ocr state complete-round --stdin'";
|
|
35690
|
+
nextActionKind = "complete_round";
|
|
35691
|
+
} else {
|
|
35692
|
+
nextAction = "advance through the phases, then 'ocr state complete-round'";
|
|
35693
|
+
nextActionKind = "advance";
|
|
35694
|
+
}
|
|
34876
35695
|
}
|
|
34877
35696
|
}
|
|
34878
35697
|
return {
|
|
@@ -34888,7 +35707,9 @@ async function stateStatus(ocrDir, sessionId) {
|
|
|
34888
35707
|
marked_closed: row?.[2] === 1,
|
|
34889
35708
|
dependents_settled: row?.[3] === 1,
|
|
34890
35709
|
next_action: nextAction,
|
|
34891
|
-
next_action_kind: nextActionKind
|
|
35710
|
+
next_action_kind: nextActionKind,
|
|
35711
|
+
...remainingPhases ? { remaining_phases: remainingPhases } : {},
|
|
35712
|
+
...attemptsRemaining !== void 0 ? { forward_resume_attempts_remaining: attemptsRemaining } : {}
|
|
34892
35713
|
};
|
|
34893
35714
|
}
|
|
34894
35715
|
async function stateSync(ocrDir) {
|
|
@@ -34976,14 +35797,73 @@ async function stateSync(ocrDir) {
|
|
|
34976
35797
|
}
|
|
34977
35798
|
|
|
34978
35799
|
// src/commands/state.ts
|
|
34979
|
-
init_command_log();
|
|
34980
35800
|
init_db();
|
|
34981
35801
|
init_db();
|
|
34982
|
-
|
|
34983
|
-
|
|
35802
|
+
|
|
35803
|
+
// ../shared/config/src/runtime-config.ts
|
|
35804
|
+
import { existsSync as existsSync16, readFileSync as readFileSync11 } from "node:fs";
|
|
35805
|
+
import { join as join18 } from "node:path";
|
|
35806
|
+
var DEFAULT_AGENT_HEARTBEAT_SECONDS = 60;
|
|
35807
|
+
var DEFAULT_FORWARD_RESUME_MAX_ATTEMPTS = 2;
|
|
35808
|
+
var DEFAULT_FORWARD_RESUME_LEASE_SECONDS = 1800;
|
|
35809
|
+
function readRuntimePositiveInt(ocrDir, key, defaultValue) {
|
|
35810
|
+
const configPath = join18(ocrDir, "config.yaml");
|
|
35811
|
+
if (!existsSync16(configPath)) return defaultValue;
|
|
35812
|
+
let content;
|
|
35813
|
+
try {
|
|
35814
|
+
content = readFileSync11(configPath, "utf-8");
|
|
35815
|
+
} catch {
|
|
35816
|
+
return defaultValue;
|
|
35817
|
+
}
|
|
35818
|
+
const blockMatch = content.match(
|
|
35819
|
+
new RegExp(
|
|
35820
|
+
String.raw`^runtime:\s*\n(?:\s+[^\n]*\n)*?\s+${key}:\s*([^\s#\n]+)`,
|
|
35821
|
+
"m"
|
|
35822
|
+
)
|
|
35823
|
+
);
|
|
35824
|
+
const inlineMatch = content.match(
|
|
35825
|
+
new RegExp(String.raw`^runtime:\s*\{[^}]*\b${key}:\s*([^\s,}]+)`, "m")
|
|
35826
|
+
);
|
|
35827
|
+
const raw = blockMatch?.[1] ?? inlineMatch?.[1];
|
|
35828
|
+
if (!raw) return defaultValue;
|
|
35829
|
+
const parsed = Number(raw);
|
|
35830
|
+
if (!Number.isFinite(parsed) || parsed <= 0 || !Number.isInteger(parsed)) {
|
|
35831
|
+
process.stderr.write(
|
|
35832
|
+
`[ocr] runtime.${key} is not a positive integer (got "${raw}"); falling back to ${defaultValue}.
|
|
35833
|
+
`
|
|
35834
|
+
);
|
|
35835
|
+
return defaultValue;
|
|
35836
|
+
}
|
|
35837
|
+
return parsed;
|
|
35838
|
+
}
|
|
35839
|
+
function getAgentHeartbeatSeconds(ocrDir) {
|
|
35840
|
+
return readRuntimePositiveInt(
|
|
35841
|
+
ocrDir,
|
|
35842
|
+
"agent_heartbeat_seconds",
|
|
35843
|
+
DEFAULT_AGENT_HEARTBEAT_SECONDS
|
|
35844
|
+
);
|
|
35845
|
+
}
|
|
35846
|
+
function getForwardResumeMaxAttempts(ocrDir) {
|
|
35847
|
+
return readRuntimePositiveInt(
|
|
35848
|
+
ocrDir,
|
|
35849
|
+
"forward_resume_max_attempts",
|
|
35850
|
+
DEFAULT_FORWARD_RESUME_MAX_ATTEMPTS
|
|
35851
|
+
);
|
|
35852
|
+
}
|
|
35853
|
+
function getForwardResumeLeaseMs(ocrDir) {
|
|
35854
|
+
return readRuntimePositiveInt(
|
|
35855
|
+
ocrDir,
|
|
35856
|
+
"forward_resume_lease_seconds",
|
|
35857
|
+
DEFAULT_FORWARD_RESUME_LEASE_SECONDS
|
|
35858
|
+
) * 1e3;
|
|
35859
|
+
}
|
|
35860
|
+
|
|
35861
|
+
// src/commands/state.ts
|
|
35862
|
+
init_db();
|
|
35863
|
+
function readMarkerFile(path2) {
|
|
34984
35864
|
let raw;
|
|
34985
35865
|
try {
|
|
34986
|
-
raw =
|
|
35866
|
+
raw = readFileSync12(path2, "utf-8");
|
|
34987
35867
|
} catch {
|
|
34988
35868
|
return null;
|
|
34989
35869
|
}
|
|
@@ -35004,6 +35884,30 @@ function readDashboardSpawnMarker(ocrDir) {
|
|
|
35004
35884
|
}
|
|
35005
35885
|
return marker;
|
|
35006
35886
|
}
|
|
35887
|
+
function readDashboardSpawnMarker(ocrDir) {
|
|
35888
|
+
const dir = join19(ocrDir, "data", "dashboard-active-spawn");
|
|
35889
|
+
let entries = [];
|
|
35890
|
+
try {
|
|
35891
|
+
entries = readdirSync8(dir).filter((f) => f.endsWith(".json"));
|
|
35892
|
+
} catch {
|
|
35893
|
+
entries = [];
|
|
35894
|
+
}
|
|
35895
|
+
const live = [];
|
|
35896
|
+
for (const entry of entries) {
|
|
35897
|
+
const marker = readMarkerFile(join19(dir, entry));
|
|
35898
|
+
if (marker) live.push(marker);
|
|
35899
|
+
}
|
|
35900
|
+
if (live.length === 1) return live[0] ?? null;
|
|
35901
|
+
if (live.length > 1) {
|
|
35902
|
+
console.error(
|
|
35903
|
+
source_default.gray(
|
|
35904
|
+
`[state] ${live.length} concurrent dashboard spawns live; marker fallback is ambiguous \u2014 pass --dashboard-uid for linkage`
|
|
35905
|
+
)
|
|
35906
|
+
);
|
|
35907
|
+
return null;
|
|
35908
|
+
}
|
|
35909
|
+
return readMarkerFile(join19(ocrDir, "data", "dashboard-active-spawn.json"));
|
|
35910
|
+
}
|
|
35007
35911
|
async function readStdin() {
|
|
35008
35912
|
const chunks = [];
|
|
35009
35913
|
for await (const chunk of process.stdin) {
|
|
@@ -35045,7 +35949,7 @@ async function linkDashboardInvocation(ocrDir, sessionId, explicitUid, label) {
|
|
|
35045
35949
|
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
35950
|
const targetDir = process.cwd();
|
|
35047
35951
|
requireOcrSetup(targetDir);
|
|
35048
|
-
const ocrDir =
|
|
35952
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35049
35953
|
try {
|
|
35050
35954
|
const result = await stateShow(ocrDir, options.sessionId);
|
|
35051
35955
|
if (!result) {
|
|
@@ -35114,7 +36018,7 @@ var showSubcommand = new Command("show").description("Show current session state
|
|
|
35114
36018
|
var syncSubcommand = new Command("sync").description("Rebuild session state from filesystem artifacts").action(async () => {
|
|
35115
36019
|
const targetDir = process.cwd();
|
|
35116
36020
|
requireOcrSetup(targetDir);
|
|
35117
|
-
const ocrDir =
|
|
36021
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35118
36022
|
try {
|
|
35119
36023
|
const synced = await stateSync(ocrDir);
|
|
35120
36024
|
console.log(`Synced ${synced} session${synced !== 1 ? "s" : ""} from filesystem.`);
|
|
@@ -35141,7 +36045,7 @@ var reconcileSubcommand = new Command("reconcile").description(
|
|
|
35141
36045
|
).option("--dry-run", "Print the repair plan without writing anything").option("--json", "Output the result as JSON").action(async (options) => {
|
|
35142
36046
|
const targetDir = process.cwd();
|
|
35143
36047
|
requireOcrSetup(targetDir);
|
|
35144
|
-
const ocrDir =
|
|
36048
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35145
36049
|
try {
|
|
35146
36050
|
const db = await ensureDatabase(ocrDir);
|
|
35147
36051
|
const result = reconcileLegacyState(db, ocrDir, { dryRun: options.dryRun });
|
|
@@ -35200,9 +36104,9 @@ var beginSubcommand = new Command("begin").description("Start or resume a workfl
|
|
|
35200
36104
|
async (options) => {
|
|
35201
36105
|
const targetDir = process.cwd();
|
|
35202
36106
|
requireOcrSetup(targetDir);
|
|
35203
|
-
const ocrDir =
|
|
35204
|
-
const sessionDir = options.sessionDir ??
|
|
35205
|
-
if (!
|
|
36107
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
36108
|
+
const sessionDir = options.sessionDir ?? join19(ocrDir, "sessions", options.sessionId);
|
|
36109
|
+
if (!existsSync17(sessionDir)) mkdirSync7(sessionDir, { recursive: true });
|
|
35206
36110
|
try {
|
|
35207
36111
|
const result = await stateBegin({
|
|
35208
36112
|
sessionId: options.sessionId,
|
|
@@ -35224,7 +36128,7 @@ var advanceSubcommand = new Command("advance").description("Advance the workflow
|
|
|
35224
36128
|
async (options) => {
|
|
35225
36129
|
const targetDir = process.cwd();
|
|
35226
36130
|
requireOcrSetup(targetDir);
|
|
35227
|
-
const ocrDir =
|
|
36131
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35228
36132
|
try {
|
|
35229
36133
|
const { id: sessionId } = await resolveActiveSession(ocrDir, options.sessionId);
|
|
35230
36134
|
await stateAdvance({
|
|
@@ -35244,7 +36148,7 @@ var completeRoundSubcommand = new Command("complete-round").description("Atomica
|
|
|
35244
36148
|
async (options) => {
|
|
35245
36149
|
const targetDir = process.cwd();
|
|
35246
36150
|
requireOcrSetup(targetDir);
|
|
35247
|
-
const ocrDir =
|
|
36151
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35248
36152
|
try {
|
|
35249
36153
|
const base = options.stdin ? { source: "stdin", data: await readStdin() } : options.file ? { source: "file", filePath: options.file } : (() => {
|
|
35250
36154
|
throw new StateError(STATE_EXIT.USAGE, "Provide --stdin or --file with round metadata");
|
|
@@ -35268,7 +36172,7 @@ var completeMapSubcommand = new Command("complete-map").description("Atomically
|
|
|
35268
36172
|
async (options) => {
|
|
35269
36173
|
const targetDir = process.cwd();
|
|
35270
36174
|
requireOcrSetup(targetDir);
|
|
35271
|
-
const ocrDir =
|
|
36175
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35272
36176
|
try {
|
|
35273
36177
|
const base = options.stdin ? { source: "stdin", data: await readStdin() } : options.file ? { source: "file", filePath: options.file } : (() => {
|
|
35274
36178
|
throw new StateError(STATE_EXIT.USAGE, "Provide --stdin or --file with map metadata");
|
|
@@ -35290,7 +36194,7 @@ var completeMapSubcommand = new Command("complete-map").description("Atomically
|
|
|
35290
36194
|
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
36195
|
const targetDir = process.cwd();
|
|
35292
36196
|
requireOcrSetup(targetDir);
|
|
35293
|
-
const ocrDir =
|
|
36197
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35294
36198
|
try {
|
|
35295
36199
|
const { id: sessionId } = await resolveActiveSession(ocrDir, options.sessionId);
|
|
35296
36200
|
await stateClose({ sessionId, ocrDir, abort: options.abort });
|
|
@@ -35302,14 +36206,20 @@ var finishSubcommand = new Command("finish").description("Close a workflow (refu
|
|
|
35302
36206
|
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
36207
|
const targetDir = process.cwd();
|
|
35304
36208
|
requireOcrSetup(targetDir);
|
|
35305
|
-
const ocrDir =
|
|
36209
|
+
const ocrDir = join19(targetDir, ".ocr");
|
|
35306
36210
|
try {
|
|
35307
|
-
const result = await stateStatus(ocrDir, options.sessionId
|
|
36211
|
+
const result = await stateStatus(ocrDir, options.sessionId, {
|
|
36212
|
+
maxAttempts: getForwardResumeMaxAttempts(ocrDir),
|
|
36213
|
+
heartbeatMs: getAgentHeartbeatSeconds(ocrDir) * 1e3
|
|
36214
|
+
});
|
|
35308
36215
|
if (options.json) {
|
|
35309
36216
|
console.log(JSON.stringify(result, null, 2));
|
|
35310
36217
|
} else {
|
|
35311
36218
|
console.log(`${result.session_id}: ${result.completeness_state}`);
|
|
35312
36219
|
console.log(source_default.dim(` next: ${result.next_action}`));
|
|
36220
|
+
if (result.remaining_phases?.length) {
|
|
36221
|
+
console.log(source_default.dim(` remaining: ${result.remaining_phases.join(" \u2192 ")}`));
|
|
36222
|
+
}
|
|
35313
36223
|
}
|
|
35314
36224
|
} catch (error) {
|
|
35315
36225
|
exitFromStateError(error, "Failed to read status");
|
|
@@ -35333,50 +36243,6 @@ var stateCommand = new Command("state").description("Manage OCR session state").
|
|
|
35333
36243
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
35334
36244
|
import { join as join20 } from "node:path";
|
|
35335
36245
|
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
36246
|
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
35381
36247
|
"done",
|
|
35382
36248
|
"crashed",
|
|
@@ -35427,6 +36293,11 @@ var startInstanceSubcommand = new Command("start-instance").description("Journal
|
|
|
35427
36293
|
}
|
|
35428
36294
|
);
|
|
35429
36295
|
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) => {
|
|
36296
|
+
if (!SAFE_VENDOR_SESSION_ID.test(vendorId)) {
|
|
36297
|
+
fail(
|
|
36298
|
+
`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.`
|
|
36299
|
+
);
|
|
36300
|
+
}
|
|
35430
36301
|
const { ocrDir } = await setup();
|
|
35431
36302
|
const db = await ensureDatabase(ocrDir);
|
|
35432
36303
|
try {
|
|
@@ -35524,7 +36395,7 @@ var listSubcommand = new Command("list").description("List agent sessions for a
|
|
|
35524
36395
|
});
|
|
35525
36396
|
var sessionCommand = new Command("session").description("Manage agent-CLI session lifecycle journal").addCommand(startInstanceSubcommand).addCommand(bindVendorIdSubcommand).addCommand(beatSubcommand).addCommand(endInstanceSubcommand).addCommand(listSubcommand);
|
|
35526
36397
|
|
|
35527
|
-
// src/
|
|
36398
|
+
// ../shared/config/src/models.ts
|
|
35528
36399
|
init_src();
|
|
35529
36400
|
function parseOpenCodeModelList(stdout) {
|
|
35530
36401
|
const models = [];
|
|
@@ -35926,11 +36797,11 @@ function pairKey(pair) {
|
|
|
35926
36797
|
var teamCommand = new Command("team").description("Resolve and persist team composition").addCommand(resolveSubcommand).addCommand(setSubcommand);
|
|
35927
36798
|
|
|
35928
36799
|
// src/commands/review.ts
|
|
35929
|
-
|
|
36800
|
+
init_src();
|
|
35930
36801
|
import { join as join22 } from "node:path";
|
|
35931
36802
|
init_db();
|
|
35932
36803
|
|
|
35933
|
-
// src/
|
|
36804
|
+
// ../shared/persistence/src/vendor-resume.ts
|
|
35934
36805
|
var VENDOR_BINARIES = {
|
|
35935
36806
|
claude: "claude",
|
|
35936
36807
|
opencode: "opencode"
|
|
@@ -35952,6 +36823,7 @@ function fail3(message) {
|
|
|
35952
36823
|
console.error(source_default.red(`Error: ${message}`));
|
|
35953
36824
|
process.exit(1);
|
|
35954
36825
|
}
|
|
36826
|
+
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
36827
|
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
36828
|
if (!options.resume) {
|
|
35957
36829
|
console.error(
|
|
@@ -35968,21 +36840,89 @@ var reviewCommand = new Command("review").description("Run or resume an OCR revi
|
|
|
35968
36840
|
requireOcrSetup(targetDir);
|
|
35969
36841
|
const ocrDir = join22(targetDir, ".ocr");
|
|
35970
36842
|
const db = await ensureDatabase(ocrDir);
|
|
35971
|
-
const
|
|
36843
|
+
const workflowId = options.resume;
|
|
36844
|
+
const session = getSession(db, workflowId);
|
|
35972
36845
|
if (!session) {
|
|
35973
|
-
fail3(`Workflow session not found: ${
|
|
36846
|
+
fail3(`Workflow session not found: ${workflowId}`);
|
|
36847
|
+
}
|
|
36848
|
+
const maxAttempts = getForwardResumeMaxAttempts(ocrDir);
|
|
36849
|
+
const leaseMs = getForwardResumeLeaseMs(ocrDir);
|
|
36850
|
+
const heartbeatMs = getAgentHeartbeatSeconds(ocrDir) * 1e3;
|
|
36851
|
+
const status = await stateStatus(ocrDir, workflowId, {
|
|
36852
|
+
maxAttempts,
|
|
36853
|
+
heartbeatMs
|
|
36854
|
+
});
|
|
36855
|
+
switch (status.next_action_kind) {
|
|
36856
|
+
case "none":
|
|
36857
|
+
console.error(source_default.green(`Workflow ${workflowId} is already complete \u2014 nothing to resume.`));
|
|
36858
|
+
process.exit(0);
|
|
36859
|
+
break;
|
|
36860
|
+
case "finish":
|
|
36861
|
+
console.error(
|
|
36862
|
+
source_default.yellow(`Workflow ${workflowId}'s round is complete but the session is still open.`)
|
|
36863
|
+
);
|
|
36864
|
+
console.error(source_default.dim("Run `ocr state finish` to close it."));
|
|
36865
|
+
process.exit(0);
|
|
36866
|
+
break;
|
|
36867
|
+
case "abort_or_fresh": {
|
|
36868
|
+
closeForwardResumeExhausted(db, workflowId, maxAttempts);
|
|
36869
|
+
fail3(
|
|
36870
|
+
`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.`
|
|
36871
|
+
);
|
|
36872
|
+
break;
|
|
36873
|
+
}
|
|
36874
|
+
case "advance":
|
|
36875
|
+
case "complete_round":
|
|
36876
|
+
case "wait":
|
|
36877
|
+
console.error(
|
|
36878
|
+
source_default.yellow(
|
|
36879
|
+
`Workflow ${workflowId} appears to still be running (phase "${status.current_phase}"). Nothing to resume yet.`
|
|
36880
|
+
)
|
|
36881
|
+
);
|
|
36882
|
+
process.exit(0);
|
|
36883
|
+
break;
|
|
36884
|
+
case "reopen":
|
|
36885
|
+
console.error(
|
|
36886
|
+
source_default.yellow(`Workflow ${workflowId} was closed without a completed round.`)
|
|
36887
|
+
);
|
|
36888
|
+
console.error(source_default.dim("Re-invoke the review skill to finalize it."));
|
|
36889
|
+
process.exit(0);
|
|
36890
|
+
break;
|
|
35974
36891
|
}
|
|
35975
|
-
const
|
|
35976
|
-
|
|
36892
|
+
const lease = tryAcquireForwardResumeLease(db, workflowId, session.current_round, {
|
|
36893
|
+
leaseMs,
|
|
36894
|
+
maxAttempts
|
|
36895
|
+
});
|
|
36896
|
+
if (!lease.acquired) {
|
|
36897
|
+
if (lease.reason === "cap_exhausted") {
|
|
36898
|
+
closeForwardResumeExhausted(db, workflowId, lease.attemptsUsed);
|
|
36899
|
+
fail3(
|
|
36900
|
+
`Forward-resume attempts exhausted for workflow ${workflowId} (cap ${maxAttempts}). Closed non-success (artifacts preserved). Start a fresh review.`
|
|
36901
|
+
);
|
|
36902
|
+
}
|
|
35977
36903
|
fail3(
|
|
35978
|
-
`
|
|
36904
|
+
`A forward-resume is already in progress for workflow ${workflowId} (lease held). Wait for it to finish or retry after the lease expires.`
|
|
35979
36905
|
);
|
|
35980
36906
|
}
|
|
35981
|
-
|
|
35982
|
-
|
|
35983
|
-
|
|
35984
|
-
|
|
36907
|
+
console.error(
|
|
36908
|
+
source_default.dim(
|
|
36909
|
+
`Forward-resuming workflow ${session.id} on branch ${session.branch} from phase "${status.current_phase}" (${status.forward_resume_attempts_remaining ?? "?"} attempt(s) left).`
|
|
36910
|
+
)
|
|
36911
|
+
);
|
|
36912
|
+
const latest = getLatestAgentSessionWithVendorId(db, workflowId);
|
|
36913
|
+
const binary = latest?.vendor ? VENDOR_BINARIES[latest.vendor] : void 0;
|
|
36914
|
+
if (!latest || !latest.vendor_session_id || !binary) {
|
|
36915
|
+
console.error(
|
|
36916
|
+
source_default.yellow(
|
|
36917
|
+
`No resumable vendor session is captured for workflow ${workflowId}.`
|
|
36918
|
+
)
|
|
35985
36919
|
);
|
|
36920
|
+
console.error(
|
|
36921
|
+
source_default.dim(
|
|
36922
|
+
`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})`
|
|
36923
|
+
)
|
|
36924
|
+
);
|
|
36925
|
+
process.exit(0);
|
|
35986
36926
|
}
|
|
35987
36927
|
let args;
|
|
35988
36928
|
try {
|
|
@@ -35990,12 +36930,8 @@ var reviewCommand = new Command("review").description("Run or resume an OCR revi
|
|
|
35990
36930
|
} catch (err) {
|
|
35991
36931
|
fail3(err instanceof Error ? err.message : String(err));
|
|
35992
36932
|
}
|
|
35993
|
-
console.error(
|
|
35994
|
-
|
|
35995
|
-
`Resuming workflow ${session.id} on branch ${session.branch} via ${binary}\u2026`
|
|
35996
|
-
)
|
|
35997
|
-
);
|
|
35998
|
-
const child = spawn3(binary, args, {
|
|
36933
|
+
console.error(source_default.dim(`Resuming via ${binary} (continue forward from "${status.current_phase}")\u2026`));
|
|
36934
|
+
const child = spawnBinary(binary, args, {
|
|
35999
36935
|
stdio: "inherit",
|
|
36000
36936
|
cwd: targetDir
|
|
36001
36937
|
});
|