@ouro.bot/cli 0.1.0-alpha.106 → 0.1.0-alpha.107

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.107",
6
+ "changes": [
7
+ "Family-scoped 'what are you up to?' answers now widen to the full live world-state: the current conversation, live coding lanes, other active friend-facing sessions, and any active inner holding state, instead of collapsing to just the current lane.",
8
+ "The runtime no longer regex-polices an exact status-answer template; family status now rides on the same live obligation and session world-state the agent already uses everywhere else, which keeps cross-session answers truthful and natural."
9
+ ]
10
+ },
4
11
  {
5
12
  "version": "0.1.0-alpha.106",
6
13
  "changes": [
@@ -136,7 +136,15 @@ function formatObligationContentNextAction(obligation) {
136
136
  return `work on "${content}" and bring back a concrete artifact`;
137
137
  }
138
138
  function formatNextAction(frame, obligation) {
139
- if (obligation?.nextAction?.trim()) {
139
+ const obligationHasConcreteArtifact = Boolean(obligation?.currentArtifact?.trim())
140
+ || obligation?.currentSurface?.kind === "merge";
141
+ if (obligation?.status === "waiting_for_merge") {
142
+ return obligation.nextAction?.trim() || `wait for checks, merge ${formatMergeArtifact(obligation)}, then update runtime`;
143
+ }
144
+ if (obligation?.status === "updating_runtime") {
145
+ return obligation.nextAction?.trim() || "update runtime, verify version/changelog, then re-observe";
146
+ }
147
+ if (obligationHasConcreteArtifact && obligation?.nextAction?.trim()) {
140
148
  return obligation.nextAction.trim();
141
149
  }
142
150
  const liveCodingSession = frame.codingSessions?.[0];
@@ -149,12 +157,8 @@ function formatNextAction(frame, obligation) {
149
157
  if (liveCodingSession) {
150
158
  return "finish the coding pass and bring the result back here";
151
159
  }
152
- if (obligation?.status === "waiting_for_merge") {
153
- return `wait for checks, merge ${formatMergeArtifact(obligation)}, then update runtime`;
154
- }
155
- if (obligation?.status === "updating_runtime") {
156
- return "update runtime, verify version/changelog, then re-observe";
157
- }
160
+ if (obligation?.nextAction?.trim())
161
+ return obligation.nextAction.trim();
158
162
  if (obligation) {
159
163
  return formatObligationContentNextAction(obligation) || "continue the active loop and bring the result back here";
160
164
  }
@@ -255,10 +259,13 @@ function formatOtherActiveSessionSummaries(frame, nowMs = Date.now()) {
255
259
  .filter((candidate) => candidate.originSession && sessionOriginKey(candidate.originSession) === originKey)
256
260
  .sort((left, right) => codingSessionTimestampMs(right) - codingSessionTimestampMs(left))[0] ?? null;
257
261
  const liveSession = (frame.friendActivity?.allOtherLiveSessions ?? []).find((candidate) => sessionOriginKey(candidate) === originKey) ?? null;
258
- const hasFreshSessionActivity = liveSession
259
- ? (nowMs - liveSession.lastActivityMs) <= RECENT_OTHER_LIVE_SESSION_WINDOW_MS
262
+ const hasMaterialLiveSession = liveSession
263
+ ? ((nowMs - liveSession.lastActivityMs) <= RECENT_OTHER_LIVE_SESSION_WINDOW_MS
264
+ || (frame.currentSession != null
265
+ && liveSession.friendId === frame.currentSession.friendId
266
+ && liveSession.channel !== frame.currentSession.channel))
260
267
  : false;
261
- if (!obligation && !codingSession && !hasFreshSessionActivity) {
268
+ if (!obligation && !codingSession && !hasMaterialLiveSession) {
262
269
  return null;
263
270
  }
264
271
  const timestampMs = Math.max(liveSession?.lastActivityMs ?? 0, codingSession ? codingSessionTimestampMs(codingSession) : 0, obligation ? obligationTimestampMs(obligation) : 0);
@@ -27,7 +27,6 @@ const azure_1 = require("./providers/azure");
27
27
  const minimax_1 = require("./providers/minimax");
28
28
  const openai_codex_1 = require("./providers/openai-codex");
29
29
  const github_copilot_1 = require("./providers/github-copilot");
30
- const obligation_steering_1 = require("../mind/obligation-steering");
31
30
  const pending_1 = require("../mind/pending");
32
31
  const identity_2 = require("./identity");
33
32
  const socket_client_1 = require("./daemon/socket-client");
@@ -273,45 +272,6 @@ function getFinalAnswerRetryError(mustResolveBeforeHandoff, intent, sawSteeringF
273
272
  }
274
273
  return null;
275
274
  }
276
- function hasExactStatusReplyShape(answer, statusCheckScope) {
277
- const lines = answer.trimEnd().split(/\r?\n/);
278
- const hasFiveLineHeader = (/^live conversation:\s+\S.+$/i.test(lines[0])
279
- && /^active lane:\s+\S.+$/i.test(lines[1])
280
- && /^current artifact:\s+\S.+$/i.test(lines[2])
281
- && /^latest checkpoint:\s+\S.+$/i.test(lines[3])
282
- && /^next action:\s+\S.+$/i.test(lines[4]));
283
- if (!hasFiveLineHeader)
284
- return false;
285
- if (statusCheckScope !== "all-sessions-family") {
286
- return lines.length === 5;
287
- }
288
- if (lines.length < 7)
289
- return false;
290
- if (!/^other active sessions:\s*$/i.test(lines[5]))
291
- return false;
292
- return lines.slice(6).every((line) => /^-\s+\S.+$/i.test(line));
293
- }
294
- function extractLatestCheckpoint(answer) {
295
- const latestLine = answer.trimEnd().split(/\r?\n/)[3];
296
- return latestLine.replace(/^latest checkpoint:\s*/i, "").trim();
297
- }
298
- function getStatusReplyRetryError(answer, statusCheckRequested, activeWorkFrame, statusCheckScope) {
299
- if (!statusCheckRequested || answer == null)
300
- return null;
301
- if (hasExactStatusReplyShape(answer, statusCheckScope))
302
- return null;
303
- if (!activeWorkFrame) {
304
- return `the user asked for current status. call final_answer again using exactly these five non-empty lines and nothing else:
305
- live conversation: ...
306
- active lane: ...
307
- current artifact: ...
308
- latest checkpoint: ...
309
- next action: ...`;
310
- }
311
- return `the user asked for current status right now.
312
- ${(0, obligation_steering_1.renderExactStatusReplyContract)(activeWorkFrame, (0, obligation_steering_1.findStatusObligation)(activeWorkFrame), statusCheckScope)}
313
- call final_answer again using that exact status shape and nothing else.`;
314
- }
315
275
  // Re-export kick utilities for backward compat
316
276
  var kicks_1 = require("./kicks");
317
277
  Object.defineProperty(exports, "hasToolIntent", { enumerable: true, get: function () { return kicks_1.hasToolIntent; } });
@@ -591,7 +551,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
591
551
  traceId,
592
552
  toolChoiceRequired,
593
553
  reasoningEffort: currentReasoningEffort,
594
- eagerFinalAnswerStreaming: !options?.statusCheckRequested,
554
+ eagerFinalAnswerStreaming: true,
595
555
  });
596
556
  // Track usage from the latest API call
597
557
  if (result.usage)
@@ -640,21 +600,16 @@ async function runAgent(messages, callbacks, channel, signal, options) {
640
600
  // Supports: {"answer":"text","intent":"..."} or "text" (JSON string).
641
601
  const { answer, intent } = parseFinalAnswerPayload(result.toolCalls[0].arguments);
642
602
  const retryError = getFinalAnswerRetryError(mustResolveBeforeHandoffActive, intent, sawSteeringFollowUp, options?.delegationDecision, sawSendMessageSelf, sawGoInward, sawQuerySession, options?.currentObligation ?? null, options?.activeWorkFrame?.inner?.job, sawExternalStateQuery);
643
- const statusReplyRetryError = getStatusReplyRetryError(answer, options?.statusCheckRequested, options?.activeWorkFrame, options?.statusCheckScope);
644
- const exactStatusReplyAccepted = Boolean(options?.statusCheckRequested) && !statusReplyRetryError && answer != null;
645
- const deliveredAnswer = exactStatusReplyAccepted && options?.activeWorkFrame
646
- ? (0, obligation_steering_1.buildExactStatusReply)(options.activeWorkFrame, (0, obligation_steering_1.findStatusObligation)(options.activeWorkFrame), extractLatestCheckpoint(answer), options?.statusCheckScope)
647
- : answer;
603
+ const deliveredAnswer = answer;
648
604
  const validDirectReply = mustResolveBeforeHandoffActive && intent === "direct_reply" && sawSteeringFollowUp;
649
605
  const validTerminalIntent = intent === "complete" || intent === "blocked";
650
606
  const validClosure = deliveredAnswer != null
651
- && (exactStatusReplyAccepted || !retryError)
652
- && !statusReplyRetryError
653
- && (exactStatusReplyAccepted || !mustResolveBeforeHandoffActive || validDirectReply || validTerminalIntent);
607
+ && !retryError
608
+ && (!mustResolveBeforeHandoffActive || validDirectReply || validTerminalIntent);
654
609
  if (validClosure) {
655
610
  completion = {
656
611
  answer: deliveredAnswer,
657
- intent: validDirectReply && !exactStatusReplyAccepted ? "direct_reply" : intent === "blocked" ? "blocked" : "complete",
612
+ intent: validDirectReply ? "direct_reply" : intent === "blocked" ? "blocked" : "complete",
658
613
  };
659
614
  if (result.finalAnswerStreamed) {
660
615
  // The streaming layer already parsed and emitted the answer
@@ -669,7 +624,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
669
624
  callbacks.onTextChunk(deliveredAnswer);
670
625
  }
671
626
  messages.push(msg);
672
- if (validDirectReply && !exactStatusReplyAccepted) {
627
+ if (validDirectReply) {
673
628
  const resumeWork = "direct reply delivered. resume the unresolved obligation now and keep working until you can finish or clearly report that you are blocked.";
674
629
  messages.push({ role: "tool", tool_call_id: result.toolCalls[0].id, content: resumeWork });
675
630
  providerRuntime.appendToolOutput(result.toolCalls[0].id, resumeWork);
@@ -688,8 +643,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
688
643
  // assistant msg + error tool result and let the model try again.
689
644
  callbacks.onClearText?.();
690
645
  messages.push(msg);
691
- const toolRetryMessage = statusReplyRetryError
692
- ?? retryError
646
+ const toolRetryMessage = retryError
693
647
  ?? "your final_answer was incomplete or malformed. call final_answer again with your complete response.";
694
648
  messages.push({ role: "tool", tool_call_id: result.toolCalls[0].id, content: toolRetryMessage });
695
649
  providerRuntime.appendToolOutput(result.toolCalls[0].id, toolRetryMessage);
@@ -113,8 +113,17 @@ function formatCurrentArtifact(frame, obligation) {
113
113
  return obligation ? "no artifact yet" : "";
114
114
  }
115
115
  function formatNextAction(frame, obligation) {
116
- if (obligation?.nextAction)
117
- return obligation.nextAction;
116
+ const obligationHasConcreteArtifact = Boolean(obligation?.currentArtifact?.trim())
117
+ || obligation?.currentSurface?.kind === "merge";
118
+ if (obligation?.status === "waiting_for_merge") {
119
+ return obligation.nextAction?.trim() || `wait for checks, merge ${formatMergeArtifact(obligation)}, then update runtime`;
120
+ }
121
+ if (obligation?.status === "updating_runtime") {
122
+ return obligation.nextAction?.trim() || "update runtime, verify version/changelog, then re-observe";
123
+ }
124
+ if (obligationHasConcreteArtifact && obligation?.nextAction?.trim()) {
125
+ return obligation.nextAction.trim();
126
+ }
118
127
  const liveCodingSession = frame.codingSessions?.[0];
119
128
  if (liveCodingSession?.status === "waiting_input") {
120
129
  return `answer ${liveCodingSession.runner} ${liveCodingSession.id} and continue`;
@@ -125,12 +134,8 @@ function formatNextAction(frame, obligation) {
125
134
  if (liveCodingSession) {
126
135
  return "finish the coding pass and bring the result back here";
127
136
  }
128
- if (obligation?.status === "waiting_for_merge") {
129
- return `wait for checks, merge ${formatMergeArtifact(obligation)}, then update runtime`;
130
- }
131
- if (obligation?.status === "updating_runtime") {
132
- return "update runtime, verify version/changelog, then re-observe";
133
- }
137
+ if (obligation?.nextAction?.trim())
138
+ return obligation.nextAction.trim();
134
139
  if (obligation?.content?.trim()) {
135
140
  return `work on "${obligation.content.trim()}" and bring back a concrete artifact`;
136
141
  }
@@ -466,9 +466,15 @@ function familyCrossSessionTruthSection(context, options) {
466
466
  if a family member asks what i'm up to or how things are going, that includes the material live work i can see across sessions, not just this thread.
467
467
  i answer naturally from the live world-state in this prompt.
468
468
  i do not rely on canned status-question modes or phrase matching.
469
- if part of the picture is still fuzzy, i say what i can see and what still needs checking.`;
470
- }
471
- function centerOfGravitySteeringSection(channel, options) {
469
+ if part of the picture is still fuzzy, i say what i can see and what still needs checking.
470
+ when the live ask is about status, i widen before answering:
471
+ - where i am right now
472
+ - any other material active sessions or coding lanes i can see
473
+ - the freshest concrete checkpoint
474
+ - the next concrete step
475
+ i do not collapse down to only the current lane.`;
476
+ }
477
+ function centerOfGravitySteeringSection(channel, options, context) {
472
478
  if (channel === "inner")
473
479
  return "";
474
480
  const frame = options?.activeWorkFrame;
@@ -523,8 +529,15 @@ i should bring my answer back to the conversation it came from.`;
523
529
  : liveCodingSession.originSession
524
530
  ? ` for ${liveCodingSession.originSession.channel}/${liveCodingSession.originSession.key}`
525
531
  : "";
532
+ const otherSessionLines = (0, active_work_1.formatOtherActiveSessionSummaries)(frame);
533
+ const familyStatusClause = context?.friend?.trustLevel === "family"
534
+ ? `\nif a family member asks what i'm up to, i treat this coding lane as one part of the visible picture, not the whole picture.
535
+ after i name this lane, i widen back out with:
536
+ other active sessions:
537
+ ${otherSessionLines.length > 0 ? otherSessionLines.join("\n") : "- none"}`
538
+ : "";
526
539
  return `## where my attention is
527
- i already have coding work running in ${liveCodingSession.runner} ${liveCodingSession.id}${scopeClause}.
540
+ i already have coding work running in ${liveCodingSession.runner} ${liveCodingSession.id}${scopeClause}.${familyStatusClause}
528
541
 
529
542
  i should orient around that live lane first, then decide what still needs to come back here.`;
530
543
  }
@@ -546,17 +559,6 @@ i should keep the different sides aligned. what i learn here may matter there, a
546
559
  /* v8 ignore next -- unreachable: all center-of-gravity modes covered above @preserve */
547
560
  return "";
548
561
  }
549
- function statusCheckSection(channel, options) {
550
- if (channel === "inner" || !options?.statusCheckRequested)
551
- return "";
552
- const frame = options.activeWorkFrame;
553
- if (!frame)
554
- return "";
555
- const activeObligation = (0, obligation_steering_1.findStatusObligation)(frame);
556
- return `## status question on this turn
557
- the user is asking for current status right now.
558
- ${(0, obligation_steering_1.renderExactStatusReplyContract)(frame, activeObligation, options.statusCheckScope)}`;
559
- }
560
562
  function commitmentsSection(options) {
561
563
  if (!options?.activeWorkFrame)
562
564
  return "";
@@ -765,8 +767,7 @@ async function buildSystem(channel = "cli", options, context) {
765
767
  taskBoardSection(),
766
768
  activeWorkSection(options),
767
769
  familyCrossSessionTruthSection(context, options),
768
- statusCheckSection(channel, options),
769
- centerOfGravitySteeringSection(channel, options),
770
+ centerOfGravitySteeringSection(channel, options, context),
770
771
  commitmentsSection(options),
771
772
  delegationHintSection(options),
772
773
  bridgeContextSection(options),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.106",
3
+ "version": "0.1.0-alpha.107",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",