@ouro.bot/cli 0.1.0-alpha.92 → 0.1.0-alpha.93

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,12 @@
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.93",
6
+ "changes": [
7
+ "Final-answer truth checks now require fresh external-state verification (gh pr view, npm view, etc.) before allowing intent=complete when a live obligation is active, preventing stale or guessed merge/publish/deploy claims."
8
+ ]
9
+ },
4
10
  {
5
11
  "version": "0.1.0-alpha.92",
6
12
  "changes": [
@@ -7,6 +7,7 @@ exports.getModel = getModel;
7
7
  exports.getProvider = getProvider;
8
8
  exports.createSummarize = createSummarize;
9
9
  exports.getProviderDisplayLabel = getProviderDisplayLabel;
10
+ exports.isExternalStateQuery = isExternalStateQuery;
10
11
  exports.getFinalAnswerRetryError = getFinalAnswerRetryError;
11
12
  exports.stripLastToolCalls = stripLastToolCalls;
12
13
  exports.repairOrphanedToolCalls = repairOrphanedToolCalls;
@@ -228,7 +229,14 @@ function parseFinalAnswerPayload(argumentsText) {
228
229
  return {};
229
230
  }
230
231
  }
231
- function getFinalAnswerRetryError(mustResolveBeforeHandoff, intent, sawSteeringFollowUp, delegationDecision, sawSendMessageSelf, sawGoInward, sawQuerySession, currentObligation, innerJob) {
232
+ /** Returns true when a tool call queries external state (GitHub, npm registry). */
233
+ function isExternalStateQuery(toolName, args) {
234
+ if (toolName !== "shell")
235
+ return false;
236
+ const cmd = String(args.command ?? "");
237
+ return /\bgh\s+(pr|run|api|issue)\b/.test(cmd) || /\bnpm\s+(view|info|show)\b/.test(cmd);
238
+ }
239
+ function getFinalAnswerRetryError(mustResolveBeforeHandoff, intent, sawSteeringFollowUp, delegationDecision, sawSendMessageSelf, sawGoInward, sawQuerySession, currentObligation, innerJob, sawExternalStateQuery) {
232
240
  // 1. Delegation adherence: delegate-inward without evidence of inward action
233
241
  if (delegationDecision?.target === "delegate-inward" && !sawSendMessageSelf && !sawGoInward && !sawQuerySession) {
234
242
  (0, runtime_1.emitNervesEvent)({
@@ -258,6 +266,10 @@ function getFinalAnswerRetryError(mustResolveBeforeHandoff, intent, sawSteeringF
258
266
  if (mustResolveBeforeHandoff && intent === "complete" && currentObligation && !sawSteeringFollowUp) {
259
267
  return "you still owe the live session a visible return on this work. don't end the turn yet — continue until you've brought back the external-state update, or use intent=blocked with the concrete blocker.";
260
268
  }
269
+ // 6. External-state grounding: obligation + complete requires fresh external verification
270
+ if (intent === "complete" && currentObligation && !sawExternalStateQuery && !sawSteeringFollowUp) {
271
+ return "you're claiming this work is complete, but the external state hasn't been verified this turn. ground your claim with a fresh check (gh pr view, npm view, gh run view, etc.) before calling final_answer.";
272
+ }
261
273
  return null;
262
274
  }
263
275
  // Re-export kick utilities for backward compat
@@ -477,6 +489,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
477
489
  let sawGoInward = false;
478
490
  let sawQuerySession = false;
479
491
  let sawBridgeManage = false;
492
+ let sawExternalStateQuery = false;
480
493
  // Prevent MaxListenersExceeded warning — each iteration adds a listener
481
494
  try {
482
495
  require("events").setMaxListeners(50, signal);
@@ -585,7 +598,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
585
598
  // Extract answer from the tool call arguments.
586
599
  // Supports: {"answer":"text","intent":"..."} or "text" (JSON string).
587
600
  const { answer, intent } = parseFinalAnswerPayload(result.toolCalls[0].arguments);
588
- const retryError = getFinalAnswerRetryError(mustResolveBeforeHandoffActive, intent, sawSteeringFollowUp, options?.delegationDecision, sawSendMessageSelf, sawGoInward, sawQuerySession, options?.currentObligation ?? null, options?.activeWorkFrame?.inner?.job);
601
+ const retryError = getFinalAnswerRetryError(mustResolveBeforeHandoffActive, intent, sawSteeringFollowUp, options?.delegationDecision, sawSendMessageSelf, sawGoInward, sawQuerySession, options?.currentObligation ?? null, options?.activeWorkFrame?.inner?.job, sawExternalStateQuery);
589
602
  const validDirectReply = mustResolveBeforeHandoffActive && intent === "direct_reply" && sawSteeringFollowUp;
590
603
  const validTerminalIntent = intent === "complete" || intent === "blocked";
591
604
  const validClosure = answer != null
@@ -783,6 +796,9 @@ async function runAgent(messages, callbacks, channel, signal, options) {
783
796
  /* v8 ignore next -- flag tested via truth-check integration tests @preserve */
784
797
  if (tc.name === "bridge_manage")
785
798
  sawBridgeManage = true;
799
+ /* v8 ignore next -- flag tested via truth-check integration tests @preserve */
800
+ if (isExternalStateQuery(tc.name, args))
801
+ sawExternalStateQuery = true;
786
802
  const argSummary = (0, tools_1.summarizeArgs)(tc.name, args);
787
803
  // Confirmation check for mutate tools
788
804
  if ((0, tools_1.isConfirmationRequired)(tc.name) && !options?.skipConfirmation) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.92",
3
+ "version": "0.1.0-alpha.93",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",