@ouro.bot/cli 0.1.0-alpha.212 → 0.1.0-alpha.214

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,14 +33,16 @@ Current provider ids:
33
33
 
34
34
  The shared harness lives in `src/`:
35
35
 
36
+ - `src/arc/`
37
+ Durable continuity state — obligations, cares, episodes, intentions, presence, and attention types. The agent's sense of ongoing story.
36
38
  - `src/heart/`
37
- Core runtime, provider adapters, daemon, bootstrap, identity, and entrypoints.
39
+ Core runtime, provider adapters, daemon, bootstrap, identity, and entrypoints. Organized into topic subdirectories: daemon/ (lifecycle), outlook/ (calendar), habits/ (scheduling), hatch/ (agent creation), versioning/ (updates), auth/, mcp/, providers/, bridges/.
38
40
  - `src/mind/`
39
- Prompt assembly, session persistence, bundle manifest enforcement, phrases, formatting, diary (memory), journal, and friend resolution.
41
+ Prompt assembly, session persistence, bundle manifest enforcement, phrases, formatting, diary (memory), associative recall, embedding providers, journal, obligation steering, and friend resolution.
40
42
  - `src/repertoire/`
41
- Tool registry, coding orchestration, task tools, and integration clients.
43
+ Tool registry (split into category modules: files, shell, memory, bridge, session, continuity, flow, surface, config, and sense-specific tools), coding orchestration, task tools, shared API client, and integration clients (Graph, ADO, GitHub).
42
44
  - `src/senses/`
43
- CLI, Teams, BlueBubbles, MCP, activity transport, inner-dialog orchestration, and contextual heartbeat.
45
+ CLI (with TUI in senses/cli/), Teams, BlueBubbles (in senses/bluebubbles/), MCP, activity transport, inner-dialog orchestration, and contextual heartbeat.
44
46
  - `src/nerves/`
45
47
  Structured runtime logging and coverage-audit infrastructure.
46
48
  - `src/__tests__/`
@@ -52,8 +54,6 @@ Other important top-level paths:
52
54
  Packaged specialist bundle used by `ouro hatch`.
53
55
  - `skills/`
54
56
  Harness-level skills shipped with the repo (e.g., `configure-dev-tools.md`). These are available to every agent and serve as fallbacks when an agent doesn't have its own version. Agent-specific skills live in the bundle at `~/AgentBundles/<agent>.ouro/skills/`.
55
- - `subagents/`
56
- Workflow skills have moved to [github.com/ouroborosbot/ouroboros-skills](https://github.com/ouroborosbot/ouroboros-skills). Use the skill-management skill for installation and updates.
57
57
  - `scripts/teams-sense/`
58
58
  Operator scripts for the Teams deployment path.
59
59
  - `docs/`
package/changelog.json CHANGED
@@ -1,6 +1,19 @@
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.214",
6
+ "changes": [
7
+ "fix: daemon death diagnostics — createStderrSink() bypassed EPIPE-safe default in createTerminalSink(), causing uncaught EPIPE crashes when daemon runs detached. Removed redundant unsafe default so the existing try-catch fires.",
8
+ "fix: daemon tombstone now covers all exit paths — unhandledRejection writes tombstone with full error+stack (was just a warn log, but Node 15+ terminates on these). Added process.on('exit') catch-all for any unanticipated exit. SIGINT/SIGTERM marked graceful to avoid false positives. _lastKnownCause threads real error through to exit handler."
9
+ ]
10
+ },
11
+ {
12
+ "version": "0.1.0-alpha.213",
13
+ "changes": [
14
+ "cleanup: remove vestigial subagents/ directory and package.json files entry (content already in ouroboros-skills repo). Remove backward-compat re-exports from heart/core.ts (tools, execTool, summarizeArgs, getToolsForChannel, streamChatCompletion, streamResponsesApi, toResponsesInput, toResponsesTools, buildSystem, Channel, hasToolIntent — no consumers used them). Update ARCHITECTURE.md, README.md, and CONTRIBUTING.md to reflect the full audit restructuring: new arc/ subsystem, heart/ topic subdirectories, split tool modules, BlueBubbles directory, scopes list."
15
+ ]
16
+ },
4
17
  {
5
18
  "version": "0.1.0-alpha.212",
6
19
  "changes": [
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hasToolIntent = exports.buildSystem = exports.toResponsesTools = exports.toResponsesInput = exports.streamResponsesApi = exports.streamChatCompletion = exports.getToolsForChannel = exports.summarizeArgs = exports.execTool = exports.tools = void 0;
4
3
  exports.createProviderRegistry = createProviderRegistry;
5
4
  exports.resetProviderRuntime = resetProviderRuntime;
6
5
  exports.getModel = getModel;
@@ -147,21 +146,6 @@ function getProviderDisplayLabel(facing = "human") {
147
146
  };
148
147
  return providerLabelBuilders[provider]();
149
148
  }
150
- // Re-export tools, execTool, summarizeArgs from ./tools for backward compat
151
- var tools_3 = require("../repertoire/tools");
152
- Object.defineProperty(exports, "tools", { enumerable: true, get: function () { return tools_3.tools; } });
153
- Object.defineProperty(exports, "execTool", { enumerable: true, get: function () { return tools_3.execTool; } });
154
- Object.defineProperty(exports, "summarizeArgs", { enumerable: true, get: function () { return tools_3.summarizeArgs; } });
155
- Object.defineProperty(exports, "getToolsForChannel", { enumerable: true, get: function () { return tools_3.getToolsForChannel; } });
156
- // Re-export streaming functions for backward compat
157
- var streaming_1 = require("./streaming");
158
- Object.defineProperty(exports, "streamChatCompletion", { enumerable: true, get: function () { return streaming_1.streamChatCompletion; } });
159
- Object.defineProperty(exports, "streamResponsesApi", { enumerable: true, get: function () { return streaming_1.streamResponsesApi; } });
160
- Object.defineProperty(exports, "toResponsesInput", { enumerable: true, get: function () { return streaming_1.toResponsesInput; } });
161
- Object.defineProperty(exports, "toResponsesTools", { enumerable: true, get: function () { return streaming_1.toResponsesTools; } });
162
- // Re-export prompt functions for backward compat
163
- var prompt_2 = require("../mind/prompt");
164
- Object.defineProperty(exports, "buildSystem", { enumerable: true, get: function () { return prompt_2.buildSystem; } });
165
149
  // Sole-call tools must be the only tool call in a turn. When they appear
166
150
  // alongside other tools, the sole-call tool is rejected with this message.
167
151
  const SOLE_CALL_REJECTION = {
@@ -264,9 +248,6 @@ function getSettleRetryError(mustResolveBeforeHandoff, intent, sawSteeringFollow
264
248
  }
265
249
  return null;
266
250
  }
267
- // Re-export kick utilities for backward compat
268
- var kicks_1 = require("./kicks");
269
- Object.defineProperty(exports, "hasToolIntent", { enumerable: true, get: function () { return kicks_1.hasToolIntent; } });
270
251
  function upsertSystemPrompt(messages, systemText) {
271
252
  const systemMessage = { role: "system", content: systemText };
272
253
  if (messages[0]?.role === "system") {
@@ -181,6 +181,7 @@ void daemon.start().then(() => {
181
181
  /* v8 ignore start -- startup failure + signal handlers: call process.exit, untestable in vitest @preserve */
182
182
  }).catch(async (err) => {
183
183
  const error = err instanceof Error ? err : new Error(String(err));
184
+ _tombstoneWritten = true;
184
185
  (0, daemon_tombstone_1.writeDaemonTombstone)("startupFailure", error);
185
186
  (0, runtime_1.emitNervesEvent)({
186
187
  level: "error",
@@ -194,6 +195,7 @@ void daemon.start().then(() => {
194
195
  process.exit(1);
195
196
  });
196
197
  process.on("SIGINT", () => {
198
+ _gracefulShutdown = true;
197
199
  for (const s of habitSchedulers) {
198
200
  s.stopWatching();
199
201
  s.stop();
@@ -202,6 +204,7 @@ process.on("SIGINT", () => {
202
204
  void daemon.stop().then(() => process.exit(0));
203
205
  });
204
206
  process.on("SIGTERM", () => {
207
+ _gracefulShutdown = true;
205
208
  for (const s of habitSchedulers) {
206
209
  s.stopWatching();
207
210
  s.stop();
@@ -217,6 +220,9 @@ process.stderr?.on?.("error", () => { });
217
220
  /* v8 ignore stop */
218
221
  /* v8 ignore start -- global exception handlers: genuinely untestable in vitest; exercised by real daemon crashes @preserve */
219
222
  let _uncaughtCount = 0;
223
+ let _tombstoneWritten = false;
224
+ let _gracefulShutdown = false;
225
+ let _lastKnownCause = null;
220
226
  const CIRCUIT_BREAKER_WINDOW_MS = 60_000;
221
227
  const CIRCUIT_BREAKER_MAX = 10;
222
228
  process.on("uncaughtException", (error) => {
@@ -224,7 +230,9 @@ process.on("uncaughtException", (error) => {
224
230
  if (error.code === "EPIPE")
225
231
  return;
226
232
  _uncaughtCount++;
233
+ _lastKnownCause = error;
227
234
  setTimeout(() => { _uncaughtCount--; }, CIRCUIT_BREAKER_WINDOW_MS).unref();
235
+ _tombstoneWritten = true;
228
236
  (0, daemon_tombstone_1.writeDaemonTombstone)("uncaughtException", error);
229
237
  (0, runtime_1.emitNervesEvent)({
230
238
  level: "error",
@@ -248,13 +256,25 @@ process.on("uncaughtException", (error) => {
248
256
  }
249
257
  });
250
258
  process.on("unhandledRejection", (reason) => {
259
+ const error = reason instanceof Error ? reason : new Error(String(reason));
260
+ _lastKnownCause = error;
261
+ _tombstoneWritten = true;
262
+ (0, daemon_tombstone_1.writeDaemonTombstone)("unhandledRejection", error);
251
263
  (0, runtime_1.emitNervesEvent)({
252
- level: "warn",
264
+ level: "error",
253
265
  component: "daemon",
254
266
  event: "daemon.unhandled_rejection",
255
267
  message: "unhandled promise rejection in daemon process",
256
- meta: { reason: reason instanceof Error ? reason.message : String(reason) },
268
+ meta: { reason: error.message, stack: error.stack ?? null },
257
269
  });
258
270
  });
271
+ // Catch-all: write tombstone on any exit where we didn't already record the cause.
272
+ // process.on('exit') is synchronous-only — writeDaemonTombstone uses writeFileSync, so it works.
273
+ process.on("exit", (code) => {
274
+ if (_tombstoneWritten || _gracefulShutdown)
275
+ return;
276
+ const reason = code === 0 ? "unexpectedCleanExit" : "unexpectedExit";
277
+ const error = _lastKnownCause ?? new Error(`daemon exited with code ${code} (no specific cause captured)`);
278
+ (0, daemon_tombstone_1.writeDaemonTombstone)(reason, error);
279
+ });
259
280
  /* v8 ignore stop */
260
- // daemon stdio fix
@@ -100,7 +100,7 @@ catch { /* EPIPE: daemon detached, no terminal */ } }, colorize = true) {
100
100
  _resumeSpinner?.();
101
101
  };
102
102
  }
103
- function createStderrSink(write = (chunk) => process.stderr.write(chunk)) {
103
+ function createStderrSink(write) {
104
104
  return createTerminalSink(write);
105
105
  }
106
106
  const DEFAULT_MAX_LOG_SIZE_BYTES = 50 * 1024 * 1024; // 50MB
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.212",
3
+ "version": "0.1.0-alpha.214",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",
@@ -10,7 +10,6 @@
10
10
  "files": [
11
11
  "dist/",
12
12
  "SerpentGuide.ouro/",
13
- "subagents/",
14
13
  "skills/",
15
14
  "assets/",
16
15
  "changelog.json"
@@ -1,7 +0,0 @@
1
- # Workflow Skills (Moved)
2
-
3
- The workflow skills (`work-planner`, `work-doer`, `work-merger`) have moved to the shared skills repository:
4
-
5
- **https://github.com/ouroborosbot/ouroboros-skills**
6
-
7
- To install or update these skills, use the **skill-management** skill from that repo. It covers browsing available skills, installing them into your agent's local skills directory, and keeping them up to date.