@ouro.bot/cli 0.1.0-alpha.967 → 0.1.0-alpha.968

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.968",
6
+ "changes": [
7
+ "The context-loss Sentinel takes over its write lock when the process that left it is gone. A lock left by a crash or a reboot used to block every Sentinel refresh until someone deleted it, which turned daemon health critical, so `ouro up` failed and self-update rolled new releases back."
8
+ ]
9
+ },
4
10
  {
5
11
  "version": "0.1.0-alpha.967",
6
12
  "changes": [
@@ -1,5 +1,5 @@
1
1
  {
2
- "runtimeVersion": "0.1.0-alpha.967",
2
+ "runtimeVersion": "0.1.0-alpha.968",
3
3
  "bundleSchemaVersion": 3,
4
4
  "lastUpdated": "2026-09-03T00:00:00.000Z"
5
5
  }
@@ -1,7 +1,7 @@
1
1
  <?xml version="1.0"?>
2
2
  <Container version="2">
3
3
  <Name>ouro-butler</Name>
4
- <Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.967</Repository>
4
+ <Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.968</Repository>
5
5
  <Registry>https://github.com/ourostack/ouroboros/pkgs/container/ouroboros-butler</Registry>
6
6
  <Network>host</Network>
7
7
  <Shell>sh</Shell>
@@ -92,6 +92,49 @@ function atomicWriteJson(filePath, value) {
92
92
  function sleep(ms) {
93
93
  return new Promise((resolve) => setTimeout(resolve, ms));
94
94
  }
95
+ function processGone(pid) {
96
+ try {
97
+ process.kill(pid, 0);
98
+ return false;
99
+ }
100
+ catch (error) {
101
+ return error.code === "ESRCH";
102
+ }
103
+ }
104
+ /**
105
+ * A lock whose writer died (a crash, a reboot) would otherwise block every refresh forever. It is taken over only when it
106
+ * names a process that no longer exists; any other content waits as before. The lock is renamed aside first, so of two
107
+ * waiters only one takes it, and a lock that changed owner in the meantime is put back.
108
+ */
109
+ function breakDeadOwnerLock(lockPath) {
110
+ let owner;
111
+ try {
112
+ owner = fs.readFileSync(lockPath, "utf-8").trim();
113
+ }
114
+ catch {
115
+ return false;
116
+ }
117
+ if (!/^\d+$/.test(owner) || !processGone(Number(owner)))
118
+ return false;
119
+ const aside = `${lockPath}.${process.pid}.${Date.now()}.stale`;
120
+ try {
121
+ fs.renameSync(lockPath, aside);
122
+ }
123
+ catch {
124
+ return false;
125
+ }
126
+ if (fs.readFileSync(aside, "utf-8").trim() !== owner) {
127
+ try {
128
+ fs.linkSync(aside, lockPath);
129
+ }
130
+ catch { /* a newer lock exists; it owns the path */ }
131
+ fs.rmSync(aside, { force: true });
132
+ return false;
133
+ }
134
+ fs.rmSync(aside, { force: true });
135
+ (0, runtime_1.emitNervesEvent)({ level: "warn", component: "heart", event: "heart.context_loss_sentinel_stale_lock", message: "took over a context-loss Sentinel lock whose owner process is gone", meta: { owner: Number(owner) } });
136
+ return true;
137
+ }
95
138
  async function withFileLock(lockPath, timeoutMs, fn) {
96
139
  fs.mkdirSync(path.dirname(lockPath), { recursive: true });
97
140
  const startedAt = Date.now();
@@ -112,6 +155,8 @@ async function withFileLock(lockPath, timeoutMs, fn) {
112
155
  if (code !== "EEXIST") {
113
156
  throw error;
114
157
  }
158
+ if (breakDeadOwnerLock(lockPath))
159
+ continue;
115
160
  if (Date.now() - startedAt > timeoutMs) {
116
161
  throw new Error(`context-loss Sentinel lock timed out: ${lockPath}`);
117
162
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.967",
3
+ "version": "0.1.0-alpha.968",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@ouro.bot/cli",
9
- "version": "0.1.0-alpha.967",
9
+ "version": "0.1.0-alpha.968",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.78.0",
12
12
  "@azure/identity": "^4.13.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.967",
3
+ "version": "0.1.0-alpha.968",
4
4
  "engines": {
5
5
  "node": ">=22"
6
6
  },