@cleocode/cleo 2026.5.0 → 2026.5.2
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/bin/postinstall.js +23 -0
- package/dist/cli/commands/complete.d.ts +9 -0
- package/dist/cli/commands/complete.d.ts.map +1 -1
- package/dist/cli/index.js +263 -36
- package/dist/cli/index.js.map +3 -3
- package/dist/dispatch/domains/tasks.d.ts.map +1 -1
- package/package.json +9 -9
- package/scripts/install-daemon-service.mjs +801 -0
package/bin/postinstall.js
CHANGED
|
@@ -154,6 +154,29 @@ async function runPostinstall() {
|
|
|
154
154
|
console.error('CLEO: Bootstrap detail:', err);
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
|
+
|
|
158
|
+
// Register the CLEO daemon as a user-level system service (systemd / launchd).
|
|
159
|
+
// This is non-blocking and never fails the install — errors are caught and logged.
|
|
160
|
+
await installDaemonServiceFromScript();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Install the CLEO daemon as a user-level system service after global install.
|
|
165
|
+
*
|
|
166
|
+
* Delegates to the cross-platform installer in scripts/install-daemon-service.mjs.
|
|
167
|
+
* Always exits cleanly — installation failures are non-fatal.
|
|
168
|
+
*/
|
|
169
|
+
async function installDaemonServiceFromScript() {
|
|
170
|
+
try {
|
|
171
|
+
const scriptPath = join(getPackageRoot(), 'scripts', 'install-daemon-service.mjs');
|
|
172
|
+
const { installDaemonService } = await import(scriptPath);
|
|
173
|
+
await installDaemonService();
|
|
174
|
+
} catch (err) {
|
|
175
|
+
console.log('CLEO: Daemon service registration deferred (will retry on first "cleo daemon install")');
|
|
176
|
+
if (process.env.CLEO_DEBUG) {
|
|
177
|
+
console.error('CLEO: Daemon install detail:', err);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
157
180
|
}
|
|
158
181
|
|
|
159
182
|
runPostinstall().catch((err) => {
|
|
@@ -13,8 +13,13 @@
|
|
|
13
13
|
* when a task touches symbols with CRITICAL impact risk. The acknowledgment is
|
|
14
14
|
* audited to `.cleo/audit/nexus-risk-ack.jsonl`.
|
|
15
15
|
*
|
|
16
|
+
* As of T1632, `cleo complete <epicId>` is REJECTED with E_EPIC_HAS_PENDING_CHILDREN
|
|
17
|
+
* when the epic has pending or active children. Pass `--override-reason "<reason>"`
|
|
18
|
+
* to bypass (audited to `.cleo/audit/premature-close.jsonl`).
|
|
19
|
+
*
|
|
16
20
|
* @task T4461
|
|
17
21
|
* @task T832
|
|
22
|
+
* @task T1632
|
|
18
23
|
* @adr ADR-051
|
|
19
24
|
* @epic T4454
|
|
20
25
|
*/
|
|
@@ -45,5 +50,9 @@ export declare const completeCommand: import("citty").CommandDef<{
|
|
|
45
50
|
readonly type: "string";
|
|
46
51
|
readonly description: "Reason for acknowledging CRITICAL impact risk (bypasses nexusImpact gate)";
|
|
47
52
|
};
|
|
53
|
+
readonly 'override-reason': {
|
|
54
|
+
readonly type: "string";
|
|
55
|
+
readonly description: "Reason for bypassing E_EPIC_HAS_PENDING_CHILDREN guard (audited to .cleo/audit/premature-close.jsonl)";
|
|
56
|
+
};
|
|
48
57
|
}>;
|
|
49
58
|
//# sourceMappingURL=complete.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"complete.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/complete.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"complete.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/complete.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAMH;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;EA8D1B,CAAC"}
|
package/dist/cli/index.js
CHANGED
|
@@ -416,6 +416,7 @@ var init_exit_codes = __esm({
|
|
|
416
416
|
ExitCode2[ExitCode2["VERIFICATION_LOCKED"] = 46] = "VERIFICATION_LOCKED";
|
|
417
417
|
ExitCode2[ExitCode2["ROUND_MISMATCH"] = 47] = "ROUND_MISMATCH";
|
|
418
418
|
ExitCode2[ExitCode2["AC_LOCKED"] = 48] = "AC_LOCKED";
|
|
419
|
+
ExitCode2[ExitCode2["EPIC_HAS_PENDING_CHILDREN"] = 49] = "EPIC_HAS_PENDING_CHILDREN";
|
|
419
420
|
ExitCode2[ExitCode2["CONTEXT_WARNING"] = 50] = "CONTEXT_WARNING";
|
|
420
421
|
ExitCode2[ExitCode2["CONTEXT_CAUTION"] = 51] = "CONTEXT_CAUTION";
|
|
421
422
|
ExitCode2[ExitCode2["CONTEXT_CRITICAL"] = 52] = "CONTEXT_CRITICAL";
|
|
@@ -465,6 +466,7 @@ var init_exit_codes = __esm({
|
|
|
465
466
|
ExitCode2[ExitCode2["ALREADY_EXISTS"] = 101] = "ALREADY_EXISTS";
|
|
466
467
|
ExitCode2[ExitCode2["NO_CHANGE"] = 102] = "NO_CHANGE";
|
|
467
468
|
ExitCode2[ExitCode2["TESTS_SKIPPED"] = 103] = "TESTS_SKIPPED";
|
|
469
|
+
ExitCode2[ExitCode2["DUPLICATE_TASK_LIKELY"] = 105] = "DUPLICATE_TASK_LIKELY";
|
|
468
470
|
ExitCode2[ExitCode2["LAFS_VIOLATION"] = 104] = "LAFS_VIOLATION";
|
|
469
471
|
return ExitCode2;
|
|
470
472
|
})(ExitCode || {});
|
|
@@ -24218,7 +24220,9 @@ var init_tasks3 = __esm({
|
|
|
24218
24220
|
// T944: orthogonal axes — role is the canonical wire field (ADR-057 D2)
|
|
24219
24221
|
role: params.role,
|
|
24220
24222
|
scope: params.scope,
|
|
24221
|
-
severity: params.severity
|
|
24223
|
+
severity: params.severity,
|
|
24224
|
+
// T1633: BRAIN duplicate-bypass flag
|
|
24225
|
+
forceDuplicate: params.forceDuplicate
|
|
24222
24226
|
}),
|
|
24223
24227
|
"add"
|
|
24224
24228
|
);
|
|
@@ -24260,7 +24264,11 @@ var init_tasks3 = __esm({
|
|
|
24260
24264
|
"complete"
|
|
24261
24265
|
);
|
|
24262
24266
|
}
|
|
24263
|
-
const result = await completeTaskStrict(projectRoot, params.taskId,
|
|
24267
|
+
const result = await completeTaskStrict(projectRoot, params.taskId, {
|
|
24268
|
+
notes: params.notes,
|
|
24269
|
+
overrideReason: params.overrideReason,
|
|
24270
|
+
acknowledgeRisk: params.acknowledgeRisk
|
|
24271
|
+
});
|
|
24264
24272
|
setImmediate(async () => {
|
|
24265
24273
|
try {
|
|
24266
24274
|
const { trackMemoryUsage } = await import("@cleocode/core/internal");
|
|
@@ -25950,7 +25958,7 @@ var init_cli = __esm({
|
|
|
25950
25958
|
// packages/cleo/src/cli/index.ts
|
|
25951
25959
|
import { readFileSync as readFileSync13 } from "node:fs";
|
|
25952
25960
|
import { dirname as dirname9, join as join19 } from "node:path";
|
|
25953
|
-
import { fileURLToPath as
|
|
25961
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
25954
25962
|
import {
|
|
25955
25963
|
detectAndRemoveLegacyGlobalFiles,
|
|
25956
25964
|
detectAndRemoveStrayProjectNexus,
|
|
@@ -26882,6 +26890,19 @@ var addCommand = defineCommand({
|
|
|
26882
26890
|
severity: {
|
|
26883
26891
|
type: "string",
|
|
26884
26892
|
description: "Bug severity (P0|P1|P2|P3) \u2014 only valid with --role bug (T944)"
|
|
26893
|
+
},
|
|
26894
|
+
/**
|
|
26895
|
+
* Bypass the E_DUPLICATE_TASK_LIKELY rejection guard.
|
|
26896
|
+
*
|
|
26897
|
+
* When passed, `cleo add` proceeds even if BRAIN similarity scoring
|
|
26898
|
+
* determines the task is very likely a duplicate (score >= 0.92).
|
|
26899
|
+
* The bypass is audited to `.cleo/audit/duplicate-bypass.jsonl`.
|
|
26900
|
+
*
|
|
26901
|
+
* @task T1633
|
|
26902
|
+
*/
|
|
26903
|
+
"force-duplicate": {
|
|
26904
|
+
type: "boolean",
|
|
26905
|
+
description: "Bypass BRAIN duplicate-task rejection (audited to .cleo/audit/duplicate-bypass.jsonl) (T1633)"
|
|
26885
26906
|
}
|
|
26886
26907
|
},
|
|
26887
26908
|
async run({ args, cmd }) {
|
|
@@ -26916,6 +26937,7 @@ var addCommand = defineCommand({
|
|
|
26916
26937
|
params["role"] = params["role"] ?? args.kind;
|
|
26917
26938
|
if (args.scope !== void 0) params["scope"] = args.scope;
|
|
26918
26939
|
if (args.severity !== void 0) params["severity"] = args.severity;
|
|
26940
|
+
if (args["force-duplicate"] !== void 0) params["forceDuplicate"] = args["force-duplicate"];
|
|
26919
26941
|
const inferred = await inferTaskAddParams(getProjectRoot18(), {
|
|
26920
26942
|
title: args.title,
|
|
26921
26943
|
description: args.description ?? args.desc,
|
|
@@ -33013,6 +33035,10 @@ var completeCommand = defineCommand({
|
|
|
33013
33035
|
"acknowledge-risk": {
|
|
33014
33036
|
type: "string",
|
|
33015
33037
|
description: "Reason for acknowledging CRITICAL impact risk (bypasses nexusImpact gate)"
|
|
33038
|
+
},
|
|
33039
|
+
"override-reason": {
|
|
33040
|
+
type: "string",
|
|
33041
|
+
description: "Reason for bypassing E_EPIC_HAS_PENDING_CHILDREN guard (audited to .cleo/audit/premature-close.jsonl)"
|
|
33016
33042
|
}
|
|
33017
33043
|
},
|
|
33018
33044
|
async run({ args }) {
|
|
@@ -33021,7 +33047,8 @@ var completeCommand = defineCommand({
|
|
|
33021
33047
|
notes: args.notes,
|
|
33022
33048
|
changeset: args.changeset,
|
|
33023
33049
|
verificationNote: args["verification-note"],
|
|
33024
|
-
acknowledgeRisk: args["acknowledge-risk"]
|
|
33050
|
+
acknowledgeRisk: args["acknowledge-risk"],
|
|
33051
|
+
overrideReason: args["override-reason"]
|
|
33025
33052
|
});
|
|
33026
33053
|
if (!response.success) {
|
|
33027
33054
|
handleRawError(response, { command: "complete", operation: "tasks.complete" });
|
|
@@ -33999,31 +34026,93 @@ var currentCommand = defineCommand({
|
|
|
33999
34026
|
// packages/cleo/src/cli/commands/daemon.ts
|
|
34000
34027
|
import { homedir as homedir2 } from "node:os";
|
|
34001
34028
|
import { join as join9 } from "node:path";
|
|
34029
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
34002
34030
|
import { getGCDaemonStatus, spawnGCDaemon, stopGCDaemon } from "@cleocode/core/gc/daemon.js";
|
|
34003
|
-
|
|
34031
|
+
import {
|
|
34032
|
+
bootstrapDaemon as bootstrapSentientDaemon,
|
|
34033
|
+
getSentientDaemonStatus
|
|
34034
|
+
} from "@cleocode/core/sentient";
|
|
34035
|
+
async function showDaemonStatus(cleoDir, projectRoot, json2) {
|
|
34004
34036
|
try {
|
|
34005
|
-
const
|
|
34006
|
-
|
|
34037
|
+
const gcStatus = await getGCDaemonStatus(cleoDir);
|
|
34038
|
+
let hygieneLastRunAt = null;
|
|
34039
|
+
let hygieneSummary = null;
|
|
34040
|
+
let hygieneStats = {
|
|
34041
|
+
projectsChecked: 0,
|
|
34042
|
+
projectsHealthy: 0,
|
|
34043
|
+
tempGcCandidates: 0,
|
|
34044
|
+
duplicateEpicGroups: 0,
|
|
34045
|
+
worktreesPruned: 0
|
|
34046
|
+
};
|
|
34047
|
+
try {
|
|
34048
|
+
const sentientStatus = await getSentientDaemonStatus(projectRoot);
|
|
34049
|
+
hygieneLastRunAt = sentientStatus.hygieneLastRunAt;
|
|
34050
|
+
hygieneSummary = sentientStatus.hygieneSummary;
|
|
34051
|
+
hygieneStats = sentientStatus.hygieneStats;
|
|
34052
|
+
} catch {
|
|
34053
|
+
}
|
|
34054
|
+
const result = {
|
|
34055
|
+
success: true,
|
|
34056
|
+
data: {
|
|
34057
|
+
gc: gcStatus,
|
|
34058
|
+
hygiene: {
|
|
34059
|
+
lastRunAt: hygieneLastRunAt,
|
|
34060
|
+
summary: hygieneSummary,
|
|
34061
|
+
stats: hygieneStats
|
|
34062
|
+
}
|
|
34063
|
+
}
|
|
34064
|
+
};
|
|
34007
34065
|
if (json2) {
|
|
34008
34066
|
process.stdout.write(JSON.stringify(result) + "\n");
|
|
34009
34067
|
} else {
|
|
34010
|
-
const runningStr =
|
|
34011
|
-
process.stdout.write(`Daemon: ${runningStr}
|
|
34068
|
+
const runningStr = gcStatus.running ? `running (PID ${gcStatus.pid})` : "stopped";
|
|
34069
|
+
process.stdout.write(`GC Daemon: ${runningStr}
|
|
34012
34070
|
`);
|
|
34013
|
-
process.stdout.write(`Started at:
|
|
34071
|
+
process.stdout.write(`Started at: ${gcStatus.startedAt ?? "never"}
|
|
34014
34072
|
`);
|
|
34015
|
-
process.stdout.write(`Last GC run:
|
|
34073
|
+
process.stdout.write(`Last GC run: ${gcStatus.lastRunAt ?? "never"}
|
|
34016
34074
|
`);
|
|
34017
|
-
const diskStr =
|
|
34018
|
-
process.stdout.write(`Disk used:
|
|
34075
|
+
const diskStr = gcStatus.lastDiskUsedPct !== null ? `${gcStatus.lastDiskUsedPct.toFixed(1)}%` : "unknown";
|
|
34076
|
+
process.stdout.write(`Disk used: ${diskStr}
|
|
34019
34077
|
`);
|
|
34020
|
-
if (
|
|
34078
|
+
if (gcStatus.escalationNeeded) {
|
|
34021
34079
|
process.stdout.write(
|
|
34022
34080
|
`
|
|
34023
34081
|
WARNING: Disk threshold breached. Run 'cleo gc run' to reclaim space.
|
|
34024
34082
|
`
|
|
34025
34083
|
);
|
|
34026
34084
|
}
|
|
34085
|
+
process.stdout.write(`
|
|
34086
|
+
Hygiene Loop (cross-project):
|
|
34087
|
+
`);
|
|
34088
|
+
process.stdout.write(` Last run: ${hygieneLastRunAt ?? "never"}
|
|
34089
|
+
`);
|
|
34090
|
+
process.stdout.write(` Summary: ${hygieneSummary ?? "not yet run"}
|
|
34091
|
+
`);
|
|
34092
|
+
if (hygieneStats.projectsChecked > 0) {
|
|
34093
|
+
process.stdout.write(
|
|
34094
|
+
` Projects: ${hygieneStats.projectsHealthy}/${hygieneStats.projectsChecked} healthy
|
|
34095
|
+
`
|
|
34096
|
+
);
|
|
34097
|
+
if (hygieneStats.tempGcCandidates > 0) {
|
|
34098
|
+
process.stdout.write(
|
|
34099
|
+
` Temp GC: ${hygieneStats.tempGcCandidates} candidate(s) pending approval
|
|
34100
|
+
`
|
|
34101
|
+
);
|
|
34102
|
+
}
|
|
34103
|
+
if (hygieneStats.duplicateEpicGroups > 0) {
|
|
34104
|
+
process.stdout.write(
|
|
34105
|
+
` Duplicate epics: ${hygieneStats.duplicateEpicGroups} group(s) detected
|
|
34106
|
+
`
|
|
34107
|
+
);
|
|
34108
|
+
}
|
|
34109
|
+
if (hygieneStats.worktreesPruned > 0) {
|
|
34110
|
+
process.stdout.write(
|
|
34111
|
+
` Worktrees: ${hygieneStats.worktreesPruned} stale worktree(s) pruned
|
|
34112
|
+
`
|
|
34113
|
+
);
|
|
34114
|
+
}
|
|
34115
|
+
}
|
|
34027
34116
|
}
|
|
34028
34117
|
} catch (err) {
|
|
34029
34118
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -34038,6 +34127,11 @@ WARNING: Disk threshold breached. Run 'cleo gc run' to reclaim space.
|
|
|
34038
34127
|
process.exit(1);
|
|
34039
34128
|
}
|
|
34040
34129
|
}
|
|
34130
|
+
function resolveDaemonInstallerScript() {
|
|
34131
|
+
const __filename = fileURLToPath3(import.meta.url);
|
|
34132
|
+
const pkgRoot = join9(__filename, "..", "..", "..", "..");
|
|
34133
|
+
return join9(pkgRoot, "scripts", "install-daemon-service.mjs");
|
|
34134
|
+
}
|
|
34041
34135
|
var startCommand3 = defineCommand({
|
|
34042
34136
|
meta: { name: "start", description: "Spawn the GC daemon as a detached background process" },
|
|
34043
34137
|
args: {
|
|
@@ -34045,6 +34139,10 @@ var startCommand3 = defineCommand({
|
|
|
34045
34139
|
type: "string",
|
|
34046
34140
|
description: "Override .cleo/ directory path"
|
|
34047
34141
|
},
|
|
34142
|
+
foreground: {
|
|
34143
|
+
type: "boolean",
|
|
34144
|
+
description: "Run the sentient daemon in the foreground (used by systemd/launchd service units)"
|
|
34145
|
+
},
|
|
34048
34146
|
json: {
|
|
34049
34147
|
type: "boolean",
|
|
34050
34148
|
description: "Output result as JSON"
|
|
@@ -34053,6 +34151,16 @@ var startCommand3 = defineCommand({
|
|
|
34053
34151
|
async run({ args }) {
|
|
34054
34152
|
const cleoDir = args["cleo-dir"] ?? join9(homedir2(), ".cleo");
|
|
34055
34153
|
const jsonMode = args.json ?? false;
|
|
34154
|
+
const foreground = args.foreground ?? false;
|
|
34155
|
+
if (foreground) {
|
|
34156
|
+
const projectRoot = process.cwd();
|
|
34157
|
+
process.stdout.write(
|
|
34158
|
+
`[CLEO DAEMON] Starting sentient daemon in foreground mode (PID ${process.pid})
|
|
34159
|
+
`
|
|
34160
|
+
);
|
|
34161
|
+
await bootstrapSentientDaemon(projectRoot);
|
|
34162
|
+
return;
|
|
34163
|
+
}
|
|
34056
34164
|
try {
|
|
34057
34165
|
const status = await getGCDaemonStatus(cleoDir);
|
|
34058
34166
|
if (status.running && status.pid) {
|
|
@@ -34144,7 +34252,7 @@ var stopCommand3 = defineCommand({
|
|
|
34144
34252
|
var statusCommand4 = defineCommand({
|
|
34145
34253
|
meta: {
|
|
34146
34254
|
name: "status",
|
|
34147
|
-
description: "Show daemon running state, PID, last GC run, and
|
|
34255
|
+
description: "Show daemon running state, PID, last GC run, disk usage, and cross-project hygiene summary"
|
|
34148
34256
|
},
|
|
34149
34257
|
args: {
|
|
34150
34258
|
"cleo-dir": {
|
|
@@ -34158,7 +34266,87 @@ var statusCommand4 = defineCommand({
|
|
|
34158
34266
|
},
|
|
34159
34267
|
async run({ args }) {
|
|
34160
34268
|
const cleoDir = args["cleo-dir"] ?? join9(homedir2(), ".cleo");
|
|
34161
|
-
await showDaemonStatus(cleoDir, args.json ?? false);
|
|
34269
|
+
await showDaemonStatus(cleoDir, process.cwd(), args.json ?? false);
|
|
34270
|
+
}
|
|
34271
|
+
});
|
|
34272
|
+
var installCommand2 = defineCommand({
|
|
34273
|
+
meta: {
|
|
34274
|
+
name: "install",
|
|
34275
|
+
description: "Register the CLEO daemon as a user-level system service (systemd / launchd)"
|
|
34276
|
+
},
|
|
34277
|
+
args: {
|
|
34278
|
+
json: {
|
|
34279
|
+
type: "boolean",
|
|
34280
|
+
description: "Output result as JSON"
|
|
34281
|
+
}
|
|
34282
|
+
},
|
|
34283
|
+
async run({ args }) {
|
|
34284
|
+
const jsonMode = args.json ?? false;
|
|
34285
|
+
try {
|
|
34286
|
+
const scriptPath = resolveDaemonInstallerScript();
|
|
34287
|
+
const { installDaemonService } = await import(scriptPath);
|
|
34288
|
+
await installDaemonService();
|
|
34289
|
+
const result = {
|
|
34290
|
+
success: true,
|
|
34291
|
+
data: {
|
|
34292
|
+
platform: process.platform,
|
|
34293
|
+
message: "Daemon service installation complete."
|
|
34294
|
+
}
|
|
34295
|
+
};
|
|
34296
|
+
if (jsonMode) {
|
|
34297
|
+
process.stdout.write(JSON.stringify(result) + "\n");
|
|
34298
|
+
} else {
|
|
34299
|
+
process.stdout.write("CLEO: Daemon service installation complete.\n");
|
|
34300
|
+
}
|
|
34301
|
+
} catch (err) {
|
|
34302
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
34303
|
+
const result = { success: false, error: { code: "E_INTERNAL", message } };
|
|
34304
|
+
if (jsonMode) {
|
|
34305
|
+
process.stdout.write(JSON.stringify(result) + "\n");
|
|
34306
|
+
} else {
|
|
34307
|
+
process.stderr.write(`Error installing daemon service: ${message}
|
|
34308
|
+
`);
|
|
34309
|
+
}
|
|
34310
|
+
process.exit(1);
|
|
34311
|
+
}
|
|
34312
|
+
}
|
|
34313
|
+
});
|
|
34314
|
+
var uninstallCommand = defineCommand({
|
|
34315
|
+
meta: {
|
|
34316
|
+
name: "uninstall",
|
|
34317
|
+
description: "Disable and remove the user-level system service (systemd unit / launchd plist)"
|
|
34318
|
+
},
|
|
34319
|
+
args: {
|
|
34320
|
+
json: {
|
|
34321
|
+
type: "boolean",
|
|
34322
|
+
description: "Output result as JSON"
|
|
34323
|
+
}
|
|
34324
|
+
},
|
|
34325
|
+
async run({ args }) {
|
|
34326
|
+
const jsonMode = args.json ?? false;
|
|
34327
|
+
try {
|
|
34328
|
+
const scriptPath = resolveDaemonInstallerScript();
|
|
34329
|
+
const { uninstallDaemonService } = await import(scriptPath);
|
|
34330
|
+
const result = await uninstallDaemonService();
|
|
34331
|
+
const envelope = { success: result.success, data: result };
|
|
34332
|
+
if (jsonMode) {
|
|
34333
|
+
process.stdout.write(JSON.stringify(envelope) + "\n");
|
|
34334
|
+
} else {
|
|
34335
|
+
process.stdout.write(`CLEO: ${result.message}
|
|
34336
|
+
`);
|
|
34337
|
+
}
|
|
34338
|
+
if (!result.success) process.exit(1);
|
|
34339
|
+
} catch (err) {
|
|
34340
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
34341
|
+
const result = { success: false, error: { code: "E_INTERNAL", message } };
|
|
34342
|
+
if (jsonMode) {
|
|
34343
|
+
process.stdout.write(JSON.stringify(result) + "\n");
|
|
34344
|
+
} else {
|
|
34345
|
+
process.stderr.write(`Error uninstalling daemon service: ${message}
|
|
34346
|
+
`);
|
|
34347
|
+
}
|
|
34348
|
+
process.exit(1);
|
|
34349
|
+
}
|
|
34162
34350
|
}
|
|
34163
34351
|
});
|
|
34164
34352
|
var daemonCommand = defineCommand({
|
|
@@ -34179,12 +34367,14 @@ var daemonCommand = defineCommand({
|
|
|
34179
34367
|
subCommands: {
|
|
34180
34368
|
start: startCommand3,
|
|
34181
34369
|
stop: stopCommand3,
|
|
34182
|
-
status: statusCommand4
|
|
34370
|
+
status: statusCommand4,
|
|
34371
|
+
install: installCommand2,
|
|
34372
|
+
uninstall: uninstallCommand
|
|
34183
34373
|
},
|
|
34184
34374
|
async run({ args, cmd, rawArgs }) {
|
|
34185
34375
|
if (isSubCommandDispatch(rawArgs, cmd.subCommands)) return;
|
|
34186
34376
|
const cleoDir = args["cleo-dir"] ?? join9(homedir2(), ".cleo");
|
|
34187
|
-
await showDaemonStatus(cleoDir, args.json ?? false);
|
|
34377
|
+
await showDaemonStatus(cleoDir, process.cwd(), args.json ?? false);
|
|
34188
34378
|
}
|
|
34189
34379
|
});
|
|
34190
34380
|
|
|
@@ -34199,6 +34389,10 @@ var dashCommand = defineCommand({
|
|
|
34199
34389
|
"blocked-limit": {
|
|
34200
34390
|
type: "string",
|
|
34201
34391
|
description: "Max blocked tasks to show"
|
|
34392
|
+
},
|
|
34393
|
+
"no-hygiene": {
|
|
34394
|
+
type: "boolean",
|
|
34395
|
+
description: "Suppress the hygiene section note"
|
|
34202
34396
|
}
|
|
34203
34397
|
},
|
|
34204
34398
|
async run({ args }) {
|
|
@@ -34211,6 +34405,11 @@ var dashCommand = defineCommand({
|
|
|
34211
34405
|
},
|
|
34212
34406
|
{ command: "dash" }
|
|
34213
34407
|
);
|
|
34408
|
+
if (!args["no-hygiene"]) {
|
|
34409
|
+
process.stdout.write(
|
|
34410
|
+
"\n--- Sentient Hygiene (T1636) ---\nBackground scan runs every 4h (dream cycle). Run `cleo memory digest --hygiene` to see the latest hygiene observations (orphan tasks, top-level tasks without an epic, content defects, premature-close leaks).\n"
|
|
34411
|
+
);
|
|
34412
|
+
}
|
|
34214
34413
|
}
|
|
34215
34414
|
});
|
|
34216
34415
|
|
|
@@ -40266,21 +40465,49 @@ var backfillCommand3 = defineCommand({
|
|
|
40266
40465
|
await showUsage(cmd);
|
|
40267
40466
|
}
|
|
40268
40467
|
});
|
|
40269
|
-
var digestCommand =
|
|
40270
|
-
|
|
40271
|
-
|
|
40468
|
+
var digestCommand = defineCommand({
|
|
40469
|
+
meta: {
|
|
40470
|
+
name: "digest",
|
|
40471
|
+
description: "Summarized top-N brain observations for session briefing (T1006). Pass --hygiene to show latest hygiene scan results from the sentient background loop (T1636)."
|
|
40472
|
+
},
|
|
40272
40473
|
args: {
|
|
40273
40474
|
limit: {
|
|
40274
40475
|
type: "string",
|
|
40275
40476
|
description: "Maximum number of observations to include (default: 10)."
|
|
40477
|
+
},
|
|
40478
|
+
hygiene: {
|
|
40479
|
+
type: "boolean",
|
|
40480
|
+
description: "Show only hygiene observations (hygiene:orphan, hygiene:top-level-orphan, hygiene:content-defect, hygiene:premature-close-leak) from the sentient background loop (T1636)."
|
|
40481
|
+
},
|
|
40482
|
+
json: {
|
|
40483
|
+
type: "boolean",
|
|
40484
|
+
description: "Output as JSON"
|
|
40276
40485
|
}
|
|
40277
40486
|
},
|
|
40278
|
-
|
|
40279
|
-
|
|
40280
|
-
|
|
40281
|
-
|
|
40282
|
-
|
|
40283
|
-
|
|
40487
|
+
async run({ args }) {
|
|
40488
|
+
if (args.hygiene) {
|
|
40489
|
+
await dispatchFromCli(
|
|
40490
|
+
"query",
|
|
40491
|
+
"memory",
|
|
40492
|
+
"find",
|
|
40493
|
+
{
|
|
40494
|
+
query: "hygiene:",
|
|
40495
|
+
limit: args.limit !== void 0 ? parseInt(args.limit, 10) : 20
|
|
40496
|
+
},
|
|
40497
|
+
{ command: "memory-hygiene-digest", operation: "memory.find" }
|
|
40498
|
+
);
|
|
40499
|
+
} else {
|
|
40500
|
+
await dispatchFromCli(
|
|
40501
|
+
"query",
|
|
40502
|
+
"memory",
|
|
40503
|
+
"digest",
|
|
40504
|
+
{
|
|
40505
|
+
...args["limit"] !== void 0 && { limit: parseInt(args["limit"], 10) }
|
|
40506
|
+
},
|
|
40507
|
+
{ command: "memory-digest", operation: "memory.digest" }
|
|
40508
|
+
);
|
|
40509
|
+
}
|
|
40510
|
+
}
|
|
40284
40511
|
});
|
|
40285
40512
|
var recentCommand = makeMemorySubcommand({
|
|
40286
40513
|
name: "recent",
|
|
@@ -48696,7 +48923,7 @@ async function runPostUpdateDiagnostics(opts) {
|
|
|
48696
48923
|
import { join as join16 } from "node:path";
|
|
48697
48924
|
import { cwd as processCwd } from "node:process";
|
|
48698
48925
|
import {
|
|
48699
|
-
getSentientDaemonStatus,
|
|
48926
|
+
getSentientDaemonStatus as getSentientDaemonStatus2,
|
|
48700
48927
|
resumeSentientDaemon,
|
|
48701
48928
|
SENTIENT_STATE_FILE,
|
|
48702
48929
|
spawnSentientDaemon,
|
|
@@ -48754,7 +48981,7 @@ var startSub = defineCommand({
|
|
|
48754
48981
|
const jsonMode = args.json === true;
|
|
48755
48982
|
const dryRun = args["dry-run"] === true;
|
|
48756
48983
|
try {
|
|
48757
|
-
const existing = await
|
|
48984
|
+
const existing = await getSentientDaemonStatus2(projectRoot);
|
|
48758
48985
|
if (existing.running && existing.pid) {
|
|
48759
48986
|
emitSuccess(
|
|
48760
48987
|
{ running: true, pid: existing.pid, message: "daemon already running" },
|
|
@@ -48822,7 +49049,7 @@ var statusSub = defineCommand({
|
|
|
48822
49049
|
const projectRoot = resolveProjectRoot4(args.project);
|
|
48823
49050
|
const jsonMode = args.json === true;
|
|
48824
49051
|
try {
|
|
48825
|
-
const status = await
|
|
49052
|
+
const status = await getSentientDaemonStatus2(projectRoot);
|
|
48826
49053
|
if (jsonMode) {
|
|
48827
49054
|
process.stdout.write(`${JSON.stringify({ success: true, data: status })}
|
|
48828
49055
|
`);
|
|
@@ -49334,7 +49561,7 @@ var sentientCommand = defineCommand({
|
|
|
49334
49561
|
const projectRoot = resolveProjectRoot4(args.project);
|
|
49335
49562
|
const jsonMode = args.json === true;
|
|
49336
49563
|
try {
|
|
49337
|
-
const status = await
|
|
49564
|
+
const status = await getSentientDaemonStatus2(projectRoot);
|
|
49338
49565
|
if (jsonMode) {
|
|
49339
49566
|
process.stdout.write(`${JSON.stringify({ success: true, data: status })}
|
|
49340
49567
|
`);
|
|
@@ -50121,7 +50348,7 @@ var infoCommand = defineCommand({
|
|
|
50121
50348
|
);
|
|
50122
50349
|
}
|
|
50123
50350
|
});
|
|
50124
|
-
var
|
|
50351
|
+
var installCommand3 = defineCommand({
|
|
50125
50352
|
meta: { name: "install", description: "Install skill to agent directory" },
|
|
50126
50353
|
args: {
|
|
50127
50354
|
"skill-name": {
|
|
@@ -50147,7 +50374,7 @@ var installCommand2 = defineCommand({
|
|
|
50147
50374
|
);
|
|
50148
50375
|
}
|
|
50149
50376
|
});
|
|
50150
|
-
var
|
|
50377
|
+
var uninstallCommand2 = defineCommand({
|
|
50151
50378
|
meta: { name: "uninstall", description: "Uninstall a skill" },
|
|
50152
50379
|
args: {
|
|
50153
50380
|
"skill-name": {
|
|
@@ -50348,8 +50575,8 @@ var skillsCommand2 = defineCommand({
|
|
|
50348
50575
|
search: searchCommand3,
|
|
50349
50576
|
validate: validateCommand7,
|
|
50350
50577
|
info: infoCommand,
|
|
50351
|
-
install:
|
|
50352
|
-
uninstall:
|
|
50578
|
+
install: installCommand3,
|
|
50579
|
+
uninstall: uninstallCommand2,
|
|
50353
50580
|
enable: enableCommand2,
|
|
50354
50581
|
disable: disableCommand2,
|
|
50355
50582
|
refresh: refreshCommand,
|
|
@@ -52516,7 +52743,7 @@ Or via NodeSource: https://github.com/nodesource/distributions
|
|
|
52516
52743
|
}
|
|
52517
52744
|
}
|
|
52518
52745
|
function getPackageVersion() {
|
|
52519
|
-
const pkgPath = join19(dirname9(
|
|
52746
|
+
const pkgPath = join19(dirname9(fileURLToPath4(import.meta.url)), "../../package.json");
|
|
52520
52747
|
const pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
|
|
52521
52748
|
return pkg.version;
|
|
52522
52749
|
}
|