@ouro.bot/cli 0.1.0-alpha.728 → 0.1.0-alpha.729
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
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.729",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Respawn long-lived auto-start workers after unsolicited clean exits so managed BlueBubbles listeners recover without a full daemon restart.",
|
|
8
|
+
"Bound repeated clean-exit loops with cause-neutral diagnostics and keep explicit stop, whole-daemon stop, and manual restart free of stale respawns."
|
|
9
|
+
]
|
|
10
|
+
},
|
|
4
11
|
{
|
|
5
12
|
"version": "0.1.0-alpha.728",
|
|
6
13
|
"changes": [
|
|
@@ -672,26 +672,29 @@ class DaemonProcessManager {
|
|
|
672
672
|
state.snapshot.errorReason = null;
|
|
673
673
|
state.snapshot.fixHint = null;
|
|
674
674
|
}
|
|
675
|
-
const
|
|
675
|
+
const unexpectedExit = !state.stopRequested;
|
|
676
|
+
const crashed = unexpectedExit && code !== 0;
|
|
676
677
|
const now = this.currentTimeMs();
|
|
677
678
|
const startedAt = state.snapshot.startedAt ? Date.parse(state.snapshot.startedAt) : now;
|
|
678
679
|
const runDuration = Math.max(0, now - startedAt);
|
|
679
680
|
(0, runtime_1.emitNervesEvent)({
|
|
680
|
-
level:
|
|
681
|
+
level: unexpectedExit ? "warn" : "info",
|
|
681
682
|
component: "daemon",
|
|
682
683
|
event: "daemon.agent_exit",
|
|
683
684
|
message: "managed agent process exited",
|
|
684
|
-
meta: { agent: state.config.name, code, signal, crashed, runDurationMs: runDuration },
|
|
685
|
+
meta: { agent: state.config.name, code, signal, crashed, unexpectedExit, runDurationMs: runDuration },
|
|
685
686
|
});
|
|
686
|
-
if (
|
|
687
|
+
if (runDuration >= this.stabilityThresholdMs) {
|
|
688
|
+
state.snapshot.backoffMs = this.initialBackoffMs;
|
|
689
|
+
}
|
|
690
|
+
if (!unexpectedExit) {
|
|
687
691
|
state.snapshot.status = "stopped";
|
|
688
|
-
if (runDuration >= this.stabilityThresholdMs) {
|
|
689
|
-
state.snapshot.backoffMs = this.initialBackoffMs;
|
|
690
|
-
}
|
|
691
692
|
this.notifySnapshotChange(state.snapshot);
|
|
692
693
|
return;
|
|
693
694
|
}
|
|
694
|
-
|
|
695
|
+
if (crashed) {
|
|
696
|
+
state.snapshot.lastCrashAt = new Date(now).toISOString();
|
|
697
|
+
}
|
|
695
698
|
if (state.config.autoStart === false) {
|
|
696
699
|
state.snapshot.status = "stopped";
|
|
697
700
|
state.snapshot.errorReason = "non-autostart worker exited unexpectedly; not respawning";
|
|
@@ -699,46 +702,45 @@ class DaemonProcessManager {
|
|
|
699
702
|
this.notifySnapshotChange(state.snapshot);
|
|
700
703
|
return;
|
|
701
704
|
}
|
|
702
|
-
// Fast-
|
|
703
|
-
//
|
|
704
|
-
//
|
|
705
|
+
// Fast-exit detection: repeated early exits, including clean exit-code-0
|
|
706
|
+
// terminations, indicate a startup/configuration or lifecycle fault rather
|
|
707
|
+
// than a stable long-lived worker. Bound them without claiming a crash.
|
|
705
708
|
const FAST_CRASH_THRESHOLD_MS = 5000;
|
|
706
709
|
const FAST_CRASH_MAX = 3;
|
|
707
710
|
if (runDuration < FAST_CRASH_THRESHOLD_MS) {
|
|
708
711
|
state.fastCrashCount = state.fastCrashCount + 1;
|
|
709
712
|
if (state.fastCrashCount >= FAST_CRASH_MAX) {
|
|
710
713
|
state.snapshot.status = "crashed";
|
|
711
|
-
// Capture the fast-
|
|
712
|
-
//
|
|
713
|
-
|
|
714
|
-
state.snapshot.
|
|
715
|
-
state.snapshot.fixHint = `Fix the config and run \`ouro up\` to restart, or check daemon logs for the underlying error.`;
|
|
714
|
+
// Capture the fast-exit diagnosis on the snapshot so it surfaces via
|
|
715
|
+
// the pulse with a prescriptive, cause-neutral repair path.
|
|
716
|
+
state.snapshot.errorReason = `agent exited unexpectedly ${FAST_CRASH_MAX} times within ${FAST_CRASH_THRESHOLD_MS}ms of startup — likely a startup/configuration or lifecycle issue.`;
|
|
717
|
+
state.snapshot.fixHint = `Inspect daemon logs and lifecycle/configuration, then run \`ouro up\` to restart.`;
|
|
716
718
|
(0, runtime_1.emitNervesEvent)({
|
|
717
719
|
level: "error",
|
|
718
720
|
component: "daemon",
|
|
719
721
|
event: "daemon.agent_config_failure",
|
|
720
|
-
message: `agent
|
|
721
|
-
meta: { agent: state.config.name,
|
|
722
|
+
message: `agent exited unexpectedly ${FAST_CRASH_MAX} times within ${FAST_CRASH_THRESHOLD_MS}ms of startup. Not retrying. Inspect lifecycle/configuration and run \`ouro up\` to restart.`,
|
|
723
|
+
meta: { agent: state.config.name, fastUnexpectedExitCount: state.fastCrashCount, avgRunDurationMs: runDuration },
|
|
722
724
|
});
|
|
723
725
|
this.notifySnapshotChange(state.snapshot);
|
|
724
726
|
return; // Don't schedule cooldown recovery — this needs human/agent intervention
|
|
725
727
|
}
|
|
726
728
|
}
|
|
727
729
|
else {
|
|
728
|
-
// Reset fast-
|
|
730
|
+
// Reset the fast unexpected-exit counter on a stable run.
|
|
729
731
|
state.fastCrashCount = 0;
|
|
730
732
|
}
|
|
731
733
|
state.crashTimestamps = state.crashTimestamps.filter((crashTs) => crashTs >= startOfHour(now));
|
|
732
734
|
state.crashTimestamps.push(now);
|
|
733
735
|
if (state.crashTimestamps.length > this.maxRestartsPerHour) {
|
|
734
736
|
state.snapshot.status = "crashed";
|
|
735
|
-
state.snapshot.errorReason = `agent exceeded restart limit (${this.maxRestartsPerHour}/hr) — entering cooldown`;
|
|
736
|
-
state.snapshot.fixHint = "investigate why the agent keeps
|
|
737
|
+
state.snapshot.errorReason = `agent exceeded unexpected-exit restart limit (${this.maxRestartsPerHour}/hr) — entering cooldown`;
|
|
738
|
+
state.snapshot.fixHint = "investigate why the agent keeps exiting unexpectedly; cooldown will retry shortly";
|
|
737
739
|
(0, runtime_1.emitNervesEvent)({
|
|
738
740
|
level: "error",
|
|
739
741
|
component: "daemon",
|
|
740
742
|
event: "daemon.agent_restart_exhausted",
|
|
741
|
-
message: "managed agent exceeded restart limit and is marked crashed",
|
|
743
|
+
message: "managed agent exceeded unexpected-exit restart limit and is marked crashed",
|
|
742
744
|
meta: { agent: state.config.name, maxRestartsPerHour: this.maxRestartsPerHour },
|
|
743
745
|
});
|
|
744
746
|
this.notifySnapshotChange(state.snapshot);
|
|
@@ -488,7 +488,7 @@ function readBlueBubblesRuntimeFacts(agent, bundlesRoot, snapshot) {
|
|
|
488
488
|
...proofFacts,
|
|
489
489
|
lastFailure: "listener process is not running",
|
|
490
490
|
failureLayer: "listener",
|
|
491
|
-
recoveryAction: "daemon
|
|
491
|
+
recoveryAction: "daemon process manager will restart the BlueBubbles listener after an unsolicited exit",
|
|
492
492
|
};
|
|
493
493
|
}
|
|
494
494
|
if (state.upstreamStatus === "error") {
|