@ouro.bot/cli 0.1.0-alpha.689 → 0.1.0-alpha.690

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.690",
6
+ "changes": [
7
+ "Clear stale context-loss Sentinel-authored Flight Recorder blockers once later health checks recover, so transient sense failures cannot leave Arc stuck on an obsolete recovery ask."
8
+ ]
9
+ },
4
10
  {
5
11
  "version": "0.1.0-alpha.689",
6
12
  "changes": [
@@ -609,8 +609,6 @@ function anchorFromResume(kind, resume) {
609
609
  };
610
610
  }
611
611
  function readFlightRecorderEventsByIds(agentRoot, eventIds) {
612
- if (eventIds.length === 0)
613
- return [];
614
612
  const wanted = new Set(eventIds);
615
613
  const eventsRoot = path.join(agentRoot, "arc", "flight-recorder", "events");
616
614
  if (!fs.existsSync(eventsRoot))
@@ -634,16 +632,24 @@ function isSentinelAuthoredBlockerEvent(event) {
634
632
  && (event.meta?.source === "context-loss-sentinel"
635
633
  || Boolean(event.producedRefs?.some((ref) => ref.kind === "arc" && ref.locator.startsWith(relativeSentinelRoot()))));
636
634
  }
637
- function hasSentinelAuthoredBlocker(agentRoot, resume) {
635
+ function hasOnlySentinelAuthoredBlockers(agentRoot, resume) {
638
636
  if (resume.blockedBecause.length === 0)
639
637
  return false;
640
- return readFlightRecorderEventsByIds(agentRoot, resume.lastSafeCheckpoint.sourceEventIds)
641
- .some(isSentinelAuthoredBlockerEvent);
638
+ if (resume.lastSafeCheckpoint.sourceEventIds.length === 0)
639
+ return false;
640
+ const events = readFlightRecorderEventsByIds(agentRoot, resume.lastSafeCheckpoint.sourceEventIds);
641
+ const foundEventIds = new Set(events.map((event) => event.id));
642
+ if (resume.lastSafeCheckpoint.sourceEventIds.some((eventId) => !foundEventIds.has(eventId)))
643
+ return false;
644
+ const blockerEvents = events.filter((event) => (event.blockedBecause?.length ?? 0) > 0);
645
+ if (blockerEvents.length === 0)
646
+ return false;
647
+ return blockerEvents.every(isSentinelAuthoredBlockerEvent);
642
648
  }
643
649
  function selectGauntletResume(agentRoot) {
644
650
  const resume = (0, flight_recorder_1.readFlightRecorderResume)(agentRoot);
645
651
  const latestReady = readLatestReady(agentRoot);
646
- if (hasSentinelAuthoredBlocker(agentRoot, resume) && latestReady) {
652
+ if (hasOnlySentinelAuthoredBlockers(agentRoot, resume) && latestReady) {
647
653
  return { resume: latestReady.resumeSnapshot, anchorKind: "latest-ready" };
648
654
  }
649
655
  return { resume, anchorKind: "flight-recorder" };
@@ -743,6 +749,8 @@ function blockedSignalSummaries(receipt) {
743
749
  function recordBlockedReceiptEvent(agentRoot, receipt) {
744
750
  if (receipt.verdict !== "blocked")
745
751
  return;
752
+ if (receipt.signals.some((signal) => signal.kind === "gauntlet" && signal.verdictImpact === "blocked"))
753
+ return;
746
754
  (0, flight_recorder_1.recordFlightRecorderEvent)(agentRoot, {
747
755
  id: `fr-${receipt.id}`,
748
756
  kind: "blocker_detected",
@@ -760,6 +768,30 @@ function recordBlockedReceiptEvent(agentRoot, receipt) {
760
768
  },
761
769
  });
762
770
  }
771
+ function recordRecoveredReceiptEvent(agentRoot, receipt) {
772
+ if (receipt.verdict === "blocked")
773
+ return;
774
+ const resume = (0, flight_recorder_1.readFlightRecorderResume)(agentRoot);
775
+ if (!hasOnlySentinelAuthoredBlockers(agentRoot, resume))
776
+ return;
777
+ (0, flight_recorder_1.recordFlightRecorderEvent)(agentRoot, {
778
+ id: `fr-${receipt.id}-recovered`,
779
+ kind: "agent_note",
780
+ recordedAt: receipt.generatedAt,
781
+ summary: "context-loss Sentinel cleared its prior recovery blocker",
782
+ blockedBecause: [],
783
+ producedRefs: [{
784
+ kind: "arc",
785
+ locator: receipt.receiptLocator,
786
+ }],
787
+ meta: {
788
+ source: "context-loss-sentinel",
789
+ receiptId: receipt.id,
790
+ trigger: receipt.trigger,
791
+ resolution: "blocked-signals-recovered",
792
+ },
793
+ });
794
+ }
763
795
  async function persistReceipt(agentRoot, receipt, lockTimeoutMs) {
764
796
  const paths = contextLossSentinelPaths(agentRoot);
765
797
  return withFileLock(paths.lock, lockTimeoutMs, async () => {
@@ -782,6 +814,7 @@ async function persistReceipt(agentRoot, receipt, lockTimeoutMs) {
782
814
  writeWatermark(agentRoot, watermark);
783
815
  setReceiptFileMtime(paths.latest, receipt);
784
816
  recordBlockedReceiptEvent(agentRoot, receipt);
817
+ recordRecoveredReceiptEvent(agentRoot, receipt);
785
818
  }
786
819
  else if (existingLatest && nextReady === receipt) {
787
820
  const updatedLatest = syncLatestReadyState(existingLatest, nextReady);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.689",
3
+ "version": "0.1.0-alpha.690",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",