@ouro.bot/cli 0.1.0-alpha.724 → 0.1.0-alpha.725
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/changelog.json +12 -0
- package/dist/heart/active-work.js +10 -3
- package/dist/heart/core.js +343 -77
- package/dist/heart/daemon/cli-exec.js +72 -14
- package/dist/heart/daemon/cli-help.js +13 -2
- package/dist/heart/daemon/cli-parse.js +82 -1
- package/dist/heart/daemon/daemon.js +286 -33
- package/dist/heart/daemon/doctor.js +21 -6
- package/dist/heart/daemon/habit-private-wake.js +6 -1
- package/dist/heart/habits/habit-cancel.js +810 -0
- package/dist/heart/habits/habit-lifecycle.js +1327 -0
- package/dist/heart/habits/habit-migration.js +28 -23
- package/dist/heart/habits/habit-parser.js +72 -8
- package/dist/heart/habits/habit-runtime-state.js +3 -24
- package/dist/heart/habits/habit-scheduler.js +268 -50
- package/dist/heart/habits/habit-session.js +16 -0
- package/dist/heart/hatch/hatch-flow.js +6 -4
- package/dist/heart/mailbox/readers/runtime-readers.js +26 -27
- package/dist/heart/orientation-frame.js +58 -1
- package/dist/heart/provider-attempt.js +4 -1
- package/dist/heart/providers/anthropic.js +23 -2
- package/dist/heart/start-of-turn-packet.js +14 -11
- package/dist/heart/streaming.js +565 -185
- package/dist/mind/obligation-steering.js +15 -9
- package/dist/mind/prompt.js +58 -26
- package/dist/nerves/coverage/run-artifacts.js +55 -35
- package/dist/nerves/review/cli.js +2 -2
- package/dist/nerves/review/core.js +14 -7
- package/dist/repertoire/tools-base.js +2 -0
- package/dist/repertoire/tools-habits.js +103 -0
- package/dist/repertoire/tools.js +18 -3
- package/dist/rsvp/cli.js +126 -20
- package/dist/rsvp/diagnostics.js +12 -2
- package/dist/rsvp/habit-policy.js +7 -0
- package/dist/rsvp/habit-stage.js +19 -4
- package/dist/rsvp/native-habit-runner.js +151 -11
- package/dist/rsvp/outbound-state.js +360 -0
- package/dist/senses/bluebubbles/client.js +90 -17
- package/dist/senses/bluebubbles/inbound-log.js +1 -0
- package/dist/senses/bluebubbles/index.js +662 -425
- package/dist/senses/bluebubbles/model.js +57 -13
- package/dist/senses/bluebubbles/mutation-log.js +21 -10
- package/dist/senses/bluebubbles/reaction-policy.js +55 -0
- package/dist/senses/bluebubbles/semantic-receipts.js +1818 -0
- package/dist/senses/cli/tui-store.js +1 -0
- package/dist/senses/cli.js +1 -0
- package/dist/senses/habit-lifecycle-guard.js +24 -0
- package/dist/senses/ingress-evidence.js +2 -0
- package/dist/senses/pipeline.js +90 -24
- package/dist/senses/private-runtime-worker.js +21 -20
- package/dist/senses/private-runtime.js +79 -29
- package/dist/senses/shared-turn.js +1 -0
- package/dist/senses/teams.js +1 -0
- package/package.json +6 -1
|
@@ -1444,8 +1444,41 @@ async function checkManualCloneBundles(deps) {
|
|
|
1444
1444
|
}
|
|
1445
1445
|
// ── toDaemonCommand ──
|
|
1446
1446
|
function toDaemonCommand(command) {
|
|
1447
|
+
if (command.kind === "habit.probe") {
|
|
1448
|
+
return {
|
|
1449
|
+
kind: "habit.probe",
|
|
1450
|
+
agent: command.agent,
|
|
1451
|
+
habitName: command.habitName,
|
|
1452
|
+
noSend: true,
|
|
1453
|
+
};
|
|
1454
|
+
}
|
|
1447
1455
|
return command;
|
|
1448
1456
|
}
|
|
1457
|
+
function habitProbeJsonResponse(response) {
|
|
1458
|
+
const data = response.data && typeof response.data === "object" && !Array.isArray(response.data)
|
|
1459
|
+
? response.data
|
|
1460
|
+
: null;
|
|
1461
|
+
const status = typeof data?.status === "string" ? data.status : "degraded";
|
|
1462
|
+
if (response.ok
|
|
1463
|
+
&& data?.noSend === true
|
|
1464
|
+
&& typeof data.transportInvocationCount === "number"
|
|
1465
|
+
&& data.transportInvocationCount === 0) {
|
|
1466
|
+
return JSON.stringify({
|
|
1467
|
+
noSend: true,
|
|
1468
|
+
status,
|
|
1469
|
+
transportInvocationCount: 0,
|
|
1470
|
+
}, null, 2);
|
|
1471
|
+
}
|
|
1472
|
+
return JSON.stringify({
|
|
1473
|
+
ok: false,
|
|
1474
|
+
noSend: true,
|
|
1475
|
+
status,
|
|
1476
|
+
transportInvocationCount: null,
|
|
1477
|
+
error: response.error
|
|
1478
|
+
?? (!response.ok ? response.message : undefined)
|
|
1479
|
+
?? "habit probe did not produce verified zero-transport evidence",
|
|
1480
|
+
}, null, 2);
|
|
1481
|
+
}
|
|
1449
1482
|
// ── Hatch input resolution ──
|
|
1450
1483
|
async function resolveHatchInput(command, deps) {
|
|
1451
1484
|
const prompt = deps.promptInput;
|
|
@@ -7218,8 +7251,9 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
7218
7251
|
return result.summary;
|
|
7219
7252
|
}
|
|
7220
7253
|
// ── habit subcommands (local, no daemon socket needed) ──
|
|
7221
|
-
if (command.kind === "habit.list" || command.kind === "habit.create" || command.kind === "habit.runs" || command.kind === "habit.inspect" || command.kind === "habit.summary") {
|
|
7222
|
-
const { parseHabitFile, renderHabitFile } = await Promise.resolve().then(() => __importStar(require("../habits/habit-parser")));
|
|
7254
|
+
if (command.kind === "habit.list" || command.kind === "habit.create" || command.kind === "habit.runs" || command.kind === "habit.inspect" || command.kind === "habit.summary" || command.kind === "habit.cancel") {
|
|
7255
|
+
const { createDegradedHabitFile, parseHabitFile, renderHabitFile } = await Promise.resolve().then(() => __importStar(require("../habits/habit-parser")));
|
|
7256
|
+
const { publishNewHabitDefinition } = await Promise.resolve().then(() => __importStar(require("../habits/habit-lifecycle")));
|
|
7223
7257
|
const { applyHabitRuntimeState } = await Promise.resolve().then(() => __importStar(require("../habits/habit-runtime-state")));
|
|
7224
7258
|
const { listHabitRunReceipts, readHabitRunReceipt } = await Promise.resolve().then(() => __importStar(require("../../arc/flight-recorder")));
|
|
7225
7259
|
const { readHabitSessionSummary } = await Promise.resolve().then(() => __importStar(require("../habits/habit-session-summary")));
|
|
@@ -7227,10 +7261,21 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
7227
7261
|
const bundleRoot = deps.agentBundleRoot ?? path.join(deps.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)(), `${command.agent}.ouro`);
|
|
7228
7262
|
/* v8 ignore stop */
|
|
7229
7263
|
const habitsDir = path.join(bundleRoot, "habits");
|
|
7264
|
+
if (command.kind === "habit.cancel") {
|
|
7265
|
+
const { cancelHabit } = await Promise.resolve().then(() => __importStar(require("../habits/habit-cancel")));
|
|
7266
|
+
const receipt = await cancelHabit({
|
|
7267
|
+
agentRoot: bundleRoot,
|
|
7268
|
+
habitId: command.habitName,
|
|
7269
|
+
evidenceLocator: command.evidenceLocator,
|
|
7270
|
+
authority: { kind: "offline_bridge" },
|
|
7271
|
+
}, deps.habitCancelDeps);
|
|
7272
|
+
deps.writeStdout(receipt.acknowledgement);
|
|
7273
|
+
return receipt.acknowledgement;
|
|
7274
|
+
}
|
|
7230
7275
|
if (command.kind === "habit.list") {
|
|
7231
7276
|
let files;
|
|
7232
7277
|
try {
|
|
7233
|
-
files = fs.readdirSync(habitsDir).filter((f) => f.endsWith(".md") && f !== "README.md");
|
|
7278
|
+
files = fs.readdirSync(habitsDir).filter((f) => f.endsWith(".md") && f !== "README.md").sort();
|
|
7234
7279
|
}
|
|
7235
7280
|
catch {
|
|
7236
7281
|
const message = "no habits found";
|
|
@@ -7244,10 +7289,18 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
7244
7289
|
}
|
|
7245
7290
|
const lines = [];
|
|
7246
7291
|
for (const file of files) {
|
|
7247
|
-
const
|
|
7248
|
-
|
|
7292
|
+
const filePath = path.join(habitsDir, file);
|
|
7293
|
+
let habit;
|
|
7294
|
+
try {
|
|
7295
|
+
const fileContent = fs.readFileSync(filePath, "utf-8");
|
|
7296
|
+
habit = applyHabitRuntimeState(bundleRoot, parseHabitFile(fileContent, filePath));
|
|
7297
|
+
}
|
|
7298
|
+
catch (error) {
|
|
7299
|
+
habit = createDegradedHabitFile(filePath, "read_error", "", error instanceof Error ? error.message : String(error));
|
|
7300
|
+
}
|
|
7249
7301
|
const lastRunStr = habit.lastRun ?? "never";
|
|
7250
|
-
|
|
7302
|
+
const degradedReason = habit.status === "degraded" ? ` degradedReason=${habit.degradedReason}` : "";
|
|
7303
|
+
lines.push(`${habit.name} cadence=${habit.cadence ?? "none"} status=${habit.status}${degradedReason} lastRun=${lastRunStr}`);
|
|
7251
7304
|
}
|
|
7252
7305
|
const message = lines.join("\n");
|
|
7253
7306
|
deps.writeStdout(message);
|
|
@@ -7331,12 +7384,6 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
7331
7384
|
}
|
|
7332
7385
|
// habit.create
|
|
7333
7386
|
const filePath = path.join(habitsDir, `${command.name}.md`);
|
|
7334
|
-
if (fs.existsSync(filePath)) {
|
|
7335
|
-
const message = `error: habit '${command.name}' already exists`;
|
|
7336
|
-
deps.writeStdout(message);
|
|
7337
|
-
return message;
|
|
7338
|
-
}
|
|
7339
|
-
fs.mkdirSync(habitsDir, { recursive: true });
|
|
7340
7387
|
const now = new Date().toISOString();
|
|
7341
7388
|
const habitContent = renderHabitFile({
|
|
7342
7389
|
title: command.name,
|
|
@@ -7344,7 +7391,16 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
7344
7391
|
status: "active",
|
|
7345
7392
|
created: now,
|
|
7346
7393
|
}, `Habit: ${command.name}`);
|
|
7347
|
-
|
|
7394
|
+
const publication = publishNewHabitDefinition({
|
|
7395
|
+
agentRoot: bundleRoot,
|
|
7396
|
+
habitId: command.name,
|
|
7397
|
+
bytes: habitContent,
|
|
7398
|
+
});
|
|
7399
|
+
if (publication === "exists") {
|
|
7400
|
+
const message = `error: habit '${command.name}' already exists`;
|
|
7401
|
+
deps.writeStdout(message);
|
|
7402
|
+
return message;
|
|
7403
|
+
}
|
|
7348
7404
|
const message = `created: ${filePath}`;
|
|
7349
7405
|
deps.writeStdout(message);
|
|
7350
7406
|
return message;
|
|
@@ -8317,7 +8373,9 @@ async function runOuroCli(args, deps = (0, cli_defaults_1.createDefaultOuroCliDe
|
|
|
8317
8373
|
? command.json
|
|
8318
8374
|
? formatDaemonStatusJsonOutput(response)
|
|
8319
8375
|
: (0, cli_render_1.formatDaemonStatusOutput)(response, fallbackMessage)
|
|
8320
|
-
:
|
|
8376
|
+
: command.kind === "habit.probe" && command.json
|
|
8377
|
+
? habitProbeJsonResponse(response)
|
|
8378
|
+
: fallbackMessage;
|
|
8321
8379
|
deps.writeStdout(message);
|
|
8322
8380
|
return message;
|
|
8323
8381
|
}
|
|
@@ -10,6 +10,7 @@ exports.levenshteinDistance = levenshteinDistance;
|
|
|
10
10
|
exports.suggestCommand = suggestCommand;
|
|
11
11
|
exports.getGroupedHelp = getGroupedHelp;
|
|
12
12
|
exports.getCommandHelp = getCommandHelp;
|
|
13
|
+
const core_1 = require("../../nerves/review/core");
|
|
13
14
|
// ── Registry ──
|
|
14
15
|
exports.COMMAND_REGISTRY = {
|
|
15
16
|
up: {
|
|
@@ -142,7 +143,7 @@ exports.COMMAND_REGISTRY = {
|
|
|
142
143
|
description: "Manage agent habits",
|
|
143
144
|
usage: "ouro habit <subcommand> [--agent <name>]",
|
|
144
145
|
example: "ouro habit list",
|
|
145
|
-
subcommands: ["list", "create", "runs", "inspect", "summary", "poke"],
|
|
146
|
+
subcommands: ["list", "create", "runs", "inspect", "summary", "poke", "cancel", "probe"],
|
|
146
147
|
},
|
|
147
148
|
rsvp: {
|
|
148
149
|
category: "Habits",
|
|
@@ -186,7 +187,7 @@ exports.COMMAND_REGISTRY = {
|
|
|
186
187
|
},
|
|
187
188
|
"nerves-review": {
|
|
188
189
|
category: "Internal",
|
|
189
|
-
description:
|
|
190
|
+
description: `Read-only review of recent nerves events from one agent log stream (default: ${core_1.DEFAULT_NERVES_PROCESS})`,
|
|
190
191
|
usage: "ouro nerves-review [--agent <name>] [--process <name>] [--component <substr>] [--event <substr>] [--level <level>] [--since <duration>] [--limit <n>] [--json]",
|
|
191
192
|
example: "ouro nerves-review --agent slugger --component daemon --event habit --since 30m --json",
|
|
192
193
|
},
|
|
@@ -368,6 +369,16 @@ exports.COMMAND_REGISTRY = {
|
|
|
368
369
|
},
|
|
369
370
|
};
|
|
370
371
|
const SUBCOMMAND_HELP = {
|
|
372
|
+
"habit probe": {
|
|
373
|
+
description: "Probe one habit through its real dispatch path with an irrevocable no-send boundary; it cannot send and reports zero transport invocations",
|
|
374
|
+
usage: "ouro habit probe --agent <name> --habit <name> --no-send [--json]",
|
|
375
|
+
example: "ouro habit probe --agent slugger --habit report-name --no-send --json",
|
|
376
|
+
},
|
|
377
|
+
"habit cancel": {
|
|
378
|
+
description: "Cancel a habit offline from a previously verified evidence bridge",
|
|
379
|
+
usage: "ouro habit cancel --agent <name> --habit <name> --evidence <bridge-id>",
|
|
380
|
+
example: "ouro habit cancel --agent slugger --habit report-name --evidence pre-v1-bluebubbles-event-id",
|
|
381
|
+
},
|
|
371
382
|
"private decisions": {
|
|
372
383
|
description: "Read recent private-runtime allow/deny decisions from the policy ledger",
|
|
373
384
|
usage: "ouro private decisions [--agent <name>] [--limit <n>] [--json]",
|
|
@@ -18,6 +18,7 @@ const friends_1 = require("@ouro.bot/friends");
|
|
|
18
18
|
const cli_help_1 = require("./cli-help");
|
|
19
19
|
const cli_desk_1 = require("./cli-desk");
|
|
20
20
|
const flight_recorder_1 = require("../../arc/flight-recorder");
|
|
21
|
+
const core_1 = require("../../nerves/review/core");
|
|
21
22
|
const vault_items_1 = require("./vault-items");
|
|
22
23
|
// ── Shared helpers ──
|
|
23
24
|
function extractAgentFlag(args) {
|
|
@@ -112,6 +113,8 @@ function usage() {
|
|
|
112
113
|
" ouro habit runs [--agent <name>] [--limit <n>]",
|
|
113
114
|
" ouro habit inspect [--agent <name>] <runId>",
|
|
114
115
|
" ouro habit summary [--agent <name>] (--run-id <id>|--habit <name>|--operation-id <id>) [--which latest|previous|latest-success|latest-failure] [--json]",
|
|
116
|
+
" ouro habit cancel --agent <name> --habit <name> --evidence <bridge-id>",
|
|
117
|
+
" ouro habit probe --agent <name> --habit <name> --no-send [--json]",
|
|
115
118
|
" ouro link <agent> --friend <id> --provider <provider> --external-id <external-id>",
|
|
116
119
|
" ouro bluebubbles replay [--agent <name>] --message-guid <guid> [--event-type new-message|updated-message] [--json]",
|
|
117
120
|
" ouro bluebubbles context-smoke [--agent <name>] --message-guid <guid> [--persist] [--json]",
|
|
@@ -314,6 +317,84 @@ function parsePokeCommand(args) {
|
|
|
314
317
|
function parseHabitCommand(args) {
|
|
315
318
|
const { agent, rest } = extractAgentFlag(args);
|
|
316
319
|
const sub = rest[0];
|
|
320
|
+
if (sub === "probe") {
|
|
321
|
+
if (args.includes("--allow-send")) {
|
|
322
|
+
throw new Error("habit probe cannot allow send");
|
|
323
|
+
}
|
|
324
|
+
if (args.filter((value) => value === "--agent").length !== 1
|
|
325
|
+
|| !agent
|
|
326
|
+
|| !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(agent))
|
|
327
|
+
throw new Error("habit probe requires --agent <name>");
|
|
328
|
+
let habitName;
|
|
329
|
+
let json = false;
|
|
330
|
+
let sawNoSend = false;
|
|
331
|
+
const options = rest.slice(1);
|
|
332
|
+
for (let index = 0; index < options.length; index += 1) {
|
|
333
|
+
const option = options[index];
|
|
334
|
+
if (option === "--json") {
|
|
335
|
+
if (json)
|
|
336
|
+
throw new Error("habit probe received duplicate --json");
|
|
337
|
+
json = true;
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
if (option === "--no-send") {
|
|
341
|
+
if (sawNoSend)
|
|
342
|
+
throw new Error("habit probe received duplicate --no-send");
|
|
343
|
+
sawNoSend = true;
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
if (option === "--habit" && options[index + 1]) {
|
|
347
|
+
if (habitName !== undefined)
|
|
348
|
+
throw new Error("habit probe received duplicate --habit");
|
|
349
|
+
habitName = options[index + 1];
|
|
350
|
+
index += 1;
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
throw new Error("Usage: ouro habit probe --agent <name> --habit <name> --no-send [--json]");
|
|
354
|
+
}
|
|
355
|
+
if (!habitName)
|
|
356
|
+
throw new Error("habit probe requires --habit <name>");
|
|
357
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(habitName)) {
|
|
358
|
+
throw new Error("habit probe requires a valid --habit name");
|
|
359
|
+
}
|
|
360
|
+
return { kind: "habit.probe", agent, habitName, noSend: true, json };
|
|
361
|
+
}
|
|
362
|
+
if (sub === "cancel") {
|
|
363
|
+
if (args.filter((value) => value === "--agent").length !== 1
|
|
364
|
+
|| !agent
|
|
365
|
+
|| !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(agent)) {
|
|
366
|
+
throw new Error(`Usage\n${usage()}`);
|
|
367
|
+
}
|
|
368
|
+
let habitName;
|
|
369
|
+
let evidenceLocator;
|
|
370
|
+
const options = rest.slice(1);
|
|
371
|
+
for (let index = 0; index < options.length; index += 1) {
|
|
372
|
+
const option = options[index];
|
|
373
|
+
const value = options[index + 1];
|
|
374
|
+
if ((option !== "--habit" && option !== "--evidence") || value === undefined) {
|
|
375
|
+
throw new Error(`Usage\n${usage()}`);
|
|
376
|
+
}
|
|
377
|
+
if (option === "--habit") {
|
|
378
|
+
if (habitName !== undefined)
|
|
379
|
+
throw new Error(`Usage\n${usage()}`);
|
|
380
|
+
habitName = value;
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
if (evidenceLocator !== undefined)
|
|
384
|
+
throw new Error(`Usage\n${usage()}`);
|
|
385
|
+
evidenceLocator = value;
|
|
386
|
+
}
|
|
387
|
+
index += 1;
|
|
388
|
+
}
|
|
389
|
+
if (!habitName || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(habitName)) {
|
|
390
|
+
throw new Error("habit cancellation requires a valid --habit name");
|
|
391
|
+
}
|
|
392
|
+
if (!evidenceLocator
|
|
393
|
+
|| evidenceLocator.startsWith("capture:")
|
|
394
|
+
|| !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(evidenceLocator))
|
|
395
|
+
throw new Error("habit cancellation requires an offline evidence bridge ID");
|
|
396
|
+
return { kind: "habit.cancel", agent, habitName, evidenceLocator };
|
|
397
|
+
}
|
|
317
398
|
if (sub === "list") {
|
|
318
399
|
return { kind: "habit.list", ...(agent ? { agent } : {}) };
|
|
319
400
|
}
|
|
@@ -2225,7 +2306,7 @@ function parseRsvpSmokeCommand(args) {
|
|
|
2225
2306
|
}
|
|
2226
2307
|
function parseNervesReviewCommand(args) {
|
|
2227
2308
|
const { agent, rest } = extractAgentFlag(args);
|
|
2228
|
-
let processName =
|
|
2309
|
+
let processName = core_1.DEFAULT_NERVES_PROCESS;
|
|
2229
2310
|
let component;
|
|
2230
2311
|
let event;
|
|
2231
2312
|
let level;
|