@cleocode/cleo 2026.5.131 → 2026.5.132
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +702 -467
- package/dist/cli/index.js.map +3 -3
- package/package.json +12 -11
package/dist/cli/index.js
CHANGED
|
@@ -47108,24 +47108,143 @@ var init_server = __esm({
|
|
|
47108
47108
|
}
|
|
47109
47109
|
});
|
|
47110
47110
|
|
|
47111
|
-
// packages/cleo/src/cli/
|
|
47112
|
-
import {
|
|
47113
|
-
import { open as fsOpen } from "node:fs/promises";
|
|
47111
|
+
// packages/cleo/src/cli/docs-viewer-subsystem.ts
|
|
47112
|
+
import { mkdir as mkdir2 } from "node:fs/promises";
|
|
47114
47113
|
import { join as join20 } from "node:path";
|
|
47115
|
-
import {
|
|
47116
|
-
import {
|
|
47117
|
-
function
|
|
47118
|
-
const
|
|
47119
|
-
return
|
|
47114
|
+
import { getCleoHome as getCleoHome3 } from "@cleocode/core";
|
|
47115
|
+
import { defineSubsystem } from "@cleocode/runtime/daemon";
|
|
47116
|
+
function getViewerPaths() {
|
|
47117
|
+
const cleoHome = getCleoHome3();
|
|
47118
|
+
return {
|
|
47119
|
+
pidFile: viewerPidFilePath(),
|
|
47120
|
+
logFile: join20(cleoHome, "viewer.log"),
|
|
47121
|
+
logDir: cleoHome
|
|
47122
|
+
};
|
|
47123
|
+
}
|
|
47124
|
+
function isViewerProcessRunning(pid) {
|
|
47125
|
+
return isProcessAlive(pid);
|
|
47120
47126
|
}
|
|
47121
|
-
async function
|
|
47122
|
-
const
|
|
47123
|
-
|
|
47124
|
-
|
|
47125
|
-
await
|
|
47127
|
+
async function getViewerStatus() {
|
|
47128
|
+
const record = await readViewerPidFile();
|
|
47129
|
+
if (!record) return { running: false, pid: null, port: null, host: null, url: null };
|
|
47130
|
+
if (!isProcessAlive(record.pid)) {
|
|
47131
|
+
await removeViewerPidFile();
|
|
47132
|
+
return { running: false, pid: null, port: null, host: null, url: null };
|
|
47126
47133
|
}
|
|
47127
|
-
return
|
|
47134
|
+
return {
|
|
47135
|
+
running: true,
|
|
47136
|
+
pid: record.pid,
|
|
47137
|
+
port: record.port,
|
|
47138
|
+
host: record.host,
|
|
47139
|
+
url: `http://${record.host}:${record.port}`
|
|
47140
|
+
};
|
|
47128
47141
|
}
|
|
47142
|
+
function createDocsViewerSubsystem(opts = {}) {
|
|
47143
|
+
const startPort = opts.startPort ?? VIEWER_DEFAULT_PORT;
|
|
47144
|
+
const endPort = opts.endPort ?? VIEWER_DEFAULT_END_PORT;
|
|
47145
|
+
const host = opts.host ?? VIEWER_DEFAULT_HOST;
|
|
47146
|
+
const autoIncrement = !(opts.noAutoPort ?? false);
|
|
47147
|
+
let live;
|
|
47148
|
+
return defineSubsystem({
|
|
47149
|
+
name: VIEWER_SUBSYSTEM_NAME,
|
|
47150
|
+
async start() {
|
|
47151
|
+
const { pidFile, logDir } = getViewerPaths();
|
|
47152
|
+
const existing = await getViewerStatus();
|
|
47153
|
+
if (existing.running && existing.pid !== null) {
|
|
47154
|
+
const ctx2 = {
|
|
47155
|
+
pid: existing.pid,
|
|
47156
|
+
pidFile,
|
|
47157
|
+
port: existing.port ?? startPort,
|
|
47158
|
+
host: existing.host ?? host
|
|
47159
|
+
};
|
|
47160
|
+
live = ctx2;
|
|
47161
|
+
return ctx2;
|
|
47162
|
+
}
|
|
47163
|
+
await mkdir2(logDir, { recursive: true });
|
|
47164
|
+
const handle = await startViewer({
|
|
47165
|
+
startPort,
|
|
47166
|
+
endPort,
|
|
47167
|
+
host,
|
|
47168
|
+
autoIncrement
|
|
47169
|
+
});
|
|
47170
|
+
await writeViewerPidFile({
|
|
47171
|
+
pid: process.pid,
|
|
47172
|
+
port: handle.port,
|
|
47173
|
+
host: handle.host,
|
|
47174
|
+
projectRoot: process.cwd(),
|
|
47175
|
+
startedAt: Date.now()
|
|
47176
|
+
});
|
|
47177
|
+
const ctx = {
|
|
47178
|
+
pid: process.pid,
|
|
47179
|
+
pidFile,
|
|
47180
|
+
port: handle.port,
|
|
47181
|
+
host: handle.host
|
|
47182
|
+
};
|
|
47183
|
+
live = ctx;
|
|
47184
|
+
return ctx;
|
|
47185
|
+
},
|
|
47186
|
+
healthProbe() {
|
|
47187
|
+
if (live === void 0) {
|
|
47188
|
+
const stopped = "stopped";
|
|
47189
|
+
return {
|
|
47190
|
+
child_id: VIEWER_SUBSYSTEM_NAME,
|
|
47191
|
+
pid: 0,
|
|
47192
|
+
state: stopped,
|
|
47193
|
+
restart_count: 0,
|
|
47194
|
+
detail: "not started"
|
|
47195
|
+
};
|
|
47196
|
+
}
|
|
47197
|
+
const alive = isViewerProcessRunning(live.pid);
|
|
47198
|
+
const state = alive ? "running" : "stopped";
|
|
47199
|
+
return {
|
|
47200
|
+
child_id: VIEWER_SUBSYSTEM_NAME,
|
|
47201
|
+
pid: alive ? live.pid : 0,
|
|
47202
|
+
state,
|
|
47203
|
+
restart_count: 0,
|
|
47204
|
+
detail: alive ? `url=http://${live.host}:${live.port} pid=${live.pid}` : `pid=${live.pid} exited`
|
|
47205
|
+
};
|
|
47206
|
+
},
|
|
47207
|
+
async shutdown(context) {
|
|
47208
|
+
if (!isViewerProcessRunning(context.pid)) {
|
|
47209
|
+
await removeViewerPidFile();
|
|
47210
|
+
live = void 0;
|
|
47211
|
+
return;
|
|
47212
|
+
}
|
|
47213
|
+
try {
|
|
47214
|
+
process.kill(context.pid, "SIGTERM");
|
|
47215
|
+
} catch {
|
|
47216
|
+
}
|
|
47217
|
+
for (let i = 0; i < SIGTERM_GRACE_ITERATIONS; i++) {
|
|
47218
|
+
if (!isViewerProcessRunning(context.pid)) break;
|
|
47219
|
+
await new Promise((resolve11) => setTimeout(resolve11, 500));
|
|
47220
|
+
}
|
|
47221
|
+
if (isViewerProcessRunning(context.pid)) {
|
|
47222
|
+
try {
|
|
47223
|
+
process.kill(context.pid, "SIGKILL");
|
|
47224
|
+
} catch {
|
|
47225
|
+
}
|
|
47226
|
+
}
|
|
47227
|
+
await removeViewerPidFile();
|
|
47228
|
+
live = void 0;
|
|
47229
|
+
}
|
|
47230
|
+
});
|
|
47231
|
+
}
|
|
47232
|
+
var VIEWER_DEFAULT_PORT, VIEWER_DEFAULT_END_PORT, VIEWER_DEFAULT_HOST, VIEWER_SUBSYSTEM_NAME, SIGTERM_GRACE_ITERATIONS;
|
|
47233
|
+
var init_docs_viewer_subsystem = __esm({
|
|
47234
|
+
"packages/cleo/src/cli/docs-viewer-subsystem.ts"() {
|
|
47235
|
+
"use strict";
|
|
47236
|
+
init_pidfile();
|
|
47237
|
+
init_server();
|
|
47238
|
+
VIEWER_DEFAULT_PORT = 7777;
|
|
47239
|
+
VIEWER_DEFAULT_END_PORT = 7800;
|
|
47240
|
+
VIEWER_DEFAULT_HOST = "127.0.0.1";
|
|
47241
|
+
VIEWER_SUBSYSTEM_NAME = "cleo-docs-viewer";
|
|
47242
|
+
SIGTERM_GRACE_ITERATIONS = 20;
|
|
47243
|
+
}
|
|
47244
|
+
});
|
|
47245
|
+
|
|
47246
|
+
// packages/cleo/src/cli/commands/docs-viewer.ts
|
|
47247
|
+
import { spawn } from "node:child_process";
|
|
47129
47248
|
function openInBrowser(url) {
|
|
47130
47249
|
try {
|
|
47131
47250
|
let cmd;
|
|
@@ -47144,72 +47263,40 @@ function openInBrowser(url) {
|
|
|
47144
47263
|
} catch {
|
|
47145
47264
|
}
|
|
47146
47265
|
}
|
|
47147
|
-
|
|
47148
|
-
const logFile = join20(getCleoHome3(), "viewer.log");
|
|
47149
|
-
const handle = await fsOpen(logFile, "a").catch(() => null);
|
|
47150
|
-
const stdio = handle ? ["ignore", handle.fd, handle.fd] : ["ignore", "ignore", "ignore"];
|
|
47151
|
-
const args = [
|
|
47152
|
-
getCleoBinPath(),
|
|
47153
|
-
"docs",
|
|
47154
|
-
"serve",
|
|
47155
|
-
"--port",
|
|
47156
|
-
String(opts.startPort),
|
|
47157
|
-
"--end-port",
|
|
47158
|
-
String(opts.endPort),
|
|
47159
|
-
"--host",
|
|
47160
|
-
opts.host
|
|
47161
|
-
];
|
|
47162
|
-
if (opts.noAutoPort) args.push("--no-auto-port");
|
|
47163
|
-
const child = spawn(process.execPath, args, {
|
|
47164
|
-
detached: true,
|
|
47165
|
-
stdio,
|
|
47166
|
-
env: { ...process.env, [DETACHED_CHILD_ENV]: "1" },
|
|
47167
|
-
cwd: getProjectRoot37()
|
|
47168
|
-
});
|
|
47169
|
-
child.unref();
|
|
47170
|
-
if (handle) await handle.close();
|
|
47171
|
-
return child;
|
|
47172
|
-
}
|
|
47173
|
-
var DETACHED_CHILD_ENV, serveCommand, openCommand, stopCommand4, viewerStatusCommand, runViewerStatus, viewerCommand, docsViewerSubcommands;
|
|
47266
|
+
var serveCommand, openCommand, stopCommand4, viewerStatusCommand, runViewerStatus, viewerCommand, docsViewerSubcommands;
|
|
47174
47267
|
var init_docs_viewer = __esm({
|
|
47175
47268
|
"packages/cleo/src/cli/commands/docs-viewer.ts"() {
|
|
47176
47269
|
"use strict";
|
|
47177
47270
|
init_src2();
|
|
47178
47271
|
init_dist();
|
|
47179
47272
|
init_pidfile();
|
|
47180
|
-
|
|
47273
|
+
init_docs_viewer_subsystem();
|
|
47181
47274
|
init_renderers();
|
|
47182
|
-
DETACHED_CHILD_ENV = "CLEO_VIEWER_DETACHED_CHILD";
|
|
47183
47275
|
serveCommand = defineCommand({
|
|
47184
47276
|
meta: {
|
|
47185
47277
|
name: "serve",
|
|
47186
|
-
description: "
|
|
47278
|
+
description: "Run docs viewer \u2014 prefer `cleo docs viewer start`"
|
|
47187
47279
|
},
|
|
47188
47280
|
args: {
|
|
47189
47281
|
port: {
|
|
47190
47282
|
type: "string",
|
|
47191
47283
|
description: "Starting port (default 7777)",
|
|
47192
|
-
default:
|
|
47284
|
+
default: String(VIEWER_DEFAULT_PORT)
|
|
47193
47285
|
},
|
|
47194
47286
|
"end-port": {
|
|
47195
47287
|
type: "string",
|
|
47196
47288
|
description: "Last port to try when auto-incrementing (default 7800)",
|
|
47197
|
-
default:
|
|
47289
|
+
default: String(VIEWER_DEFAULT_END_PORT)
|
|
47198
47290
|
},
|
|
47199
47291
|
host: {
|
|
47200
47292
|
type: "string",
|
|
47201
47293
|
description: "Bind host (default 127.0.0.1)",
|
|
47202
|
-
default:
|
|
47294
|
+
default: VIEWER_DEFAULT_HOST
|
|
47203
47295
|
},
|
|
47204
47296
|
"no-auto-port": {
|
|
47205
47297
|
type: "boolean",
|
|
47206
47298
|
description: "Disable auto-increment when start port is busy",
|
|
47207
47299
|
default: false
|
|
47208
|
-
},
|
|
47209
|
-
detach: {
|
|
47210
|
-
type: "boolean",
|
|
47211
|
-
description: "Run in background; write pid to viewer.pid; exit immediately",
|
|
47212
|
-
default: false
|
|
47213
47300
|
}
|
|
47214
47301
|
},
|
|
47215
47302
|
async run({ args }) {
|
|
@@ -47217,8 +47304,6 @@ var init_docs_viewer = __esm({
|
|
|
47217
47304
|
const endPort = Number.parseInt(String(args["end-port"]), 10);
|
|
47218
47305
|
const host = String(args.host);
|
|
47219
47306
|
const noAutoPort = Boolean(args["no-auto-port"]);
|
|
47220
|
-
const detach = Boolean(args.detach);
|
|
47221
|
-
const isDetachedChild = process.env[DETACHED_CHILD_ENV] === "1";
|
|
47222
47307
|
if (!Number.isFinite(startPort) || startPort < 1 || startPort > 65535) {
|
|
47223
47308
|
cliError(`invalid --port: ${args.port}`, 6 /* VALIDATION_ERROR */, { name: "E_VALIDATION" });
|
|
47224
47309
|
return;
|
|
@@ -47229,79 +47314,25 @@ var init_docs_viewer = __esm({
|
|
|
47229
47314
|
});
|
|
47230
47315
|
return;
|
|
47231
47316
|
}
|
|
47232
|
-
|
|
47233
|
-
const
|
|
47234
|
-
|
|
47235
|
-
|
|
47236
|
-
{
|
|
47237
|
-
running: true,
|
|
47238
|
-
pid: existing.pid,
|
|
47239
|
-
port: existing.port,
|
|
47240
|
-
host: existing.host,
|
|
47241
|
-
url: `http://${existing.host}:${existing.port}`,
|
|
47242
|
-
pidFile: viewerPidFilePath()
|
|
47243
|
-
},
|
|
47244
|
-
{
|
|
47245
|
-
command: "docs serve",
|
|
47246
|
-
operation: "docs.serve",
|
|
47247
|
-
message: `viewer already running on http://${existing.host}:${existing.port}`
|
|
47248
|
-
}
|
|
47249
|
-
);
|
|
47250
|
-
return;
|
|
47251
|
-
}
|
|
47252
|
-
const child = await spawnDetachedServer({ startPort, endPort, host, noAutoPort });
|
|
47253
|
-
if (!child.pid) {
|
|
47254
|
-
cliError("failed to spawn detached viewer process", 1 /* GENERAL_ERROR */, {
|
|
47255
|
-
name: "E_SPAWN_FAILED"
|
|
47256
|
-
});
|
|
47257
|
-
return;
|
|
47258
|
-
}
|
|
47259
|
-
let record2 = null;
|
|
47260
|
-
const deadline = Date.now() + 1e4;
|
|
47261
|
-
while (Date.now() < deadline) {
|
|
47262
|
-
await new Promise((r) => setTimeout(r, 150));
|
|
47263
|
-
record2 = await readViewerPidFile();
|
|
47264
|
-
if (record2 && record2.pid === child.pid) break;
|
|
47265
|
-
if (!isProcessAlive(child.pid)) {
|
|
47266
|
-
cliError(
|
|
47267
|
-
"detached viewer exited before binding (check ~/.local/share/cleo/viewer.log)",
|
|
47268
|
-
1 /* GENERAL_ERROR */,
|
|
47269
|
-
{ name: "E_VIEWER_EXITED" }
|
|
47270
|
-
);
|
|
47271
|
-
return;
|
|
47272
|
-
}
|
|
47273
|
-
}
|
|
47274
|
-
if (!record2 || record2.pid !== child.pid) {
|
|
47275
|
-
cliError("timed out waiting for detached viewer to bind", 1 /* GENERAL_ERROR */, {
|
|
47276
|
-
name: "E_VIEWER_TIMEOUT"
|
|
47277
|
-
});
|
|
47278
|
-
return;
|
|
47279
|
-
}
|
|
47317
|
+
try {
|
|
47318
|
+
const subsystem = createDocsViewerSubsystem({ startPort, endPort, host, noAutoPort });
|
|
47319
|
+
const ctx = await subsystem.start();
|
|
47320
|
+
const { pidFile } = getViewerPaths();
|
|
47280
47321
|
cliOutput(
|
|
47281
47322
|
{
|
|
47282
47323
|
running: true,
|
|
47283
|
-
pid:
|
|
47284
|
-
port:
|
|
47285
|
-
host:
|
|
47286
|
-
url: `http://${
|
|
47287
|
-
pidFile
|
|
47324
|
+
pid: ctx.pid,
|
|
47325
|
+
port: ctx.port,
|
|
47326
|
+
host: ctx.host,
|
|
47327
|
+
url: `http://${ctx.host}:${ctx.port}`,
|
|
47328
|
+
pidFile
|
|
47288
47329
|
},
|
|
47289
47330
|
{
|
|
47290
47331
|
command: "docs serve",
|
|
47291
47332
|
operation: "docs.serve",
|
|
47292
|
-
message: `viewer started on http://${
|
|
47333
|
+
message: `viewer started on http://${ctx.host}:${ctx.port}`
|
|
47293
47334
|
}
|
|
47294
47335
|
);
|
|
47295
|
-
return;
|
|
47296
|
-
}
|
|
47297
|
-
let handle;
|
|
47298
|
-
try {
|
|
47299
|
-
handle = await startViewer({
|
|
47300
|
-
startPort,
|
|
47301
|
-
endPort,
|
|
47302
|
-
host,
|
|
47303
|
-
autoIncrement: !noAutoPort
|
|
47304
|
-
});
|
|
47305
47336
|
} catch (err) {
|
|
47306
47337
|
const e = err;
|
|
47307
47338
|
if (e.code === "E_NO_PORT" || e.code === "EADDRINUSE") {
|
|
@@ -47312,49 +47343,12 @@ var init_docs_viewer = __esm({
|
|
|
47312
47343
|
}
|
|
47313
47344
|
throw err;
|
|
47314
47345
|
}
|
|
47315
|
-
const record = {
|
|
47316
|
-
pid: process.pid,
|
|
47317
|
-
port: handle.port,
|
|
47318
|
-
host: handle.host,
|
|
47319
|
-
projectRoot: getProjectRoot37(),
|
|
47320
|
-
startedAt: Date.now()
|
|
47321
|
-
};
|
|
47322
|
-
await writeViewerPidFile(record);
|
|
47323
|
-
const url = `http://${handle.host}:${handle.port}`;
|
|
47324
|
-
if (isDetachedChild) {
|
|
47325
|
-
} else {
|
|
47326
|
-
humanInfo(`viewer listening on ${url} (Ctrl+C to stop)`);
|
|
47327
|
-
cliOutput(
|
|
47328
|
-
{
|
|
47329
|
-
running: true,
|
|
47330
|
-
pid: record.pid,
|
|
47331
|
-
port: record.port,
|
|
47332
|
-
host: record.host,
|
|
47333
|
-
url,
|
|
47334
|
-
pidFile: viewerPidFilePath()
|
|
47335
|
-
},
|
|
47336
|
-
{
|
|
47337
|
-
command: "docs serve",
|
|
47338
|
-
operation: "docs.serve",
|
|
47339
|
-
message: `viewer running on ${url}`
|
|
47340
|
-
}
|
|
47341
|
-
);
|
|
47342
|
-
}
|
|
47343
|
-
const shutdown = async (signal) => {
|
|
47344
|
-
handle.server.close();
|
|
47345
|
-
await removeViewerPidFile();
|
|
47346
|
-
process.exit(signal === "SIGINT" ? 130 : 143);
|
|
47347
|
-
};
|
|
47348
|
-
process.on("SIGINT", () => void shutdown("SIGINT"));
|
|
47349
|
-
process.on("SIGTERM", () => void shutdown("SIGTERM"));
|
|
47350
|
-
await new Promise((res) => handle.server.on("close", res));
|
|
47351
|
-
await removeViewerPidFile();
|
|
47352
47346
|
}
|
|
47353
47347
|
});
|
|
47354
47348
|
openCommand = defineCommand({
|
|
47355
47349
|
meta: {
|
|
47356
47350
|
name: "open",
|
|
47357
|
-
description: "
|
|
47351
|
+
description: "Open docs viewer in browser \u2014 prefer `cleo docs viewer open`"
|
|
47358
47352
|
},
|
|
47359
47353
|
args: {
|
|
47360
47354
|
slug: {
|
|
@@ -47365,17 +47359,17 @@ var init_docs_viewer = __esm({
|
|
|
47365
47359
|
port: {
|
|
47366
47360
|
type: "string",
|
|
47367
47361
|
description: "Starting port for the viewer (default 7777)",
|
|
47368
|
-
default:
|
|
47362
|
+
default: String(VIEWER_DEFAULT_PORT)
|
|
47369
47363
|
},
|
|
47370
47364
|
"end-port": {
|
|
47371
47365
|
type: "string",
|
|
47372
47366
|
description: "Last port to try (default 7800)",
|
|
47373
|
-
default:
|
|
47367
|
+
default: String(VIEWER_DEFAULT_END_PORT)
|
|
47374
47368
|
},
|
|
47375
47369
|
host: {
|
|
47376
47370
|
type: "string",
|
|
47377
47371
|
description: "Bind host (default 127.0.0.1)",
|
|
47378
|
-
default:
|
|
47372
|
+
default: VIEWER_DEFAULT_HOST
|
|
47379
47373
|
},
|
|
47380
47374
|
"no-launch": {
|
|
47381
47375
|
type: "boolean",
|
|
@@ -47385,49 +47379,30 @@ var init_docs_viewer = __esm({
|
|
|
47385
47379
|
},
|
|
47386
47380
|
async run({ args }) {
|
|
47387
47381
|
const slug = args.slug ? String(args.slug) : void 0;
|
|
47388
|
-
let
|
|
47389
|
-
if (
|
|
47390
|
-
await removeViewerPidFile();
|
|
47391
|
-
record = null;
|
|
47392
|
-
}
|
|
47393
|
-
if (!record) {
|
|
47382
|
+
let status = await getViewerStatus();
|
|
47383
|
+
if (!status.running) {
|
|
47394
47384
|
const startPort = Number.parseInt(String(args.port), 10);
|
|
47395
47385
|
const endPort = Number.parseInt(String(args["end-port"]), 10);
|
|
47396
47386
|
const host = String(args.host);
|
|
47397
|
-
|
|
47398
|
-
startPort,
|
|
47399
|
-
|
|
47400
|
-
|
|
47401
|
-
|
|
47402
|
-
|
|
47403
|
-
|
|
47404
|
-
|
|
47405
|
-
name: "E_SPAWN_FAILED"
|
|
47406
|
-
});
|
|
47407
|
-
return;
|
|
47408
|
-
}
|
|
47409
|
-
const deadline = Date.now() + 1e4;
|
|
47410
|
-
while (Date.now() < deadline) {
|
|
47411
|
-
await new Promise((r) => setTimeout(r, 150));
|
|
47412
|
-
record = await readViewerPidFile();
|
|
47413
|
-
if (record && record.pid === child.pid) break;
|
|
47414
|
-
if (!isProcessAlive(child.pid)) {
|
|
47415
|
-
cliError(
|
|
47416
|
-
"detached viewer exited before binding (check ~/.local/share/cleo/viewer.log)",
|
|
47417
|
-
1 /* GENERAL_ERROR */,
|
|
47418
|
-
{ name: "E_VIEWER_EXITED" }
|
|
47419
|
-
);
|
|
47420
|
-
return;
|
|
47421
|
-
}
|
|
47422
|
-
}
|
|
47423
|
-
if (!record) {
|
|
47424
|
-
cliError("timed out waiting for viewer to bind", 1 /* GENERAL_ERROR */, {
|
|
47425
|
-
name: "E_VIEWER_TIMEOUT"
|
|
47387
|
+
try {
|
|
47388
|
+
const subsystem = createDocsViewerSubsystem({ startPort, endPort, host });
|
|
47389
|
+
await subsystem.start();
|
|
47390
|
+
status = await getViewerStatus();
|
|
47391
|
+
} catch (err) {
|
|
47392
|
+
const e = err;
|
|
47393
|
+
cliError(e.message ?? "failed to start docs viewer", 1 /* GENERAL_ERROR */, {
|
|
47394
|
+
name: "E_VIEWER_START_FAILED"
|
|
47426
47395
|
});
|
|
47427
47396
|
return;
|
|
47428
47397
|
}
|
|
47429
47398
|
}
|
|
47430
|
-
|
|
47399
|
+
if (!status.running || status.pid === null || status.port === null || status.host === null) {
|
|
47400
|
+
cliError("timed out waiting for viewer to bind", 1 /* GENERAL_ERROR */, {
|
|
47401
|
+
name: "E_VIEWER_TIMEOUT"
|
|
47402
|
+
});
|
|
47403
|
+
return;
|
|
47404
|
+
}
|
|
47405
|
+
const url = slug ? `http://${status.host}:${status.port}/docs/${encodeURIComponent(slug)}` : `http://${status.host}:${status.port}/`;
|
|
47431
47406
|
if (!args["no-launch"]) {
|
|
47432
47407
|
openInBrowser(url);
|
|
47433
47408
|
}
|
|
@@ -47435,9 +47410,9 @@ var init_docs_viewer = __esm({
|
|
|
47435
47410
|
{
|
|
47436
47411
|
opened: true,
|
|
47437
47412
|
slug: slug ?? null,
|
|
47438
|
-
pid:
|
|
47439
|
-
port:
|
|
47440
|
-
host:
|
|
47413
|
+
pid: status.pid,
|
|
47414
|
+
port: status.port,
|
|
47415
|
+
host: status.host,
|
|
47441
47416
|
url
|
|
47442
47417
|
},
|
|
47443
47418
|
{
|
|
@@ -47451,7 +47426,7 @@ var init_docs_viewer = __esm({
|
|
|
47451
47426
|
stopCommand4 = defineCommand({
|
|
47452
47427
|
meta: {
|
|
47453
47428
|
name: "stop",
|
|
47454
|
-
description: "
|
|
47429
|
+
description: "Stop the docs viewer \u2014 prefer `cleo docs viewer stop`"
|
|
47455
47430
|
},
|
|
47456
47431
|
args: {
|
|
47457
47432
|
timeout: {
|
|
@@ -47485,38 +47460,29 @@ var init_docs_viewer = __esm({
|
|
|
47485
47460
|
);
|
|
47486
47461
|
return;
|
|
47487
47462
|
}
|
|
47488
|
-
|
|
47489
|
-
|
|
47490
|
-
|
|
47491
|
-
|
|
47492
|
-
|
|
47493
|
-
|
|
47494
|
-
|
|
47495
|
-
|
|
47496
|
-
|
|
47497
|
-
|
|
47498
|
-
|
|
47499
|
-
}
|
|
47500
|
-
}
|
|
47463
|
+
const { pidFile } = getViewerPaths();
|
|
47464
|
+
const subsystem = createDocsViewerSubsystem({
|
|
47465
|
+
startPort: record.port,
|
|
47466
|
+
host: record.host
|
|
47467
|
+
});
|
|
47468
|
+
await subsystem.shutdown({
|
|
47469
|
+
pid: record.pid,
|
|
47470
|
+
pidFile,
|
|
47471
|
+
port: record.port,
|
|
47472
|
+
host: record.host
|
|
47473
|
+
});
|
|
47501
47474
|
const timeoutSec = Math.max(1, Number.parseInt(String(args.timeout), 10) || 10);
|
|
47502
|
-
const exited = await waitForExit(record.pid, timeoutSec * 1e3);
|
|
47503
|
-
if (!exited) {
|
|
47504
|
-
try {
|
|
47505
|
-
process.kill(record.pid, "SIGKILL");
|
|
47506
|
-
} catch {
|
|
47507
|
-
}
|
|
47508
|
-
}
|
|
47509
|
-
await removeViewerPidFile();
|
|
47510
47475
|
cliOutput(
|
|
47511
47476
|
{
|
|
47512
47477
|
stopped: true,
|
|
47513
47478
|
pid: record.pid,
|
|
47514
|
-
graceful:
|
|
47479
|
+
graceful: true,
|
|
47480
|
+
timeoutSec
|
|
47515
47481
|
},
|
|
47516
47482
|
{
|
|
47517
47483
|
command: "docs stop",
|
|
47518
47484
|
operation: "docs.stop",
|
|
47519
|
-
message:
|
|
47485
|
+
message: `viewer (pid ${record.pid}) stopped`
|
|
47520
47486
|
}
|
|
47521
47487
|
);
|
|
47522
47488
|
}
|
|
@@ -47524,15 +47490,15 @@ var init_docs_viewer = __esm({
|
|
|
47524
47490
|
viewerStatusCommand = defineCommand({
|
|
47525
47491
|
meta: {
|
|
47526
47492
|
name: "viewer-status",
|
|
47527
|
-
description: "
|
|
47493
|
+
description: "Report viewer state \u2014 prefer `cleo docs viewer status`"
|
|
47528
47494
|
},
|
|
47529
47495
|
async run() {
|
|
47530
47496
|
await runViewerStatus();
|
|
47531
47497
|
}
|
|
47532
47498
|
});
|
|
47533
47499
|
runViewerStatus = async () => {
|
|
47534
|
-
const
|
|
47535
|
-
if (!
|
|
47500
|
+
const status = await getViewerStatus();
|
|
47501
|
+
if (!status.running || status.pid === null) {
|
|
47536
47502
|
cliOutput(
|
|
47537
47503
|
{ running: false, pidFile: viewerPidFilePath() },
|
|
47538
47504
|
{
|
|
@@ -47543,40 +47509,19 @@ var init_docs_viewer = __esm({
|
|
|
47543
47509
|
);
|
|
47544
47510
|
return;
|
|
47545
47511
|
}
|
|
47546
|
-
const alive = isProcessAlive(record.pid);
|
|
47547
|
-
if (!alive) {
|
|
47548
|
-
await removeViewerPidFile();
|
|
47549
|
-
cliOutput(
|
|
47550
|
-
{
|
|
47551
|
-
running: false,
|
|
47552
|
-
reason: "stale pidfile",
|
|
47553
|
-
pid: record.pid,
|
|
47554
|
-
pidFile: viewerPidFilePath()
|
|
47555
|
-
},
|
|
47556
|
-
{
|
|
47557
|
-
command: "docs viewer-status",
|
|
47558
|
-
operation: "docs.viewer-status",
|
|
47559
|
-
message: `stale pidfile removed (pid ${record.pid} not alive)`
|
|
47560
|
-
}
|
|
47561
|
-
);
|
|
47562
|
-
return;
|
|
47563
|
-
}
|
|
47564
47512
|
cliOutput(
|
|
47565
47513
|
{
|
|
47566
47514
|
running: true,
|
|
47567
|
-
pid:
|
|
47568
|
-
port:
|
|
47569
|
-
host:
|
|
47570
|
-
|
|
47571
|
-
startedAt: record.startedAt,
|
|
47572
|
-
uptimeMs: Date.now() - record.startedAt,
|
|
47573
|
-
url: `http://${record.host}:${record.port}`,
|
|
47515
|
+
pid: status.pid,
|
|
47516
|
+
port: status.port,
|
|
47517
|
+
host: status.host,
|
|
47518
|
+
url: status.url,
|
|
47574
47519
|
pidFile: viewerPidFilePath()
|
|
47575
47520
|
},
|
|
47576
47521
|
{
|
|
47577
47522
|
command: "docs viewer-status",
|
|
47578
47523
|
operation: "docs.viewer-status",
|
|
47579
|
-
message: `viewer running (pid ${
|
|
47524
|
+
message: `viewer running (pid ${status.pid})`
|
|
47580
47525
|
}
|
|
47581
47526
|
);
|
|
47582
47527
|
};
|
|
@@ -47613,7 +47558,7 @@ __export(docs_exports, {
|
|
|
47613
47558
|
_llmOutputCommand: () => _llmOutputCommand,
|
|
47614
47559
|
docsCommand: () => docsCommand
|
|
47615
47560
|
});
|
|
47616
|
-
import { appendFile, mkdir as
|
|
47561
|
+
import { appendFile, mkdir as mkdir3, readdir, readFile as readFile4, writeFile as writeFile2 } from "node:fs/promises";
|
|
47617
47562
|
import { dirname as dirname8, isAbsolute as isAbsolute2, join as join21, resolve as resolve5 } from "node:path";
|
|
47618
47563
|
import { pushWarning as pushWarning3 } from "@cleocode/core";
|
|
47619
47564
|
import {
|
|
@@ -47624,7 +47569,7 @@ import {
|
|
|
47624
47569
|
DEFAULT_SIMILARITY_THRESHOLD,
|
|
47625
47570
|
detectStrayCleoDb as detectStrayCleoDb2,
|
|
47626
47571
|
getAgentOutputsAbsolute,
|
|
47627
|
-
getProjectRoot as
|
|
47572
|
+
getProjectRoot as getProjectRoot37,
|
|
47628
47573
|
readJson,
|
|
47629
47574
|
resolveWorktreeFilePath,
|
|
47630
47575
|
resolveWorktreeRouting as resolveWorktreeRouting4
|
|
@@ -47896,7 +47841,7 @@ var init_docs3 = __esm({
|
|
|
47896
47841
|
resolvedFile = resolveWorktreeFilePath(String(fileArg), routing);
|
|
47897
47842
|
}
|
|
47898
47843
|
if (args.slug && args.type) {
|
|
47899
|
-
const projectRoot = await
|
|
47844
|
+
const projectRoot = await getProjectRoot37();
|
|
47900
47845
|
let warnThreshold = DEFAULT_SIMILARITY_THRESHOLD;
|
|
47901
47846
|
let mode = DEFAULT_SIMILARITY_MODE;
|
|
47902
47847
|
try {
|
|
@@ -47955,7 +47900,7 @@ var init_docs3 = __esm({
|
|
|
47955
47900
|
})}
|
|
47956
47901
|
`;
|
|
47957
47902
|
try {
|
|
47958
|
-
await
|
|
47903
|
+
await mkdir3(join21(projectRoot, ".cleo", "audit"), { recursive: true });
|
|
47959
47904
|
await appendFile(
|
|
47960
47905
|
join21(projectRoot, ".cleo", "audit", "similar-bypass.jsonl"),
|
|
47961
47906
|
auditLine,
|
|
@@ -48276,7 +48221,7 @@ var init_docs3 = __esm({
|
|
|
48276
48221
|
const taskId = String(args.task);
|
|
48277
48222
|
const includeAttachments = args["include-attachments"] !== false;
|
|
48278
48223
|
const includeMemoryRefs = args["include-memory-refs"] === true;
|
|
48279
|
-
const projectRoot =
|
|
48224
|
+
const projectRoot = getProjectRoot37();
|
|
48280
48225
|
try {
|
|
48281
48226
|
const result = await dispatchDocsRaw("query", "llm-output", {
|
|
48282
48227
|
mode: "task-export",
|
|
@@ -48287,7 +48232,7 @@ var init_docs3 = __esm({
|
|
|
48287
48232
|
let writtenPath;
|
|
48288
48233
|
if (typeof args.out === "string" && args.out.length > 0) {
|
|
48289
48234
|
const outPath = isAbsolute2(args.out) ? args.out : resolve5(projectRoot, args.out);
|
|
48290
|
-
await
|
|
48235
|
+
await mkdir3(dirname8(outPath), { recursive: true });
|
|
48291
48236
|
await writeFile2(outPath, result.content, "utf8");
|
|
48292
48237
|
writtenPath = outPath;
|
|
48293
48238
|
}
|
|
@@ -48347,7 +48292,7 @@ var init_docs3 = __esm({
|
|
|
48347
48292
|
},
|
|
48348
48293
|
async run({ args }) {
|
|
48349
48294
|
const forId = String(args.for);
|
|
48350
|
-
const projectRoot =
|
|
48295
|
+
const projectRoot = getProjectRoot37();
|
|
48351
48296
|
try {
|
|
48352
48297
|
const result = await dispatchDocsRaw("query", "llm-output", {
|
|
48353
48298
|
for: forId,
|
|
@@ -48359,7 +48304,7 @@ var init_docs3 = __esm({
|
|
|
48359
48304
|
let writtenPath;
|
|
48360
48305
|
if (typeof args.out === "string" && args.out.length > 0) {
|
|
48361
48306
|
const outPath = isAbsolute2(args.out) ? args.out : resolve5(projectRoot, args.out);
|
|
48362
|
-
await
|
|
48307
|
+
await mkdir3(dirname8(outPath), { recursive: true });
|
|
48363
48308
|
await writeFile2(outPath, result.content, "utf8");
|
|
48364
48309
|
writtenPath = outPath;
|
|
48365
48310
|
}
|
|
@@ -48424,7 +48369,7 @@ var init_docs3 = __esm({
|
|
|
48424
48369
|
},
|
|
48425
48370
|
async run({ args }) {
|
|
48426
48371
|
const forId = String(args.for);
|
|
48427
|
-
const projectRoot =
|
|
48372
|
+
const projectRoot = getProjectRoot37();
|
|
48428
48373
|
try {
|
|
48429
48374
|
const result = await dispatchDocsRaw("query", "llm-output", {
|
|
48430
48375
|
for: forId,
|
|
@@ -48436,7 +48381,7 @@ var init_docs3 = __esm({
|
|
|
48436
48381
|
let writtenPath;
|
|
48437
48382
|
if (typeof args.out === "string" && args.out.length > 0) {
|
|
48438
48383
|
const outPath = isAbsolute2(args.out) ? args.out : resolve5(projectRoot, args.out);
|
|
48439
|
-
await
|
|
48384
|
+
await mkdir3(dirname8(outPath), { recursive: true });
|
|
48440
48385
|
await writeFile2(outPath, result.content, "utf8");
|
|
48441
48386
|
writtenPath = outPath;
|
|
48442
48387
|
}
|
|
@@ -48650,7 +48595,7 @@ var init_docs3 = __esm({
|
|
|
48650
48595
|
}
|
|
48651
48596
|
},
|
|
48652
48597
|
async run({ args }) {
|
|
48653
|
-
const projectRoot =
|
|
48598
|
+
const projectRoot = getProjectRoot37();
|
|
48654
48599
|
const rawStrategy = args.strategy ?? "three-way";
|
|
48655
48600
|
const strategy = rawStrategy === "cherry-pick" || rawStrategy === "multi-diff" ? rawStrategy : "three-way";
|
|
48656
48601
|
try {
|
|
@@ -48662,7 +48607,7 @@ var init_docs3 = __esm({
|
|
|
48662
48607
|
});
|
|
48663
48608
|
if (typeof args.out === "string" && args.out.length > 0) {
|
|
48664
48609
|
const outPath = isAbsolute2(args.out) ? args.out : resolve5(projectRoot, args.out);
|
|
48665
|
-
await
|
|
48610
|
+
await mkdir3(dirname8(outPath), { recursive: true });
|
|
48666
48611
|
await writeFile2(outPath, result.merged, "utf8");
|
|
48667
48612
|
humanInfo(`Wrote merged content to ${outPath}`);
|
|
48668
48613
|
}
|
|
@@ -49420,7 +49365,7 @@ var init_docs3 = __esm({
|
|
|
49420
49365
|
}
|
|
49421
49366
|
},
|
|
49422
49367
|
async run({ args }) {
|
|
49423
|
-
const projectRoot =
|
|
49368
|
+
const projectRoot = getProjectRoot37();
|
|
49424
49369
|
const dirArg = String(args.dir);
|
|
49425
49370
|
const scanRoot = isAbsolute2(dirArg) ? dirArg : resolve5(projectRoot, dirArg);
|
|
49426
49371
|
const dryRun = args["dry-run"] === true;
|
|
@@ -49434,7 +49379,7 @@ var init_docs3 = __esm({
|
|
|
49434
49379
|
})}
|
|
49435
49380
|
`;
|
|
49436
49381
|
try {
|
|
49437
|
-
await
|
|
49382
|
+
await mkdir3(join21(projectRoot, ".cleo", "audit"), { recursive: true });
|
|
49438
49383
|
await appendFile(
|
|
49439
49384
|
join21(projectRoot, ".cleo", "audit", "import-force-bypass.jsonl"),
|
|
49440
49385
|
auditLine,
|
|
@@ -49482,7 +49427,7 @@ var init_docs3 = __esm({
|
|
|
49482
49427
|
}
|
|
49483
49428
|
},
|
|
49484
49429
|
async run({ args }) {
|
|
49485
|
-
const projectRoot =
|
|
49430
|
+
const projectRoot = getProjectRoot37();
|
|
49486
49431
|
const { registry, configError } = loadCliRegistry(projectRoot);
|
|
49487
49432
|
const kinds = registry.list().map(toWireKind);
|
|
49488
49433
|
const extensionsCount = kinds.filter((k) => k.isExtension).length;
|
|
@@ -49537,7 +49482,7 @@ var init_docs3 = __esm({
|
|
|
49537
49482
|
deprecated: "docs list-types",
|
|
49538
49483
|
replacement: "docs schema"
|
|
49539
49484
|
});
|
|
49540
|
-
const projectRoot =
|
|
49485
|
+
const projectRoot = getProjectRoot37();
|
|
49541
49486
|
const { registry, configError } = loadCliRegistry(projectRoot);
|
|
49542
49487
|
const kinds = registry.list().map(toWireKind);
|
|
49543
49488
|
const extensionsCount = kinds.filter((k) => k.isExtension).length;
|
|
@@ -49631,7 +49576,7 @@ var doctor_db_substrate_exports = {};
|
|
|
49631
49576
|
__export(doctor_db_substrate_exports, {
|
|
49632
49577
|
doctorDbSubstrateCommand: () => doctorDbSubstrateCommand
|
|
49633
49578
|
});
|
|
49634
|
-
import { getProjectRoot as
|
|
49579
|
+
import { getProjectRoot as getProjectRoot38, pushWarning as pushWarning4 } from "@cleocode/core";
|
|
49635
49580
|
import { surveyDbSubstrate, surveyFleetDbSubstrate } from "@cleocode/core/doctor/db-substrate.js";
|
|
49636
49581
|
function pushSubstrateWarnings(result) {
|
|
49637
49582
|
for (const warning of result.warnings) {
|
|
@@ -49764,7 +49709,7 @@ var init_doctor_db_substrate = __esm({
|
|
|
49764
49709
|
const result = isFleet ? surveyFleetDbSubstrate(
|
|
49765
49710
|
typeof args["fleet-root"] === "string" && args["fleet-root"].length > 0 ? args["fleet-root"] : DEFAULT_FLEET_ROOT,
|
|
49766
49711
|
options
|
|
49767
|
-
) : surveyDbSubstrate(
|
|
49712
|
+
) : surveyDbSubstrate(getProjectRoot38(), options);
|
|
49768
49713
|
pushSubstrateWarnings(result);
|
|
49769
49714
|
pushPerDbWarnings(result);
|
|
49770
49715
|
cliOutput(result, {
|
|
@@ -49784,7 +49729,7 @@ var doctor_legacy_backups_exports = {};
|
|
|
49784
49729
|
__export(doctor_legacy_backups_exports, {
|
|
49785
49730
|
doctorLegacyBackupsCommand: () => doctorLegacyBackupsCommand
|
|
49786
49731
|
});
|
|
49787
|
-
import { getProjectRoot as
|
|
49732
|
+
import { getProjectRoot as getProjectRoot39 } from "@cleocode/core";
|
|
49788
49733
|
import { pruneLegacyBackups, scanLegacyBackups } from "@cleocode/core/doctor/legacy-backups.js";
|
|
49789
49734
|
function parsePositiveInt(raw, fallback) {
|
|
49790
49735
|
if (raw === void 0 || raw === null) return fallback;
|
|
@@ -49828,7 +49773,7 @@ var init_doctor_legacy_backups = __esm({
|
|
|
49828
49773
|
async run({ args }) {
|
|
49829
49774
|
const softRetentionDays = parsePositiveInt(args["soft-retention-days"], 30);
|
|
49830
49775
|
const hardRetentionDays = parsePositiveInt(args["hard-retention-days"], 90);
|
|
49831
|
-
const projectRoot =
|
|
49776
|
+
const projectRoot = getProjectRoot39();
|
|
49832
49777
|
let result;
|
|
49833
49778
|
if (args.prune === true) {
|
|
49834
49779
|
const dryRun = args["dry-run"] !== false;
|
|
@@ -50395,7 +50340,7 @@ __export(migrate_agents_v2_exports, {
|
|
|
50395
50340
|
import { createHash as createHash2 } from "node:crypto";
|
|
50396
50341
|
import { appendFileSync as appendFileSync2, existsSync as existsSync14, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync13 } from "node:fs";
|
|
50397
50342
|
import { join as join23 } from "node:path";
|
|
50398
|
-
import { getProjectRoot as
|
|
50343
|
+
import { getProjectRoot as getProjectRoot40, installAgentFromCant } from "@cleocode/core/internal";
|
|
50399
50344
|
import { openCleoDb as openCleoDb2 } from "@cleocode/core/store/open-cleo-db";
|
|
50400
50345
|
function sha256Hex(bytes) {
|
|
50401
50346
|
return createHash2("sha256").update(bytes).digest("hex");
|
|
@@ -50582,7 +50527,7 @@ var init_migrate_agents_v2 = __esm({
|
|
|
50582
50527
|
}
|
|
50583
50528
|
},
|
|
50584
50529
|
async run({ args }) {
|
|
50585
|
-
const projectRoot =
|
|
50530
|
+
const projectRoot = getProjectRoot40();
|
|
50586
50531
|
const verbose = args.quiet !== true;
|
|
50587
50532
|
if (verbose) {
|
|
50588
50533
|
humanInfo("Scanning .cleo/cant/agents/ and .cleo/agents/ for unregistered agents...");
|
|
@@ -50626,7 +50571,7 @@ __export(doctor_exports, {
|
|
|
50626
50571
|
});
|
|
50627
50572
|
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
50628
50573
|
import { join as join24 } from "node:path";
|
|
50629
|
-
import { getProjectRoot as
|
|
50574
|
+
import { getProjectRoot as getProjectRoot41, pushWarning as pushWarning5 } from "@cleocode/core";
|
|
50630
50575
|
import { renderInvariantAuditLines } from "@cleocode/core/doctor/invariant-audit-render.js";
|
|
50631
50576
|
import {
|
|
50632
50577
|
quarantineRogueCleoDir,
|
|
@@ -50899,9 +50844,18 @@ var init_doctor = __esm({
|
|
|
50899
50844
|
type: "boolean",
|
|
50900
50845
|
description: "Migrate <root>/.cleo/worktree-include (legacy) \u2192 <root>/.worktreeinclude (canonical, T9983). Combine with --dry-run to preview."
|
|
50901
50846
|
},
|
|
50847
|
+
/**
|
|
50848
|
+
* T11489 — DHQ-037/019: detect and auto-heal a leaked `core.worktree` key
|
|
50849
|
+
* in the shared `.git/config`. Reports E_WT_CONFIG_LEAK when found; heals
|
|
50850
|
+
* automatically unless `--dry-run` is passed.
|
|
50851
|
+
*/
|
|
50852
|
+
"check-worktree-config": {
|
|
50853
|
+
type: "boolean",
|
|
50854
|
+
description: "Detect and auto-heal a leaked core.worktree key in .git/config (T11489 / DHQ-037). Combine with --dry-run to report without healing."
|
|
50855
|
+
},
|
|
50902
50856
|
"dry-run": {
|
|
50903
50857
|
type: "boolean",
|
|
50904
|
-
description: "With --quarantine-rogue-cleo-dirs
|
|
50858
|
+
description: "With --quarantine-rogue-cleo-dirs, --scan-stray-nexus-dbs, or --check-worktree-config: print what would be done without acting"
|
|
50905
50859
|
},
|
|
50906
50860
|
/**
|
|
50907
50861
|
* Show brain.db health dashboard (T1908 / BBTT-W2-4).
|
|
@@ -50951,9 +50905,64 @@ var init_doctor = __esm({
|
|
|
50951
50905
|
const progress = createDoctorProgress(isHuman);
|
|
50952
50906
|
progress.start();
|
|
50953
50907
|
try {
|
|
50908
|
+
if (args["check-worktree-config"]) {
|
|
50909
|
+
const { execFileSync: execFile2 } = await import("node:child_process");
|
|
50910
|
+
const { join: pathJoin } = await import("node:path");
|
|
50911
|
+
const { existsSync: existsSync21 } = await import("node:fs");
|
|
50912
|
+
const { detectAndHealCoreWorktreeLeak } = await import("@cleocode/worktree");
|
|
50913
|
+
const projectRoot = getProjectRoot41();
|
|
50914
|
+
let gitRoot = projectRoot;
|
|
50915
|
+
try {
|
|
50916
|
+
gitRoot = execFile2("git", ["rev-parse", "--show-toplevel"], {
|
|
50917
|
+
cwd: projectRoot,
|
|
50918
|
+
encoding: "utf-8",
|
|
50919
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
50920
|
+
}).trim();
|
|
50921
|
+
} catch {
|
|
50922
|
+
}
|
|
50923
|
+
const isDryRun = args["dry-run"] === true;
|
|
50924
|
+
progress.step(0, "Checking for leaked core.worktree in .git/config");
|
|
50925
|
+
if (isDryRun) {
|
|
50926
|
+
const gitConfigPath = pathJoin(gitRoot, ".git", "config");
|
|
50927
|
+
let leakedValue;
|
|
50928
|
+
if (existsSync21(gitConfigPath)) {
|
|
50929
|
+
try {
|
|
50930
|
+
leakedValue = execFile2("git", ["config", "--file", gitConfigPath, "--get", "core.worktree"], {
|
|
50931
|
+
encoding: "utf-8",
|
|
50932
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
50933
|
+
}).trim() || void 0;
|
|
50934
|
+
} catch {
|
|
50935
|
+
}
|
|
50936
|
+
}
|
|
50937
|
+
const report = {
|
|
50938
|
+
gitRoot,
|
|
50939
|
+
gitConfigPath,
|
|
50940
|
+
leakDetected: !!leakedValue,
|
|
50941
|
+
leakedValue,
|
|
50942
|
+
healed: false,
|
|
50943
|
+
dryRun: true,
|
|
50944
|
+
message: leakedValue ? `DRY-RUN: core.worktree="${leakedValue}" found \u2014 would unset` : "No core.worktree leak detected"
|
|
50945
|
+
};
|
|
50946
|
+
progress.complete(report.message);
|
|
50947
|
+
cliOutput(report, { command: "doctor", operation: "doctor.check-worktree-config" });
|
|
50948
|
+
if (leakedValue) process.exitCode = 2;
|
|
50949
|
+
} else {
|
|
50950
|
+
const result = detectAndHealCoreWorktreeLeak(gitRoot);
|
|
50951
|
+
const report = {
|
|
50952
|
+
gitRoot,
|
|
50953
|
+
...result,
|
|
50954
|
+
dryRun: false,
|
|
50955
|
+
message: result.leakDetected ? result.healed ? `E_WT_CONFIG_LEAK healed: removed core.worktree="${result.leakedValue}"` : `E_WT_CONFIG_LEAK detected but heal FAILED: ${result.healError}` : "No core.worktree leak detected"
|
|
50956
|
+
};
|
|
50957
|
+
progress.complete(report.message);
|
|
50958
|
+
cliOutput(report, { command: "doctor", operation: "doctor.check-worktree-config" });
|
|
50959
|
+
if (result.leakDetected && !result.healed) process.exitCode = 1;
|
|
50960
|
+
}
|
|
50961
|
+
return;
|
|
50962
|
+
}
|
|
50954
50963
|
if (args.brain) {
|
|
50955
50964
|
const { computeBrainHealthDashboard } = await import("@cleocode/core/memory/brain-health-dashboard.js");
|
|
50956
|
-
const projectRoot =
|
|
50965
|
+
const projectRoot = getProjectRoot41();
|
|
50957
50966
|
const dashboard = await computeBrainHealthDashboard(projectRoot);
|
|
50958
50967
|
cliOutput(dashboard, { command: "doctor", operation: "doctor.brain" });
|
|
50959
50968
|
if (dashboard.hasP0Failure) {
|
|
@@ -50962,7 +50971,7 @@ var init_doctor = __esm({
|
|
|
50962
50971
|
return;
|
|
50963
50972
|
}
|
|
50964
50973
|
if (args["scan-test-fixtures-in-prod"]) {
|
|
50965
|
-
const projectRoot =
|
|
50974
|
+
const projectRoot = getProjectRoot41();
|
|
50966
50975
|
const matches = await scanTestFixturesInProd(projectRoot);
|
|
50967
50976
|
const dryRun = args["dry-run"] !== false && args.quarantine !== true;
|
|
50968
50977
|
const quarantined = !dryRun && matches.length > 0 ? await quarantineTestFixtures(projectRoot, matches) : void 0;
|
|
@@ -51050,7 +51059,7 @@ var init_doctor = __esm({
|
|
|
51050
51059
|
progress.complete("Comprehensive diagnostics complete");
|
|
51051
51060
|
} else if (args["scan-rogue-cleo-dirs"]) {
|
|
51052
51061
|
progress.step(0, "Scanning for rogue .cleo/ directories");
|
|
51053
|
-
const projectRoot =
|
|
51062
|
+
const projectRoot = getProjectRoot41();
|
|
51054
51063
|
const reports = scanRogueCleoDirs(projectRoot);
|
|
51055
51064
|
progress.complete(
|
|
51056
51065
|
`Found ${reports.length} rogue .cleo/ director${reports.length === 1 ? "y" : "ies"}`
|
|
@@ -51059,7 +51068,7 @@ var init_doctor = __esm({
|
|
|
51059
51068
|
} else if (args["quarantine-rogue-cleo-dirs"]) {
|
|
51060
51069
|
const isDryRun = args["dry-run"] === true;
|
|
51061
51070
|
progress.step(0, `${isDryRun ? "[DRY RUN] " : ""}Scanning for rogue .cleo/ directories`);
|
|
51062
|
-
const projectRoot =
|
|
51071
|
+
const projectRoot = getProjectRoot41();
|
|
51063
51072
|
const reports = scanRogueCleoDirs(projectRoot);
|
|
51064
51073
|
if (reports.length === 0) {
|
|
51065
51074
|
progress.complete("No rogue .cleo/ directories found \u2014 nothing to quarantine");
|
|
@@ -51113,7 +51122,7 @@ var init_doctor = __esm({
|
|
|
51113
51122
|
const { detectAndRemoveLegacyGlobalFiles, detectAndRemoveStrayProjectNexus } = await import("@cleocode/core/store/cleanup-legacy.js");
|
|
51114
51123
|
const { getCleoHome: getCleoHome6 } = await import("@cleocode/core");
|
|
51115
51124
|
const cleoHome = getCleoHome6();
|
|
51116
|
-
const projectRoot =
|
|
51125
|
+
const projectRoot = getProjectRoot41();
|
|
51117
51126
|
const legacyResult = detectAndRemoveLegacyGlobalFiles(cleoHome);
|
|
51118
51127
|
const strayResult = detectAndRemoveStrayProjectNexus(projectRoot);
|
|
51119
51128
|
const isDryRun = args["dry-run"] === true;
|
|
@@ -51146,7 +51155,7 @@ var init_doctor = __esm({
|
|
|
51146
51155
|
} else if (args["audit-worktree-orphans"]) {
|
|
51147
51156
|
progress.step(0, "Comprehensive worktree anomaly audit (T9808 / council D009)");
|
|
51148
51157
|
const { auditWorktreeOrphansComprehensive, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
|
|
51149
|
-
const projectRoot =
|
|
51158
|
+
const projectRoot = getProjectRoot41();
|
|
51150
51159
|
const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
|
|
51151
51160
|
const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
|
|
51152
51161
|
const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
|
|
@@ -51203,7 +51212,7 @@ var init_doctor = __esm({
|
|
|
51203
51212
|
`${isDryRun ? "[DRY RUN] " : ""}Scanning + pruning worktree-orphan .cleo/ directories`
|
|
51204
51213
|
);
|
|
51205
51214
|
const { pruneWorktreeOrphans, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
|
|
51206
|
-
const projectRoot =
|
|
51215
|
+
const projectRoot = getProjectRoot41();
|
|
51207
51216
|
const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
|
|
51208
51217
|
const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
|
|
51209
51218
|
const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
|
|
@@ -51282,7 +51291,7 @@ var init_doctor = __esm({
|
|
|
51282
51291
|
`${isDryRun ? "[DRY RUN] " : ""}Migrating .cleo/worktree-include \u2192 .worktreeinclude`
|
|
51283
51292
|
);
|
|
51284
51293
|
const { migrateWorktreeIncludeFile } = await import("@cleocode/core");
|
|
51285
|
-
const projectRoot =
|
|
51294
|
+
const projectRoot = getProjectRoot41();
|
|
51286
51295
|
const result = await migrateWorktreeIncludeFile(projectRoot, { dryRun: isDryRun });
|
|
51287
51296
|
progress.complete(`Migration ${result.action}`);
|
|
51288
51297
|
cliOutput(result, { command: "doctor", operation: "doctor.migrate-worktree-include" });
|
|
@@ -51301,7 +51310,7 @@ var init_doctor = __esm({
|
|
|
51301
51310
|
const stepLabel = isFocusedAlias ? "Auditing Saga hierarchy for ADR-073 invariants" : "Walking central INVARIANTS_REGISTRY";
|
|
51302
51311
|
progress.step(0, stepLabel);
|
|
51303
51312
|
const { auditInvariantRegistry } = await import("@cleocode/core/doctor/invariant-audit.js");
|
|
51304
|
-
const projectRoot =
|
|
51313
|
+
const projectRoot = getProjectRoot41();
|
|
51305
51314
|
const result = await auditInvariantRegistry(projectRoot, { adrFilter });
|
|
51306
51315
|
const operation = isFocusedAlias ? "doctor.audit-sagas" : "doctor.audit-invariants";
|
|
51307
51316
|
const summary = `Invariant audit complete \u2014 ${result.totalCount} entries walked, ${result.errorCount} error / ${result.warningCount} warning / ${result.infoCount} info violation(s), ${result.notApplicableCount} not-applicable, ${result.documentedCount} documented`;
|
|
@@ -51323,7 +51332,7 @@ var init_doctor = __esm({
|
|
|
51323
51332
|
{ command: "doctor", operation: "admin.health" }
|
|
51324
51333
|
);
|
|
51325
51334
|
try {
|
|
51326
|
-
const projectRoot =
|
|
51335
|
+
const projectRoot = getProjectRoot41();
|
|
51327
51336
|
const conflicts = readMigrationConflicts(projectRoot);
|
|
51328
51337
|
if (conflicts.length > 0) {
|
|
51329
51338
|
progress.complete(
|
|
@@ -51354,7 +51363,7 @@ var init_doctor = __esm({
|
|
|
51354
51363
|
progress.complete("Health check complete");
|
|
51355
51364
|
}
|
|
51356
51365
|
try {
|
|
51357
|
-
const projectRoot =
|
|
51366
|
+
const projectRoot = getProjectRoot41();
|
|
51358
51367
|
const { auditSagaHierarchy } = await import("@cleocode/core/doctor/saga-audit.js");
|
|
51359
51368
|
const sagaAudit = await auditSagaHierarchy(projectRoot);
|
|
51360
51369
|
if (sagaAudit.sagas.length === 0) {
|
|
@@ -52522,6 +52531,48 @@ var init_gc = __esm({
|
|
|
52522
52531
|
}
|
|
52523
52532
|
});
|
|
52524
52533
|
|
|
52534
|
+
// packages/cleo/src/cli/commands/go.ts
|
|
52535
|
+
var go_exports = {};
|
|
52536
|
+
__export(go_exports, {
|
|
52537
|
+
goCommand: () => goCommand
|
|
52538
|
+
});
|
|
52539
|
+
import { getProjectRoot as getProjectRoot42, go } from "@cleocode/core";
|
|
52540
|
+
var goCommand;
|
|
52541
|
+
var init_go = __esm({
|
|
52542
|
+
"packages/cleo/src/cli/commands/go.ts"() {
|
|
52543
|
+
"use strict";
|
|
52544
|
+
init_define_cli_command();
|
|
52545
|
+
init_renderers();
|
|
52546
|
+
goCommand = defineCommand({
|
|
52547
|
+
meta: {
|
|
52548
|
+
name: "go",
|
|
52549
|
+
description: "SG-AUTOPILOT: run one turn of briefing\u2192sagaNext\u2192ready\u2192stage-branch\u2192ivtr loop"
|
|
52550
|
+
},
|
|
52551
|
+
args: {
|
|
52552
|
+
saga: {
|
|
52553
|
+
type: "string",
|
|
52554
|
+
description: "Optional saga task ID to scope the autopilot run (default: auto-select)",
|
|
52555
|
+
required: false
|
|
52556
|
+
},
|
|
52557
|
+
headless: {
|
|
52558
|
+
type: "boolean",
|
|
52559
|
+
description: "Suppress interactive annotations; suitable for daemon / unattended use",
|
|
52560
|
+
required: false
|
|
52561
|
+
}
|
|
52562
|
+
},
|
|
52563
|
+
async run({ args }) {
|
|
52564
|
+
const projectRoot = getProjectRoot42();
|
|
52565
|
+
const result = await go.cleoGo({
|
|
52566
|
+
sagaId: typeof args.saga === "string" && args.saga.length > 0 ? args.saga : void 0,
|
|
52567
|
+
headless: args.headless === true,
|
|
52568
|
+
projectRoot
|
|
52569
|
+
});
|
|
52570
|
+
cliOutput(result.success ? result.data : result, { command: "go", operation: "go.run" });
|
|
52571
|
+
}
|
|
52572
|
+
});
|
|
52573
|
+
}
|
|
52574
|
+
});
|
|
52575
|
+
|
|
52525
52576
|
// packages/cleo/src/cli/commands/goal.ts
|
|
52526
52577
|
var goal_exports = {};
|
|
52527
52578
|
__export(goal_exports, {
|
|
@@ -52541,7 +52592,7 @@ function resolveTurnBudget(turns) {
|
|
|
52541
52592
|
const n = typeof turns === "string" ? Number.parseInt(turns, 10) : Number(turns);
|
|
52542
52593
|
return Number.isInteger(n) && n > 0 ? n : DEFAULT_TURN_BUDGET;
|
|
52543
52594
|
}
|
|
52544
|
-
var DEFAULT_TURN_BUDGET, setCommand, statusCommand9, subgoalCommand, appendCommand, goalCommand;
|
|
52595
|
+
var DEFAULT_TURN_BUDGET, setCommand, statusCommand9, subgoalCommand, advanceCommand2, appendCommand, goalCommand;
|
|
52545
52596
|
var init_goal2 = __esm({
|
|
52546
52597
|
"packages/cleo/src/cli/commands/goal.ts"() {
|
|
52547
52598
|
"use strict";
|
|
@@ -52636,6 +52687,34 @@ var init_goal2 = __esm({
|
|
|
52636
52687
|
cliOutput(record, { command: "goal subgoal", operation: "goal.subgoal" });
|
|
52637
52688
|
}
|
|
52638
52689
|
});
|
|
52690
|
+
advanceCommand2 = defineCommand({
|
|
52691
|
+
meta: {
|
|
52692
|
+
name: "advance",
|
|
52693
|
+
description: "Advance a goal one turn (load \u2192 judge \u2192 persist \u2192 continuation). Entry point for the Stop-hook loop."
|
|
52694
|
+
},
|
|
52695
|
+
args: {
|
|
52696
|
+
goalId: {
|
|
52697
|
+
type: "positional",
|
|
52698
|
+
description: "The goal id (idempotency key) to advance"
|
|
52699
|
+
}
|
|
52700
|
+
},
|
|
52701
|
+
async run({ args }) {
|
|
52702
|
+
const goalId = String(args.goalId ?? "").trim();
|
|
52703
|
+
if (goalId.length === 0) {
|
|
52704
|
+
cliError("goal advance requires a <goalId>", 6 /* VALIDATION_ERROR */, {
|
|
52705
|
+
name: "E_VALIDATION"
|
|
52706
|
+
});
|
|
52707
|
+
return;
|
|
52708
|
+
}
|
|
52709
|
+
const cwd = getProjectRoot43();
|
|
52710
|
+
const result = await goal.advanceGoalWithPersist(goalId, { cwd });
|
|
52711
|
+
if (!result) {
|
|
52712
|
+
cliError(`Goal '${goalId}' not found.`, 4 /* NOT_FOUND */, { name: "E_NOT_FOUND" });
|
|
52713
|
+
return;
|
|
52714
|
+
}
|
|
52715
|
+
cliOutput(result, { command: "goal advance", operation: "goal.advance" });
|
|
52716
|
+
}
|
|
52717
|
+
});
|
|
52639
52718
|
appendCommand = defineCommand({
|
|
52640
52719
|
meta: {
|
|
52641
52720
|
name: "append",
|
|
@@ -52671,11 +52750,12 @@ var init_goal2 = __esm({
|
|
|
52671
52750
|
goalCommand = defineCommand({
|
|
52672
52751
|
meta: {
|
|
52673
52752
|
name: "goal",
|
|
52674
|
-
description: "DB-persisted, per-agent, evidence-gate-aware goal loop (set/status/subgoal/append)."
|
|
52753
|
+
description: "DB-persisted, per-agent, evidence-gate-aware goal loop (set/status/advance/subgoal/append)."
|
|
52675
52754
|
},
|
|
52676
52755
|
subCommands: {
|
|
52677
52756
|
set: setCommand,
|
|
52678
52757
|
status: statusCommand9,
|
|
52758
|
+
advance: advanceCommand2,
|
|
52679
52759
|
subgoal: subgoalCommand,
|
|
52680
52760
|
append: appendCommand
|
|
52681
52761
|
},
|
|
@@ -53842,7 +53922,7 @@ __export(init_exports, {
|
|
|
53842
53922
|
});
|
|
53843
53923
|
import { existsSync as existsSync15, readFileSync as readFileSync14 } from "node:fs";
|
|
53844
53924
|
import { join as join27 } from "node:path";
|
|
53845
|
-
import { fileURLToPath as
|
|
53925
|
+
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
53846
53926
|
import {
|
|
53847
53927
|
CleoError as CleoError5,
|
|
53848
53928
|
getWorkflowTemplatesDir as getCoreWorkflowTemplatesDir,
|
|
@@ -53853,7 +53933,7 @@ import {
|
|
|
53853
53933
|
import { getTemplatesByKind } from "@cleocode/core/templates/registry";
|
|
53854
53934
|
function getGitignoreTemplate() {
|
|
53855
53935
|
try {
|
|
53856
|
-
const thisFile =
|
|
53936
|
+
const thisFile = fileURLToPath5(import.meta.url);
|
|
53857
53937
|
const packageRoot = join27(thisFile, "..", "..", "..", "..");
|
|
53858
53938
|
const localTemplatePath = join27(packageRoot, "templates", "cleo-gitignore");
|
|
53859
53939
|
const monorepoTemplatePath = join27(packageRoot, "..", "..", "templates", "cleo-gitignore");
|
|
@@ -58481,7 +58561,7 @@ var nexus_exports = {};
|
|
|
58481
58561
|
__export(nexus_exports, {
|
|
58482
58562
|
nexusCommand: () => nexusCommand
|
|
58483
58563
|
});
|
|
58484
|
-
import { appendFile as appendFile2, mkdir as
|
|
58564
|
+
import { appendFile as appendFile2, mkdir as mkdir4 } from "node:fs/promises";
|
|
58485
58565
|
import { homedir as homedir5 } from "node:os";
|
|
58486
58566
|
import path4 from "node:path";
|
|
58487
58567
|
import { getProjectRoot as getProjectRoot48 } from "@cleocode/core";
|
|
@@ -58493,7 +58573,7 @@ async function appendDeprecationTelemetry(op, replacement) {
|
|
|
58493
58573
|
try {
|
|
58494
58574
|
const dateStr = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
58495
58575
|
const dir = path4.join(homedir5(), ".local", "state", "cleo", "nexus-deprecation");
|
|
58496
|
-
await
|
|
58576
|
+
await mkdir4(dir, { recursive: true });
|
|
58497
58577
|
const record = JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), op, replacement }) + "\n";
|
|
58498
58578
|
await appendFile2(path4.join(dir, `${dateStr}.jsonl`), record, "utf8");
|
|
58499
58579
|
} catch {
|
|
@@ -62168,7 +62248,7 @@ var phase_exports = {};
|
|
|
62168
62248
|
__export(phase_exports, {
|
|
62169
62249
|
phaseCommand: () => phaseCommand
|
|
62170
62250
|
});
|
|
62171
|
-
var showCommand10, listCommand15, setCommand2, startCommand6, completeCommand3,
|
|
62251
|
+
var showCommand10, listCommand15, setCommand2, startCommand6, completeCommand3, advanceCommand3, renameCommand, deleteCommand2, phaseCommand;
|
|
62172
62252
|
var init_phase = __esm({
|
|
62173
62253
|
"packages/cleo/src/cli/commands/phase.ts"() {
|
|
62174
62254
|
"use strict";
|
|
@@ -62268,7 +62348,7 @@ var init_phase = __esm({
|
|
|
62268
62348
|
);
|
|
62269
62349
|
}
|
|
62270
62350
|
});
|
|
62271
|
-
|
|
62351
|
+
advanceCommand3 = defineCommand({
|
|
62272
62352
|
meta: { name: "advance", description: "Complete current phase and start next" },
|
|
62273
62353
|
args: {
|
|
62274
62354
|
force: {
|
|
@@ -62350,7 +62430,7 @@ var init_phase = __esm({
|
|
|
62350
62430
|
set: setCommand2,
|
|
62351
62431
|
start: startCommand6,
|
|
62352
62432
|
complete: completeCommand3,
|
|
62353
|
-
advance:
|
|
62433
|
+
advance: advanceCommand3,
|
|
62354
62434
|
rename: renameCommand,
|
|
62355
62435
|
delete: deleteCommand2
|
|
62356
62436
|
},
|
|
@@ -65609,7 +65689,7 @@ __export(saga_exports, {
|
|
|
65609
65689
|
sagaCommand: () => sagaCommand
|
|
65610
65690
|
});
|
|
65611
65691
|
import { parseAcceptanceCriteria } from "@cleocode/core";
|
|
65612
|
-
var createCommand3, addCommand12, detachCommand2, listCommand22, membersCommand, repairCommand, reconcileCommand5, rollupCommand2, sagaCommand;
|
|
65692
|
+
var createCommand3, addCommand12, detachCommand2, listCommand22, membersCommand, repairCommand, reconcileCommand5, rollupCommand2, nextCommand3, sagaCommand;
|
|
65613
65693
|
var init_saga = __esm({
|
|
65614
65694
|
"packages/cleo/src/cli/commands/saga.ts"() {
|
|
65615
65695
|
"use strict";
|
|
@@ -65820,6 +65900,26 @@ var init_saga = __esm({
|
|
|
65820
65900
|
cliOutput(response.data ?? {}, { command: "saga", operation: "tasks.saga.rollup" });
|
|
65821
65901
|
}
|
|
65822
65902
|
});
|
|
65903
|
+
nextCommand3 = defineCommand({
|
|
65904
|
+
meta: {
|
|
65905
|
+
name: "next",
|
|
65906
|
+
description: "Return the next actionable Saga and its ready-frontier task IDs"
|
|
65907
|
+
},
|
|
65908
|
+
args: {
|
|
65909
|
+
sagaId: {
|
|
65910
|
+
type: "positional",
|
|
65911
|
+
description: "Optional saga task ID. Omit to auto-select from canonical order.",
|
|
65912
|
+
required: false
|
|
65913
|
+
}
|
|
65914
|
+
},
|
|
65915
|
+
async run({ args }) {
|
|
65916
|
+
const { sagas: sagas2, getProjectRoot: getProjectRoot57 } = await import("@cleocode/core");
|
|
65917
|
+
const projectRoot = getProjectRoot57();
|
|
65918
|
+
const sagaId = typeof args.sagaId === "string" && args.sagaId.length > 0 ? args.sagaId : void 0;
|
|
65919
|
+
const result = await sagas2.sagaNext(projectRoot, { sagaId });
|
|
65920
|
+
cliOutput(result.success ? result.data : result, { command: "saga", operation: "saga.next" });
|
|
65921
|
+
}
|
|
65922
|
+
});
|
|
65823
65923
|
sagaCommand = defineCommand({
|
|
65824
65924
|
meta: {
|
|
65825
65925
|
name: "saga",
|
|
@@ -65833,7 +65933,8 @@ var init_saga = __esm({
|
|
|
65833
65933
|
members: membersCommand,
|
|
65834
65934
|
rollup: rollupCommand2,
|
|
65835
65935
|
repair: repairCommand,
|
|
65836
|
-
reconcile: reconcileCommand5
|
|
65936
|
+
reconcile: reconcileCommand5,
|
|
65937
|
+
next: nextCommand3
|
|
65837
65938
|
},
|
|
65838
65939
|
async run({ cmd, rawArgs }) {
|
|
65839
65940
|
const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
|
|
@@ -66075,7 +66176,7 @@ async function writeRuntimeVersionMetadata(mode, source, version) {
|
|
|
66075
66176
|
`installed=${(/* @__PURE__ */ new Date()).toISOString()}`
|
|
66076
66177
|
];
|
|
66077
66178
|
await import("node:fs/promises").then(
|
|
66078
|
-
({ writeFile: writeFile4, mkdir:
|
|
66179
|
+
({ writeFile: writeFile4, mkdir: mkdir6 }) => mkdir6(cleoHome, { recursive: true }).then(
|
|
66079
66180
|
() => writeFile4(join29(cleoHome, "VERSION"), `${lines.join("\n")}
|
|
66080
66181
|
`, "utf-8")
|
|
66081
66182
|
)
|
|
@@ -72919,15 +73020,12 @@ var init_verify = __esm({
|
|
|
72919
73020
|
}
|
|
72920
73021
|
});
|
|
72921
73022
|
|
|
72922
|
-
// packages/cleo/src/cli/
|
|
72923
|
-
var web_exports = {};
|
|
72924
|
-
__export(web_exports, {
|
|
72925
|
-
webCommand: () => webCommand
|
|
72926
|
-
});
|
|
73023
|
+
// packages/cleo/src/cli/web-subsystem.ts
|
|
72927
73024
|
import { execFileSync as execFileSync4, spawn as spawn3 } from "node:child_process";
|
|
72928
|
-
import { mkdir as
|
|
73025
|
+
import { mkdir as mkdir5, open, readFile as readFile8, rm, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
|
|
72929
73026
|
import { join as join35 } from "node:path";
|
|
72930
|
-
import {
|
|
73027
|
+
import { getCleoHome as getCleoHome5 } from "@cleocode/core";
|
|
73028
|
+
import { defineSubsystem as defineSubsystem2 } from "@cleocode/runtime/daemon";
|
|
72931
73029
|
function getWebPaths() {
|
|
72932
73030
|
const cleoHome = getCleoHome5();
|
|
72933
73031
|
return {
|
|
@@ -72937,7 +73035,7 @@ function getWebPaths() {
|
|
|
72937
73035
|
logFile: join35(cleoHome, "logs", "web-server.log")
|
|
72938
73036
|
};
|
|
72939
73037
|
}
|
|
72940
|
-
function
|
|
73038
|
+
function isWebProcessRunning(pid) {
|
|
72941
73039
|
try {
|
|
72942
73040
|
process.kill(pid, 0);
|
|
72943
73041
|
return true;
|
|
@@ -72945,20 +73043,20 @@ function isProcessRunning(pid) {
|
|
|
72945
73043
|
return false;
|
|
72946
73044
|
}
|
|
72947
73045
|
}
|
|
72948
|
-
async function
|
|
73046
|
+
async function getWebStatus() {
|
|
72949
73047
|
const { pidFile, configFile } = getWebPaths();
|
|
72950
73048
|
try {
|
|
72951
73049
|
const pidStr = (await readFile8(pidFile, "utf-8")).trim();
|
|
72952
73050
|
const pid = Number.parseInt(pidStr, 10);
|
|
72953
|
-
if (Number.isNaN(pid) || !
|
|
73051
|
+
if (Number.isNaN(pid) || !isWebProcessRunning(pid)) {
|
|
72954
73052
|
return { running: false, pid: null, port: null, host: null, url: null };
|
|
72955
73053
|
}
|
|
72956
|
-
let port =
|
|
72957
|
-
let host =
|
|
73054
|
+
let port = WEB_DEFAULT_PORT;
|
|
73055
|
+
let host = WEB_DEFAULT_HOST;
|
|
72958
73056
|
try {
|
|
72959
73057
|
const config = JSON.parse(await readFile8(configFile, "utf-8"));
|
|
72960
|
-
port = config.port ??
|
|
72961
|
-
host = config.host ??
|
|
73058
|
+
port = config.port ?? WEB_DEFAULT_PORT;
|
|
73059
|
+
host = config.host ?? WEB_DEFAULT_HOST;
|
|
72962
73060
|
} catch {
|
|
72963
73061
|
}
|
|
72964
73062
|
return { running: true, pid, port, host, url: `http://${host}:${port}` };
|
|
@@ -72966,118 +73064,212 @@ async function getStatus() {
|
|
|
72966
73064
|
return { running: false, pid: null, port: null, host: null, url: null };
|
|
72967
73065
|
}
|
|
72968
73066
|
}
|
|
72969
|
-
|
|
72970
|
-
const
|
|
72971
|
-
const
|
|
72972
|
-
|
|
72973
|
-
|
|
72974
|
-
|
|
72975
|
-
|
|
72976
|
-
|
|
72977
|
-
|
|
72978
|
-
|
|
72979
|
-
|
|
72980
|
-
|
|
72981
|
-
|
|
72982
|
-
|
|
72983
|
-
|
|
72984
|
-
|
|
72985
|
-
|
|
72986
|
-
|
|
72987
|
-
|
|
72988
|
-
|
|
72989
|
-
|
|
72990
|
-
|
|
72991
|
-
|
|
72992
|
-
|
|
72993
|
-
|
|
72994
|
-
|
|
72995
|
-
|
|
72996
|
-
throw new CleoError12(
|
|
72997
|
-
1 /* GENERAL_ERROR */,
|
|
72998
|
-
`Studio build failed. Run: pnpm --filter @cleocode/studio run build
|
|
72999
|
-
Logs: ${logFile}`
|
|
73067
|
+
function createWebSubsystem(opts = {}) {
|
|
73068
|
+
const port = opts.port ?? WEB_DEFAULT_PORT;
|
|
73069
|
+
const host = opts.host ?? WEB_DEFAULT_HOST;
|
|
73070
|
+
let live;
|
|
73071
|
+
return defineSubsystem2({
|
|
73072
|
+
name: WEB_SUBSYSTEM_NAME,
|
|
73073
|
+
async start() {
|
|
73074
|
+
const { pidFile, configFile, logFile, logDir } = getWebPaths();
|
|
73075
|
+
const existing = await getWebStatus();
|
|
73076
|
+
if (existing.running && existing.pid !== null) {
|
|
73077
|
+
const ctx2 = {
|
|
73078
|
+
pid: existing.pid,
|
|
73079
|
+
pidFile,
|
|
73080
|
+
logFile,
|
|
73081
|
+
port: existing.port ?? port,
|
|
73082
|
+
host: existing.host ?? host
|
|
73083
|
+
};
|
|
73084
|
+
live = ctx2;
|
|
73085
|
+
return ctx2;
|
|
73086
|
+
}
|
|
73087
|
+
const projectRoot = process.env["CLEO_ROOT"] ?? process.cwd();
|
|
73088
|
+
const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join35(projectRoot, "packages", "studio", "build");
|
|
73089
|
+
const webIndexPath = join35(studioDir, "index.js");
|
|
73090
|
+
await mkdir5(logDir, { recursive: true });
|
|
73091
|
+
await writeFile3(
|
|
73092
|
+
configFile,
|
|
73093
|
+
JSON.stringify({ port, host, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
|
|
73000
73094
|
);
|
|
73001
|
-
|
|
73002
|
-
|
|
73003
|
-
|
|
73004
|
-
|
|
73005
|
-
|
|
73006
|
-
|
|
73007
|
-
|
|
73008
|
-
|
|
73009
|
-
|
|
73010
|
-
|
|
73011
|
-
|
|
73095
|
+
try {
|
|
73096
|
+
await stat2(webIndexPath);
|
|
73097
|
+
} catch {
|
|
73098
|
+
try {
|
|
73099
|
+
execFileSync4("pnpm", ["--filter", "@cleocode/studio", "run", "build"], {
|
|
73100
|
+
cwd: projectRoot,
|
|
73101
|
+
stdio: "ignore"
|
|
73102
|
+
});
|
|
73103
|
+
} catch {
|
|
73104
|
+
throw new Error(
|
|
73105
|
+
`Studio build failed. Run: pnpm --filter @cleocode/studio run build
|
|
73106
|
+
Logs: ${logFile}`
|
|
73107
|
+
);
|
|
73108
|
+
}
|
|
73109
|
+
}
|
|
73110
|
+
const logFileHandle = await open(logFile, "a");
|
|
73111
|
+
const serverProcess = spawn3("node", [webIndexPath], {
|
|
73112
|
+
cwd: studioDir,
|
|
73113
|
+
env: {
|
|
73114
|
+
...process.env,
|
|
73115
|
+
HOST: host,
|
|
73116
|
+
PORT: String(port),
|
|
73117
|
+
CLEO_ROOT: projectRoot
|
|
73118
|
+
},
|
|
73119
|
+
detached: true,
|
|
73120
|
+
stdio: ["ignore", logFileHandle.fd, logFileHandle.fd]
|
|
73121
|
+
});
|
|
73122
|
+
serverProcess.unref();
|
|
73123
|
+
const pidFileTmp = `${pidFile}.tmp`;
|
|
73124
|
+
await writeFile3(pidFileTmp, String(serverProcess.pid));
|
|
73125
|
+
await rm(pidFile, { force: true });
|
|
73126
|
+
await writeFile3(pidFile, String(serverProcess.pid));
|
|
73127
|
+
await rm(pidFileTmp, { force: true });
|
|
73128
|
+
await logFileHandle.close();
|
|
73129
|
+
let started = false;
|
|
73130
|
+
for (let i = 0; i < STARTUP_POLL_ITERATIONS; i++) {
|
|
73131
|
+
try {
|
|
73132
|
+
const response = await fetch(`http://${host}:${port}/api/health`);
|
|
73133
|
+
if (response.ok) {
|
|
73134
|
+
started = true;
|
|
73135
|
+
break;
|
|
73136
|
+
}
|
|
73137
|
+
} catch {
|
|
73138
|
+
}
|
|
73139
|
+
await new Promise((resolve11) => setTimeout(resolve11, 500));
|
|
73140
|
+
}
|
|
73141
|
+
if (!started) {
|
|
73142
|
+
try {
|
|
73143
|
+
process.kill(serverProcess.pid, "SIGTERM");
|
|
73144
|
+
} catch {
|
|
73145
|
+
}
|
|
73146
|
+
await rm(pidFile, { force: true });
|
|
73147
|
+
throw new Error("Studio web server failed to start within 15 seconds");
|
|
73148
|
+
}
|
|
73149
|
+
const ctx = {
|
|
73150
|
+
pid: serverProcess.pid,
|
|
73151
|
+
pidFile,
|
|
73152
|
+
logFile,
|
|
73153
|
+
port,
|
|
73154
|
+
host
|
|
73155
|
+
};
|
|
73156
|
+
live = ctx;
|
|
73157
|
+
return ctx;
|
|
73012
73158
|
},
|
|
73013
|
-
|
|
73014
|
-
|
|
73015
|
-
|
|
73016
|
-
|
|
73017
|
-
|
|
73018
|
-
|
|
73019
|
-
|
|
73020
|
-
|
|
73021
|
-
|
|
73022
|
-
|
|
73023
|
-
const maxAttempts = 30;
|
|
73024
|
-
let started = false;
|
|
73025
|
-
for (let i = 0; i < maxAttempts; i++) {
|
|
73026
|
-
try {
|
|
73027
|
-
const response = await fetch(`http://${host}:${port}/api/health`);
|
|
73028
|
-
if (response.ok) {
|
|
73029
|
-
started = true;
|
|
73030
|
-
break;
|
|
73159
|
+
healthProbe() {
|
|
73160
|
+
if (live === void 0) {
|
|
73161
|
+
const stopped = "stopped";
|
|
73162
|
+
return {
|
|
73163
|
+
child_id: WEB_SUBSYSTEM_NAME,
|
|
73164
|
+
pid: 0,
|
|
73165
|
+
state: stopped,
|
|
73166
|
+
restart_count: 0,
|
|
73167
|
+
detail: "not started"
|
|
73168
|
+
};
|
|
73031
73169
|
}
|
|
73032
|
-
|
|
73033
|
-
|
|
73034
|
-
|
|
73035
|
-
|
|
73036
|
-
|
|
73037
|
-
|
|
73038
|
-
|
|
73039
|
-
|
|
73040
|
-
|
|
73041
|
-
await rm(pidFile, { force: true });
|
|
73042
|
-
throw new CleoError12(1 /* GENERAL_ERROR */, "Server failed to start within 15 seconds");
|
|
73043
|
-
}
|
|
73044
|
-
cliOutput(
|
|
73045
|
-
{
|
|
73046
|
-
pid: serverProcess.pid,
|
|
73047
|
-
port,
|
|
73048
|
-
host,
|
|
73049
|
-
url: `http://${host}:${port}`,
|
|
73050
|
-
logFile
|
|
73170
|
+
const alive = isWebProcessRunning(live.pid);
|
|
73171
|
+
const state = alive ? "running" : "stopped";
|
|
73172
|
+
return {
|
|
73173
|
+
child_id: WEB_SUBSYSTEM_NAME,
|
|
73174
|
+
pid: alive ? live.pid : 0,
|
|
73175
|
+
state,
|
|
73176
|
+
restart_count: 0,
|
|
73177
|
+
detail: alive ? `url=http://${live.host}:${live.port} pid=${live.pid}` : `pid=${live.pid} exited`
|
|
73178
|
+
};
|
|
73051
73179
|
},
|
|
73052
|
-
|
|
73053
|
-
|
|
73180
|
+
async shutdown(context) {
|
|
73181
|
+
const { pidFile } = context;
|
|
73182
|
+
if (!isWebProcessRunning(context.pid)) {
|
|
73183
|
+
await rm(pidFile, { force: true });
|
|
73184
|
+
live = void 0;
|
|
73185
|
+
return;
|
|
73186
|
+
}
|
|
73187
|
+
try {
|
|
73188
|
+
if (process.platform === "win32") {
|
|
73189
|
+
spawn3("taskkill", ["/PID", String(context.pid), "/T"], { stdio: "ignore" });
|
|
73190
|
+
} else {
|
|
73191
|
+
process.kill(context.pid, "SIGTERM");
|
|
73192
|
+
}
|
|
73193
|
+
} catch {
|
|
73194
|
+
}
|
|
73195
|
+
for (let i = 0; i < SIGTERM_GRACE_ITERATIONS2; i++) {
|
|
73196
|
+
if (!isWebProcessRunning(context.pid)) break;
|
|
73197
|
+
await new Promise((resolve11) => setTimeout(resolve11, 500));
|
|
73198
|
+
}
|
|
73199
|
+
if (isWebProcessRunning(context.pid)) {
|
|
73200
|
+
try {
|
|
73201
|
+
if (process.platform === "win32") {
|
|
73202
|
+
spawn3("taskkill", ["/PID", String(context.pid), "/F", "/T"], { stdio: "ignore" });
|
|
73203
|
+
} else {
|
|
73204
|
+
process.kill(context.pid, "SIGKILL");
|
|
73205
|
+
}
|
|
73206
|
+
} catch {
|
|
73207
|
+
}
|
|
73208
|
+
}
|
|
73209
|
+
await rm(pidFile, { force: true });
|
|
73210
|
+
live = void 0;
|
|
73211
|
+
}
|
|
73212
|
+
});
|
|
73054
73213
|
}
|
|
73055
|
-
var
|
|
73214
|
+
var WEB_DEFAULT_PORT, WEB_DEFAULT_HOST, WEB_SUBSYSTEM_NAME, SIGTERM_GRACE_ITERATIONS2, STARTUP_POLL_ITERATIONS;
|
|
73215
|
+
var init_web_subsystem = __esm({
|
|
73216
|
+
"packages/cleo/src/cli/web-subsystem.ts"() {
|
|
73217
|
+
"use strict";
|
|
73218
|
+
WEB_DEFAULT_PORT = 3456;
|
|
73219
|
+
WEB_DEFAULT_HOST = "127.0.0.1";
|
|
73220
|
+
WEB_SUBSYSTEM_NAME = "cleo-web";
|
|
73221
|
+
SIGTERM_GRACE_ITERATIONS2 = 60;
|
|
73222
|
+
STARTUP_POLL_ITERATIONS = 30;
|
|
73223
|
+
}
|
|
73224
|
+
});
|
|
73225
|
+
|
|
73226
|
+
// packages/cleo/src/cli/commands/web.ts
|
|
73227
|
+
var web_exports = {};
|
|
73228
|
+
__export(web_exports, {
|
|
73229
|
+
webCommand: () => webCommand
|
|
73230
|
+
});
|
|
73231
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
73232
|
+
import { rm as rm2 } from "node:fs/promises";
|
|
73233
|
+
import { CleoError as CleoError12, formatError as formatError5 } from "@cleocode/core";
|
|
73234
|
+
var startCommand9, stopCommand6, restartCommand, statusCommand18, openCommand3, webCommand;
|
|
73056
73235
|
var init_web = __esm({
|
|
73057
73236
|
"packages/cleo/src/cli/commands/web.ts"() {
|
|
73058
73237
|
"use strict";
|
|
73059
73238
|
init_src2();
|
|
73060
73239
|
init_dist();
|
|
73061
73240
|
init_renderers();
|
|
73062
|
-
|
|
73063
|
-
DEFAULT_HOST = "127.0.0.1";
|
|
73241
|
+
init_web_subsystem();
|
|
73064
73242
|
startCommand9 = defineCommand({
|
|
73065
73243
|
meta: { name: "start", description: "Start the web server" },
|
|
73066
73244
|
args: {
|
|
73067
73245
|
port: {
|
|
73068
73246
|
type: "string",
|
|
73069
73247
|
description: "Server port",
|
|
73070
|
-
default: String(
|
|
73248
|
+
default: String(WEB_DEFAULT_PORT)
|
|
73071
73249
|
},
|
|
73072
73250
|
host: {
|
|
73073
73251
|
type: "string",
|
|
73074
73252
|
description: "Server host",
|
|
73075
|
-
default:
|
|
73253
|
+
default: WEB_DEFAULT_HOST
|
|
73076
73254
|
}
|
|
73077
73255
|
},
|
|
73078
73256
|
async run({ args }) {
|
|
73079
73257
|
try {
|
|
73080
|
-
|
|
73258
|
+
const port = Number.parseInt(args.port, 10);
|
|
73259
|
+
const host = args.host;
|
|
73260
|
+
const subsystem = createWebSubsystem({ port, host });
|
|
73261
|
+
const ctx = await subsystem.start();
|
|
73262
|
+
const { logFile } = getWebPaths();
|
|
73263
|
+
cliOutput(
|
|
73264
|
+
{
|
|
73265
|
+
pid: ctx.pid,
|
|
73266
|
+
port: ctx.port,
|
|
73267
|
+
host: ctx.host,
|
|
73268
|
+
url: `http://${ctx.host}:${ctx.port}`,
|
|
73269
|
+
logFile
|
|
73270
|
+
},
|
|
73271
|
+
{ command: "web", message: `CLEO Web UI running on port ${ctx.port}` }
|
|
73272
|
+
);
|
|
73081
73273
|
} catch (err) {
|
|
73082
73274
|
if (err instanceof CleoError12) {
|
|
73083
73275
|
console.error(formatError5(err));
|
|
@@ -73091,36 +73283,24 @@ var init_web = __esm({
|
|
|
73091
73283
|
meta: { name: "stop", description: "Stop the web server" },
|
|
73092
73284
|
async run() {
|
|
73093
73285
|
try {
|
|
73094
|
-
const { pidFile } = getWebPaths();
|
|
73095
|
-
const status = await
|
|
73096
|
-
if (!status.running ||
|
|
73097
|
-
await
|
|
73286
|
+
const { pidFile, logFile } = getWebPaths();
|
|
73287
|
+
const status = await getWebStatus();
|
|
73288
|
+
if (!status.running || status.pid === null) {
|
|
73289
|
+
await rm2(pidFile, { force: true });
|
|
73098
73290
|
cliOutput({ running: false }, { command: "web", message: "Server is not running" });
|
|
73099
73291
|
return;
|
|
73100
73292
|
}
|
|
73101
|
-
|
|
73102
|
-
|
|
73103
|
-
|
|
73104
|
-
|
|
73105
|
-
|
|
73106
|
-
|
|
73107
|
-
|
|
73108
|
-
|
|
73109
|
-
|
|
73110
|
-
|
|
73111
|
-
|
|
73112
|
-
}
|
|
73113
|
-
if (isProcessRunning(status.pid)) {
|
|
73114
|
-
try {
|
|
73115
|
-
if (process.platform === "win32") {
|
|
73116
|
-
spawn3("taskkill", ["/PID", String(status.pid), "/F", "/T"], { stdio: "ignore" });
|
|
73117
|
-
} else {
|
|
73118
|
-
process.kill(status.pid, "SIGKILL");
|
|
73119
|
-
}
|
|
73120
|
-
} catch {
|
|
73121
|
-
}
|
|
73122
|
-
}
|
|
73123
|
-
await rm(pidFile, { force: true });
|
|
73293
|
+
const subsystem = createWebSubsystem({
|
|
73294
|
+
port: status.port ?? WEB_DEFAULT_PORT,
|
|
73295
|
+
host: status.host ?? WEB_DEFAULT_HOST
|
|
73296
|
+
});
|
|
73297
|
+
await subsystem.shutdown({
|
|
73298
|
+
pid: status.pid,
|
|
73299
|
+
pidFile,
|
|
73300
|
+
logFile,
|
|
73301
|
+
port: status.port ?? WEB_DEFAULT_PORT,
|
|
73302
|
+
host: status.host ?? WEB_DEFAULT_HOST
|
|
73303
|
+
});
|
|
73124
73304
|
cliOutput({ stopped: true }, { command: "web", message: "CLEO Web UI stopped" });
|
|
73125
73305
|
} catch (err) {
|
|
73126
73306
|
if (err instanceof CleoError12) {
|
|
@@ -73137,44 +73317,45 @@ var init_web = __esm({
|
|
|
73137
73317
|
port: {
|
|
73138
73318
|
type: "string",
|
|
73139
73319
|
description: "Server port",
|
|
73140
|
-
default: String(
|
|
73320
|
+
default: String(WEB_DEFAULT_PORT)
|
|
73141
73321
|
},
|
|
73142
73322
|
host: {
|
|
73143
73323
|
type: "string",
|
|
73144
73324
|
description: "Server host",
|
|
73145
|
-
default:
|
|
73325
|
+
default: WEB_DEFAULT_HOST
|
|
73146
73326
|
}
|
|
73147
73327
|
},
|
|
73148
73328
|
async run({ args }) {
|
|
73149
73329
|
try {
|
|
73150
|
-
const
|
|
73151
|
-
const
|
|
73152
|
-
|
|
73153
|
-
|
|
73154
|
-
|
|
73155
|
-
|
|
73156
|
-
|
|
73157
|
-
|
|
73158
|
-
|
|
73159
|
-
|
|
73160
|
-
|
|
73161
|
-
|
|
73162
|
-
|
|
73163
|
-
|
|
73164
|
-
|
|
73165
|
-
|
|
73166
|
-
try {
|
|
73167
|
-
if (process.platform === "win32") {
|
|
73168
|
-
spawn3("taskkill", ["/PID", String(status.pid), "/F", "/T"], { stdio: "ignore" });
|
|
73169
|
-
} else {
|
|
73170
|
-
process.kill(status.pid, "SIGKILL");
|
|
73171
|
-
}
|
|
73172
|
-
} catch {
|
|
73173
|
-
}
|
|
73174
|
-
}
|
|
73175
|
-
await rm(pidFile, { force: true });
|
|
73330
|
+
const port = Number.parseInt(args.port, 10);
|
|
73331
|
+
const host = args.host;
|
|
73332
|
+
const { pidFile, logFile } = getWebPaths();
|
|
73333
|
+
const status = await getWebStatus();
|
|
73334
|
+
if (status.running && status.pid !== null) {
|
|
73335
|
+
const stopSubsystem = createWebSubsystem({
|
|
73336
|
+
port: status.port ?? port,
|
|
73337
|
+
host: status.host ?? host
|
|
73338
|
+
});
|
|
73339
|
+
await stopSubsystem.shutdown({
|
|
73340
|
+
pid: status.pid,
|
|
73341
|
+
pidFile,
|
|
73342
|
+
logFile,
|
|
73343
|
+
port: status.port ?? port,
|
|
73344
|
+
host: status.host ?? host
|
|
73345
|
+
});
|
|
73176
73346
|
}
|
|
73177
|
-
|
|
73347
|
+
const startSubsystem = createWebSubsystem({ port, host });
|
|
73348
|
+
const ctx = await startSubsystem.start();
|
|
73349
|
+
cliOutput(
|
|
73350
|
+
{
|
|
73351
|
+
pid: ctx.pid,
|
|
73352
|
+
port: ctx.port,
|
|
73353
|
+
host: ctx.host,
|
|
73354
|
+
url: `http://${ctx.host}:${ctx.port}`,
|
|
73355
|
+
logFile
|
|
73356
|
+
},
|
|
73357
|
+
{ command: "web", message: `CLEO Web UI running on port ${ctx.port}` }
|
|
73358
|
+
);
|
|
73178
73359
|
} catch (err) {
|
|
73179
73360
|
if (err instanceof CleoError12) {
|
|
73180
73361
|
console.error(formatError5(err));
|
|
@@ -73188,7 +73369,7 @@ var init_web = __esm({
|
|
|
73188
73369
|
meta: { name: "status", description: "Check server status" },
|
|
73189
73370
|
async run() {
|
|
73190
73371
|
try {
|
|
73191
|
-
const status = await
|
|
73372
|
+
const status = await getWebStatus();
|
|
73192
73373
|
cliOutput(status, { command: "web" });
|
|
73193
73374
|
} catch (err) {
|
|
73194
73375
|
if (err instanceof CleoError12) {
|
|
@@ -73203,7 +73384,7 @@ var init_web = __esm({
|
|
|
73203
73384
|
meta: { name: "open", description: "Open browser to the UI" },
|
|
73204
73385
|
async run() {
|
|
73205
73386
|
try {
|
|
73206
|
-
const status = await
|
|
73387
|
+
const status = await getWebStatus();
|
|
73207
73388
|
if (!status.running || !status.url) {
|
|
73208
73389
|
throw new CleoError12(
|
|
73209
73390
|
1 /* GENERAL_ERROR */,
|
|
@@ -73214,11 +73395,11 @@ var init_web = __esm({
|
|
|
73214
73395
|
const platform = process.platform;
|
|
73215
73396
|
try {
|
|
73216
73397
|
if (platform === "linux") {
|
|
73217
|
-
|
|
73398
|
+
spawn4("xdg-open", [url], { detached: true, stdio: "ignore" }).unref();
|
|
73218
73399
|
} else if (platform === "darwin") {
|
|
73219
|
-
|
|
73400
|
+
spawn4("open", [url], { detached: true, stdio: "ignore" }).unref();
|
|
73220
73401
|
} else if (platform === "win32") {
|
|
73221
|
-
|
|
73402
|
+
spawn4("cmd", ["/c", "start", "", url], { detached: true, stdio: "ignore" }).unref();
|
|
73222
73403
|
}
|
|
73223
73404
|
} catch {
|
|
73224
73405
|
}
|
|
@@ -73257,7 +73438,7 @@ __export(workgraph_exports, {
|
|
|
73257
73438
|
});
|
|
73258
73439
|
import { readFileSync as readFileSync20 } from "node:fs";
|
|
73259
73440
|
import { resolve as resolve10 } from "node:path";
|
|
73260
|
-
var validateCommand10, applyCommand, planCommand4, structureCommand, workgraphCommand;
|
|
73441
|
+
var validateCommand10, applyCommand, planCommand4, structureCommand, statusCommand19, workgraphCommand;
|
|
73261
73442
|
var init_workgraph2 = __esm({
|
|
73262
73443
|
"packages/cleo/src/cli/commands/workgraph.ts"() {
|
|
73263
73444
|
"use strict";
|
|
@@ -73401,16 +73582,64 @@ var init_workgraph2 = __esm({
|
|
|
73401
73582
|
cliOutput2(result, { command: "workgraph", operation: "structure" });
|
|
73402
73583
|
}
|
|
73403
73584
|
});
|
|
73585
|
+
statusCommand19 = defineCommand({
|
|
73586
|
+
meta: {
|
|
73587
|
+
name: "status",
|
|
73588
|
+
description: "One-shot saga-to-saga workgraph dashboard (tracking checklist)"
|
|
73589
|
+
},
|
|
73590
|
+
async run() {
|
|
73591
|
+
const { sagas: sagas2, getProjectRoot: getProjectRoot57 } = await import("@cleocode/core");
|
|
73592
|
+
const { cliOutput: cliOutput2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
|
|
73593
|
+
const projectRoot = getProjectRoot57();
|
|
73594
|
+
const listResult = await sagas2.sagaList(projectRoot);
|
|
73595
|
+
if (!listResult.success) {
|
|
73596
|
+
cliOutput2(listResult, { command: "workgraph", operation: "workgraph.status" });
|
|
73597
|
+
return;
|
|
73598
|
+
}
|
|
73599
|
+
const allSagas = listResult.data?.sagas ?? [];
|
|
73600
|
+
const sagaMap = new Map(
|
|
73601
|
+
allSagas.map((s) => [s.id, s])
|
|
73602
|
+
);
|
|
73603
|
+
const TERMINAL = /* @__PURE__ */ new Set(["done", "cancelled", "deleted", "archived", "completed"]);
|
|
73604
|
+
const rows = [];
|
|
73605
|
+
for (let i = 0; i < sagas2.CANONICAL_SAGA_ORDER.length; i++) {
|
|
73606
|
+
const [id, label] = sagas2.CANONICAL_SAGA_ORDER[i];
|
|
73607
|
+
const saga = sagaMap.get(id);
|
|
73608
|
+
if (!saga) continue;
|
|
73609
|
+
const status = saga.status ?? "pending";
|
|
73610
|
+
const rollupResult = await sagas2.sagaRollup(projectRoot, { sagaId: id });
|
|
73611
|
+
const rollup = rollupResult.success ? rollupResult.data : { total: 0, done: 0, completionPct: 0 };
|
|
73612
|
+
rows.push({
|
|
73613
|
+
rank: i + 1,
|
|
73614
|
+
sagaId: id,
|
|
73615
|
+
status,
|
|
73616
|
+
completionPct: rollup.completionPct ?? 0,
|
|
73617
|
+
done: rollup.done ?? 0,
|
|
73618
|
+
total: rollup.total ?? 0,
|
|
73619
|
+
label: TERMINAL.has(status) ? `${label} \u2713` : label
|
|
73620
|
+
});
|
|
73621
|
+
}
|
|
73622
|
+
cliOutput2(
|
|
73623
|
+
{
|
|
73624
|
+
rows,
|
|
73625
|
+
total: rows.length,
|
|
73626
|
+
activeSagaCount: rows.filter((r) => !TERMINAL.has(r.status)).length
|
|
73627
|
+
},
|
|
73628
|
+
{ command: "workgraph", operation: "workgraph.status" }
|
|
73629
|
+
);
|
|
73630
|
+
}
|
|
73631
|
+
});
|
|
73404
73632
|
workgraphCommand = defineCommand({
|
|
73405
73633
|
meta: {
|
|
73406
73634
|
name: "workgraph",
|
|
73407
|
-
description: "PM-Core V2 WorkGraph operations \u2014 validate, apply, plan, structure"
|
|
73635
|
+
description: "PM-Core V2 WorkGraph operations \u2014 validate, apply, plan, structure, status"
|
|
73408
73636
|
},
|
|
73409
73637
|
subCommands: {
|
|
73410
73638
|
validate: validateCommand10,
|
|
73411
73639
|
apply: applyCommand,
|
|
73412
73640
|
plan: planCommand4,
|
|
73413
|
-
structure: structureCommand
|
|
73641
|
+
structure: structureCommand,
|
|
73642
|
+
status: statusCommand19
|
|
73414
73643
|
},
|
|
73415
73644
|
async run({ cmd, rawArgs }) {
|
|
73416
73645
|
const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
|
|
@@ -73775,7 +74004,7 @@ init_field_context();
|
|
|
73775
74004
|
init_format_context();
|
|
73776
74005
|
import { readFileSync as readFileSync21 } from "node:fs";
|
|
73777
74006
|
import { dirname as dirname11, join as join37 } from "node:path";
|
|
73778
|
-
import { fileURLToPath as
|
|
74007
|
+
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
73779
74008
|
import { enforceNodeVersion } from "@cleocode/paths";
|
|
73780
74009
|
|
|
73781
74010
|
// packages/cleo/src/cli/generated/command-manifest.ts
|
|
@@ -74176,10 +74405,16 @@ var COMMAND_MANIFEST = [
|
|
|
74176
74405
|
description: "Transcript garbage collection: manual trigger and status",
|
|
74177
74406
|
load: async () => (await Promise.resolve().then(() => (init_gc(), gc_exports))).gcCommand
|
|
74178
74407
|
},
|
|
74408
|
+
{
|
|
74409
|
+
exportName: "goCommand",
|
|
74410
|
+
name: "go",
|
|
74411
|
+
description: "SG-AUTOPILOT: run one turn of briefing\u2192sagaNext\u2192ready\u2192stage-branch\u2192ivtr loop",
|
|
74412
|
+
load: async () => (await Promise.resolve().then(() => (init_go(), go_exports))).goCommand
|
|
74413
|
+
},
|
|
74179
74414
|
{
|
|
74180
74415
|
exportName: "goalCommand",
|
|
74181
74416
|
name: "goal",
|
|
74182
|
-
description: "DB-persisted, per-agent, evidence-gate-aware goal loop (set/status/subgoal/append).",
|
|
74417
|
+
description: "DB-persisted, per-agent, evidence-gate-aware goal loop (set/status/advance/subgoal/append).",
|
|
74183
74418
|
load: async () => (await Promise.resolve().then(() => (init_goal2(), goal_exports))).goalCommand
|
|
74184
74419
|
},
|
|
74185
74420
|
{
|
|
@@ -74659,7 +74894,7 @@ var COMMAND_MANIFEST = [
|
|
|
74659
74894
|
{
|
|
74660
74895
|
exportName: "workgraphCommand",
|
|
74661
74896
|
name: "workgraph",
|
|
74662
|
-
description: "PM-Core V2 WorkGraph operations \u2014 validate, apply, plan, structure",
|
|
74897
|
+
description: "PM-Core V2 WorkGraph operations \u2014 validate, apply, plan, structure, status",
|
|
74663
74898
|
load: async () => (await Promise.resolve().then(() => (init_workgraph2(), workgraph_exports))).workgraphCommand
|
|
74664
74899
|
},
|
|
74665
74900
|
{
|
|
@@ -74940,7 +75175,7 @@ async function resolveSubCommandForHelp(cmd, rawArgs) {
|
|
|
74940
75175
|
init_summary_context();
|
|
74941
75176
|
enforceNodeVersion();
|
|
74942
75177
|
function getPackageVersion() {
|
|
74943
|
-
const pkgPath = join37(dirname11(
|
|
75178
|
+
const pkgPath = join37(dirname11(fileURLToPath6(import.meta.url)), "../../package.json");
|
|
74944
75179
|
const pkg = JSON.parse(readFileSync21(pkgPath, "utf-8"));
|
|
74945
75180
|
return pkg.version;
|
|
74946
75181
|
}
|