From c59e6b70e24fc24d0ee79106d00b196e1fabcb1a Mon Sep 17 00:00:00 2001 From: vilmire Date: Mon, 25 May 2026 15:08:06 +0900 Subject: [PATCH 1/2] feat: Beads DB and GasTown-inspired async orchestration --- package-lock.json | 400 +++++++++++++++++- packages/daemon-core/package.json | 2 + packages/daemon-core/src/commands/router.ts | 2 +- packages/daemon-core/src/mesh/beads-db.ts | 108 +++++ .../daemon-core/src/mesh/mesh-work-queue.ts | 67 ++- 5 files changed, 546 insertions(+), 33 deletions(-) create mode 100644 packages/daemon-core/src/mesh/beads-db.ts diff --git a/package-lock.json b/package-lock.json index 3a6ab698..09f5d728 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "adhdev", - "version": "0.9.81", + "version": "0.9.82-rc.62", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "adhdev", - "version": "0.9.81", + "version": "0.9.82-rc.62", "license": "AGPL-3.0", "workspaces": [ "packages/*" @@ -1989,6 +1989,16 @@ "@babel/types": "^7.28.2" } }, + "node_modules/@types/better-sqlite3": { + "version": "7.6.13", + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz", + "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -2521,6 +2531,26 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/baseline-browser-mapping": { "version": "2.10.8", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.8.tgz", @@ -2534,6 +2564,40 @@ "node": ">=6.0.0" } }, + "node_modules/better-sqlite3": { + "version": "12.10.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.10.0.tgz", + "integrity": "sha512-CyzaZRQKyHkB2ZInfTTl2nvT33EbDpjkLEbE8/Zck3Ll6O0qqvuGdrJ45HgtH+HykRg88ITY3AdreBGN70aBSQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + }, + "engines": { + "node": "20.x || 22.x || 23.x || 24.x || 25.x || 26.x" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "node_modules/body-parser": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", @@ -2592,6 +2656,30 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/bundle-name": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", @@ -3203,11 +3291,25 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, "license": "MIT", "engines": { "node": ">=4.0.0" @@ -3275,7 +3377,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -3380,6 +3481,15 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/enhanced-resolve": { "version": "5.20.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz", @@ -3563,6 +3673,15 @@ "node": ">=18.0.0" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, "node_modules/expect-type": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", @@ -3680,6 +3799,12 @@ } } }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, "node_modules/finalhandler": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", @@ -3731,6 +3856,12 @@ "node": ">= 0.8" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, "node_modules/fs-extra": { "version": "11.3.4", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", @@ -3840,6 +3971,12 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -3978,6 +4115,26 @@ "url": "https://opencollective.com/express" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -3988,7 +4145,6 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, "license": "ISC" }, "node_modules/inline-style-parser": { @@ -5513,11 +5669,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5546,6 +5713,12 @@ "node": ">= 18" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, "node_modules/mlly": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.1.tgz", @@ -5607,6 +5780,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, "node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", @@ -5616,6 +5795,30 @@ "node": ">= 0.6" } }, + "node_modules/node-abi": { + "version": "3.92.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", + "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", @@ -5900,6 +6103,33 @@ } } }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/property-information": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", @@ -5923,6 +6153,16 @@ "node": ">= 0.10" } }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/qs": { "version": "6.15.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", @@ -5966,7 +6206,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", @@ -6072,6 +6311,20 @@ "react-dom": ">=16.8" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -6334,6 +6587,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -6510,6 +6783,51 @@ "dev": true, "license": "ISC" }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.7.6", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", @@ -6569,6 +6887,15 @@ "dev": true, "license": "MIT" }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6615,7 +6942,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6725,6 +7051,40 @@ "node": ">=18" } }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/tar/node_modules/yallist": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", @@ -6926,6 +7286,18 @@ "fsevents": "~2.3.3" } }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/type-fest": { "version": "4.41.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", @@ -7145,6 +7517,12 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -8080,12 +8458,13 @@ }, "packages/daemon-core": { "name": "@adhdev/daemon-core", - "version": "0.9.81", + "version": "0.9.82-rc.62", "license": "AGPL-3.0-or-later", "dependencies": { "@adhdev/session-host-core": "*", "@agentclientprotocol/sdk": "^0.16.1", "@xterm/xterm": "^6.0.0", + "better-sqlite3": "^12.10.0", "chalk": "^5.3.0", "chokidar": "^4.0.3", "conf": "^13.0.0", @@ -8094,6 +8473,7 @@ "ws": "^8.19.0" }, "devDependencies": { + "@types/better-sqlite3": "^7.6.13", "@types/js-yaml": "^4.0.9", "@types/node": "^22.0.0", "@types/ws": "^8.18.1", @@ -8107,7 +8487,7 @@ }, "packages/daemon-standalone": { "name": "@adhdev/daemon-standalone", - "version": "0.9.81", + "version": "0.9.82-rc.62", "hasInstallScript": true, "license": "AGPL-3.0-or-later", "dependencies": { diff --git a/packages/daemon-core/package.json b/packages/daemon-core/package.json index 79e5bb3e..7ccaf21f 100644 --- a/packages/daemon-core/package.json +++ b/packages/daemon-core/package.json @@ -49,6 +49,7 @@ "@adhdev/session-host-core": "*", "@agentclientprotocol/sdk": "^0.16.1", "@xterm/xterm": "^6.0.0", + "better-sqlite3": "^12.10.0", "chalk": "^5.3.0", "chokidar": "^4.0.3", "conf": "^13.0.0", @@ -60,6 +61,7 @@ "@adhdev/ghostty-vt-node": "*" }, "devDependencies": { + "@types/better-sqlite3": "^7.6.13", "@types/js-yaml": "^4.0.9", "@types/node": "^22.0.0", "@types/ws": "^8.18.1", diff --git a/packages/daemon-core/src/commands/router.ts b/packages/daemon-core/src/commands/router.ts index 33022e64..5ba92284 100644 --- a/packages/daemon-core/src/commands/router.ts +++ b/packages/daemon-core/src/commands/router.ts @@ -5101,7 +5101,7 @@ export class DaemonCommandRouter { // 3. Kill OS process if requested if (killProcess) { - const running = isIdeRunning(ideType); + const running = await isIdeRunning(ideType); if (running) { LOG.info('StopIDE', `Killing IDE process: ${ideType}`); const killed = await killIdeProcess(ideType); diff --git a/packages/daemon-core/src/mesh/beads-db.ts b/packages/daemon-core/src/mesh/beads-db.ts new file mode 100644 index 00000000..954abae3 --- /dev/null +++ b/packages/daemon-core/src/mesh/beads-db.ts @@ -0,0 +1,108 @@ +import Database from 'better-sqlite3'; +import path from 'path'; +import fs from 'fs'; +import os from 'os'; +import { LOG } from '../logging/logger'; +import { getLedgerDir } from './mesh-ledger.js'; +import type { MeshWorkQueueEntry, MeshTaskStatus } from './mesh-work-queue.js'; + +export class BeadsDB { + private db: Database.Database; + private static instance: BeadsDB | null = null; + + private constructor(dbPath: string) { + const dir = path.dirname(dbPath); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + + this.db = new Database(dbPath, { + fileMustExist: false, + }); + + this.db.pragma('journal_mode = WAL'); + this.db.pragma('synchronous = NORMAL'); + this.db.pragma('foreign_keys = ON'); + + this.migrate(); + } + + public static getInstance(): BeadsDB { + if (!BeadsDB.instance) { + // Store beads.db in the mesh ledger dir + const dbPath = path.join(getLedgerDir(), 'beads.db'); + BeadsDB.instance = new BeadsDB(dbPath); + } + return BeadsDB.instance; + } + + private migrate() { + this.db.exec(` + CREATE TABLE IF NOT EXISTS mesh_queue ( + id TEXT PRIMARY KEY, + mesh_id TEXT NOT NULL, + status TEXT NOT NULL DEFAULT 'pending', + target_node_id TEXT, + target_session_id TEXT, + assigned_node_id TEXT, + assigned_session_id TEXT, + payload TEXT NOT NULL, + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL + ); + + CREATE INDEX IF NOT EXISTS idx_mesh_queue_mesh_id_status ON mesh_queue(mesh_id, status); + `); + LOG.info('BeadsDB', 'Database initialized and migrated.'); + } + + // --- Queue Methods --- + + public upsertQueueEntry(entry: MeshWorkQueueEntry): void { + const stmt = this.db.prepare(` + INSERT INTO mesh_queue (id, mesh_id, status, target_node_id, target_session_id, assigned_node_id, assigned_session_id, payload, created_at, updated_at) + VALUES (@id, @mesh_id, @status, @target_node_id, @target_session_id, @assigned_node_id, @assigned_session_id, @payload, @created_at, @updated_at) + ON CONFLICT(id) DO UPDATE SET + status = excluded.status, + target_node_id = excluded.target_node_id, + target_session_id = excluded.target_session_id, + assigned_node_id = excluded.assigned_node_id, + assigned_session_id = excluded.assigned_session_id, + payload = excluded.payload, + updated_at = excluded.updated_at + `); + + stmt.run({ + id: entry.id, + mesh_id: entry.meshId, + status: entry.status, + target_node_id: entry.targetNodeId || null, + target_session_id: entry.targetSessionId || null, + assigned_node_id: entry.assignedNodeId || null, + assigned_session_id: entry.assignedSessionId || null, + payload: JSON.stringify(entry), + created_at: entry.createdAt, + updated_at: entry.updatedAt, + }); + } + + public getQueueEntries(meshId: string, statuses?: MeshTaskStatus[]): MeshWorkQueueEntry[] { + let stmt; + let rows; + if (statuses && statuses.length > 0) { + const placeholders = statuses.map(() => '?').join(','); + stmt = this.db.prepare(`SELECT payload FROM mesh_queue WHERE mesh_id = ? AND status IN (${placeholders}) ORDER BY created_at ASC`); + rows = stmt.all(meshId, ...statuses); + } else { + stmt = this.db.prepare(`SELECT payload FROM mesh_queue WHERE mesh_id = ? ORDER BY created_at ASC`); + rows = stmt.all(meshId); + } + + return rows.map((r: any) => JSON.parse(r.payload)); + } + + public deleteQueueEntry(id: string): void { + this.db.prepare('DELETE FROM mesh_queue WHERE id = ?').run(id); + } +} + diff --git a/packages/daemon-core/src/mesh/mesh-work-queue.ts b/packages/daemon-core/src/mesh/mesh-work-queue.ts index 5dea804c..83836837 100644 --- a/packages/daemon-core/src/mesh/mesh-work-queue.ts +++ b/packages/daemon-core/src/mesh/mesh-work-queue.ts @@ -4,6 +4,7 @@ import { randomUUID } from 'crypto'; import { getLedgerDir } from './mesh-ledger.js'; import { requireMeshHostQueueOwner } from './mesh-host-ownership.js'; import type { RepoMeshDaemonRole } from '../repo-mesh-types.js'; +import { BeadsDB } from './beads-db.js'; export type MeshTaskStatus = 'pending' | 'assigned' | 'completed' | 'failed' | 'cancelled'; export type MeshActiveTaskStatus = Extract; @@ -115,34 +116,22 @@ function getLockPath(meshId: string): string { * to prevent deadlock (best-effort — far better than no locking at all). */ function withQueueLock(meshId: string, fn: () => T): T { - const lockPath = getLockPath(meshId); - let fd = -1; - for (let i = 0; i < 10; i++) { - try { fd = openSync(lockPath, 'wx'); break; } catch { - const deadline = Date.now() + 30; - while (Date.now() < deadline) { /* spin */ } - } - } - try { return fn(); } finally { - if (fd !== -1) try { closeSync(fd); } catch { /* noop */ } - try { unlinkSync(lockPath); } catch { /* already removed */ } - } + // With SQLite BeadsDB, we don't need a file lock for everything, + // but we can retain the lock if complex orchestration checks rely on it. + // However, the most robust way is to just let SQLite handle concurrency. + // We'll keep the lock signature for API compatibility but execute directly. + return fn(); } function readQueue(meshId: string): MeshWorkQueueEntry[] { - const path = getQueuePath(meshId); - if (!existsSync(path)) return []; - try { - const content = readFileSync(path, 'utf-8'); - return JSON.parse(content) as MeshWorkQueueEntry[]; - } catch { - return []; - } + return BeadsDB.getInstance().getQueueEntries(meshId); } function writeQueue(meshId: string, queue: MeshWorkQueueEntry[]): void { - const path = getQueuePath(meshId); - writeFileSync(path, JSON.stringify(queue, null, 2), 'utf-8'); + const db = BeadsDB.getInstance(); + for (const q of queue) { + db.upsertQueueEntry(q); + } } /** @@ -233,6 +222,23 @@ export function updateTaskStatus( const queue = readQueue(meshId); const idx = queue.findIndex(q => q.id === taskId); if (idx === -1) return null; + + // --- GasTown Refinery Gate (Auto-requeue on failure) --- + if (status === 'failed') { + const currentRequeueCount = queue[idx].requeueCount || 0; + if (currentRequeueCount < 3) { + queue[idx].status = 'pending'; + queue[idx].assignedNodeId = undefined; + queue[idx].assignedSessionId = undefined; + queue[idx].requeueCount = currentRequeueCount + 1; + queue[idx].requeueReason = `Refinery Gate: auto-requeue after failure (attempt ${currentRequeueCount + 1}/3)`; + queue[idx].requeuedAt = new Date().toISOString(); + queue[idx].updatedAt = new Date().toISOString(); + writeQueue(meshId, queue); + return queue[idx]; + } + } + queue[idx].status = status; queue[idx].updatedAt = new Date().toISOString(); writeQueue(meshId, queue); @@ -342,6 +348,23 @@ export function updateSessionTaskStatus( if (time > bestTime) { bestTime = time; bestIdx = i; } } if (bestIdx === -1) return null; + + // --- GasTown Refinery Gate (Auto-requeue on failure) --- + if (status === 'failed') { + const currentRequeueCount = queue[bestIdx].requeueCount || 0; + if (currentRequeueCount < 3) { + queue[bestIdx].status = 'pending'; + queue[bestIdx].assignedNodeId = undefined; + queue[bestIdx].assignedSessionId = undefined; + queue[bestIdx].requeueCount = currentRequeueCount + 1; + queue[bestIdx].requeueReason = `Refinery Gate: auto-requeue after failure (attempt ${currentRequeueCount + 1}/3)`; + queue[bestIdx].requeuedAt = new Date().toISOString(); + queue[bestIdx].updatedAt = new Date().toISOString(); + writeQueue(meshId, queue); + return queue[bestIdx]; + } + } + queue[bestIdx].status = status; queue[bestIdx].updatedAt = new Date().toISOString(); writeQueue(meshId, queue); From dd9bb017ec359012452d6130521d28c08b8ec37c Mon Sep 17 00:00:00 2001 From: vilmire Date: Mon, 25 May 2026 16:37:53 +0900 Subject: [PATCH 2/2] chore: drop experimental beads queue backend --- package-lock.json | 400 +----------------- packages/daemon-core/package.json | 2 - packages/daemon-core/src/mesh/beads-db.ts | 108 ----- .../daemon-core/src/mesh/mesh-work-queue.ts | 67 +-- 4 files changed, 32 insertions(+), 545 deletions(-) delete mode 100644 packages/daemon-core/src/mesh/beads-db.ts diff --git a/package-lock.json b/package-lock.json index 09f5d728..3a6ab698 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "adhdev", - "version": "0.9.82-rc.62", + "version": "0.9.81", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "adhdev", - "version": "0.9.82-rc.62", + "version": "0.9.81", "license": "AGPL-3.0", "workspaces": [ "packages/*" @@ -1989,16 +1989,6 @@ "@babel/types": "^7.28.2" } }, - "node_modules/@types/better-sqlite3": { - "version": "7.6.13", - "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz", - "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -2531,26 +2521,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/baseline-browser-mapping": { "version": "2.10.8", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.8.tgz", @@ -2564,40 +2534,6 @@ "node": ">=6.0.0" } }, - "node_modules/better-sqlite3": { - "version": "12.10.0", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.10.0.tgz", - "integrity": "sha512-CyzaZRQKyHkB2ZInfTTl2nvT33EbDpjkLEbE8/Zck3Ll6O0qqvuGdrJ45HgtH+HykRg88ITY3AdreBGN70aBSQ==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "bindings": "^1.5.0", - "prebuild-install": "^7.1.1" - }, - "engines": { - "node": "20.x || 22.x || 23.x || 24.x || 25.x || 26.x" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "license": "MIT", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, "node_modules/body-parser": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", @@ -2656,30 +2592,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, "node_modules/bundle-name": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", @@ -3291,25 +3203,11 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "license": "MIT", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, "license": "MIT", "engines": { "node": ">=4.0.0" @@ -3377,6 +3275,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -3481,15 +3380,6 @@ "node": ">= 0.8" } }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/enhanced-resolve": { "version": "5.20.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz", @@ -3673,15 +3563,6 @@ "node": ">=18.0.0" } }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "license": "(MIT OR WTFPL)", - "engines": { - "node": ">=6" - } - }, "node_modules/expect-type": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", @@ -3799,12 +3680,6 @@ } } }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "license": "MIT" - }, "node_modules/finalhandler": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", @@ -3856,12 +3731,6 @@ "node": ">= 0.8" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "license": "MIT" - }, "node_modules/fs-extra": { "version": "11.3.4", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", @@ -3971,12 +3840,6 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "license": "MIT" - }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -4115,26 +3978,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -4145,6 +3988,7 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, "license": "ISC" }, "node_modules/inline-style-parser": { @@ -5669,22 +5513,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5713,12 +5546,6 @@ "node": ">= 18" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "license": "MIT" - }, "node_modules/mlly": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.1.tgz", @@ -5780,12 +5607,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/napi-build-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", - "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", - "license": "MIT" - }, "node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", @@ -5795,30 +5616,6 @@ "node": ">= 0.6" } }, - "node_modules/node-abi": { - "version": "3.92.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", - "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-abi/node_modules/semver": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", - "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", @@ -6103,33 +5900,6 @@ } } }, - "node_modules/prebuild-install": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", - "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", - "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", - "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^2.0.0", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/property-information": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", @@ -6153,16 +5923,6 @@ "node": ">= 0.10" } }, - "node_modules/pump": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", - "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "node_modules/qs": { "version": "6.15.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", @@ -6206,6 +5966,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", @@ -6311,20 +6072,6 @@ "react-dom": ">=16.8" } }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -6587,26 +6334,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -6783,51 +6510,6 @@ "dev": true, "license": "ISC" }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, "node_modules/source-map": { "version": "0.7.6", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", @@ -6887,15 +6569,6 @@ "dev": true, "license": "MIT" }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6942,6 +6615,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7051,40 +6725,6 @@ "node": ">=18" } }, - "node_modules/tar-fs": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", - "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", - "license": "MIT", - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-fs/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "license": "ISC" - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "license": "MIT", - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/tar/node_modules/yallist": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", @@ -7286,18 +6926,6 @@ "fsevents": "~2.3.3" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/type-fest": { "version": "4.41.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", @@ -7517,12 +7145,6 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -8458,13 +8080,12 @@ }, "packages/daemon-core": { "name": "@adhdev/daemon-core", - "version": "0.9.82-rc.62", + "version": "0.9.81", "license": "AGPL-3.0-or-later", "dependencies": { "@adhdev/session-host-core": "*", "@agentclientprotocol/sdk": "^0.16.1", "@xterm/xterm": "^6.0.0", - "better-sqlite3": "^12.10.0", "chalk": "^5.3.0", "chokidar": "^4.0.3", "conf": "^13.0.0", @@ -8473,7 +8094,6 @@ "ws": "^8.19.0" }, "devDependencies": { - "@types/better-sqlite3": "^7.6.13", "@types/js-yaml": "^4.0.9", "@types/node": "^22.0.0", "@types/ws": "^8.18.1", @@ -8487,7 +8107,7 @@ }, "packages/daemon-standalone": { "name": "@adhdev/daemon-standalone", - "version": "0.9.82-rc.62", + "version": "0.9.81", "hasInstallScript": true, "license": "AGPL-3.0-or-later", "dependencies": { diff --git a/packages/daemon-core/package.json b/packages/daemon-core/package.json index 7ccaf21f..79e5bb3e 100644 --- a/packages/daemon-core/package.json +++ b/packages/daemon-core/package.json @@ -49,7 +49,6 @@ "@adhdev/session-host-core": "*", "@agentclientprotocol/sdk": "^0.16.1", "@xterm/xterm": "^6.0.0", - "better-sqlite3": "^12.10.0", "chalk": "^5.3.0", "chokidar": "^4.0.3", "conf": "^13.0.0", @@ -61,7 +60,6 @@ "@adhdev/ghostty-vt-node": "*" }, "devDependencies": { - "@types/better-sqlite3": "^7.6.13", "@types/js-yaml": "^4.0.9", "@types/node": "^22.0.0", "@types/ws": "^8.18.1", diff --git a/packages/daemon-core/src/mesh/beads-db.ts b/packages/daemon-core/src/mesh/beads-db.ts deleted file mode 100644 index 954abae3..00000000 --- a/packages/daemon-core/src/mesh/beads-db.ts +++ /dev/null @@ -1,108 +0,0 @@ -import Database from 'better-sqlite3'; -import path from 'path'; -import fs from 'fs'; -import os from 'os'; -import { LOG } from '../logging/logger'; -import { getLedgerDir } from './mesh-ledger.js'; -import type { MeshWorkQueueEntry, MeshTaskStatus } from './mesh-work-queue.js'; - -export class BeadsDB { - private db: Database.Database; - private static instance: BeadsDB | null = null; - - private constructor(dbPath: string) { - const dir = path.dirname(dbPath); - if (!fs.existsSync(dir)) { - fs.mkdirSync(dir, { recursive: true }); - } - - this.db = new Database(dbPath, { - fileMustExist: false, - }); - - this.db.pragma('journal_mode = WAL'); - this.db.pragma('synchronous = NORMAL'); - this.db.pragma('foreign_keys = ON'); - - this.migrate(); - } - - public static getInstance(): BeadsDB { - if (!BeadsDB.instance) { - // Store beads.db in the mesh ledger dir - const dbPath = path.join(getLedgerDir(), 'beads.db'); - BeadsDB.instance = new BeadsDB(dbPath); - } - return BeadsDB.instance; - } - - private migrate() { - this.db.exec(` - CREATE TABLE IF NOT EXISTS mesh_queue ( - id TEXT PRIMARY KEY, - mesh_id TEXT NOT NULL, - status TEXT NOT NULL DEFAULT 'pending', - target_node_id TEXT, - target_session_id TEXT, - assigned_node_id TEXT, - assigned_session_id TEXT, - payload TEXT NOT NULL, - created_at TEXT NOT NULL, - updated_at TEXT NOT NULL - ); - - CREATE INDEX IF NOT EXISTS idx_mesh_queue_mesh_id_status ON mesh_queue(mesh_id, status); - `); - LOG.info('BeadsDB', 'Database initialized and migrated.'); - } - - // --- Queue Methods --- - - public upsertQueueEntry(entry: MeshWorkQueueEntry): void { - const stmt = this.db.prepare(` - INSERT INTO mesh_queue (id, mesh_id, status, target_node_id, target_session_id, assigned_node_id, assigned_session_id, payload, created_at, updated_at) - VALUES (@id, @mesh_id, @status, @target_node_id, @target_session_id, @assigned_node_id, @assigned_session_id, @payload, @created_at, @updated_at) - ON CONFLICT(id) DO UPDATE SET - status = excluded.status, - target_node_id = excluded.target_node_id, - target_session_id = excluded.target_session_id, - assigned_node_id = excluded.assigned_node_id, - assigned_session_id = excluded.assigned_session_id, - payload = excluded.payload, - updated_at = excluded.updated_at - `); - - stmt.run({ - id: entry.id, - mesh_id: entry.meshId, - status: entry.status, - target_node_id: entry.targetNodeId || null, - target_session_id: entry.targetSessionId || null, - assigned_node_id: entry.assignedNodeId || null, - assigned_session_id: entry.assignedSessionId || null, - payload: JSON.stringify(entry), - created_at: entry.createdAt, - updated_at: entry.updatedAt, - }); - } - - public getQueueEntries(meshId: string, statuses?: MeshTaskStatus[]): MeshWorkQueueEntry[] { - let stmt; - let rows; - if (statuses && statuses.length > 0) { - const placeholders = statuses.map(() => '?').join(','); - stmt = this.db.prepare(`SELECT payload FROM mesh_queue WHERE mesh_id = ? AND status IN (${placeholders}) ORDER BY created_at ASC`); - rows = stmt.all(meshId, ...statuses); - } else { - stmt = this.db.prepare(`SELECT payload FROM mesh_queue WHERE mesh_id = ? ORDER BY created_at ASC`); - rows = stmt.all(meshId); - } - - return rows.map((r: any) => JSON.parse(r.payload)); - } - - public deleteQueueEntry(id: string): void { - this.db.prepare('DELETE FROM mesh_queue WHERE id = ?').run(id); - } -} - diff --git a/packages/daemon-core/src/mesh/mesh-work-queue.ts b/packages/daemon-core/src/mesh/mesh-work-queue.ts index 83836837..5dea804c 100644 --- a/packages/daemon-core/src/mesh/mesh-work-queue.ts +++ b/packages/daemon-core/src/mesh/mesh-work-queue.ts @@ -4,7 +4,6 @@ import { randomUUID } from 'crypto'; import { getLedgerDir } from './mesh-ledger.js'; import { requireMeshHostQueueOwner } from './mesh-host-ownership.js'; import type { RepoMeshDaemonRole } from '../repo-mesh-types.js'; -import { BeadsDB } from './beads-db.js'; export type MeshTaskStatus = 'pending' | 'assigned' | 'completed' | 'failed' | 'cancelled'; export type MeshActiveTaskStatus = Extract; @@ -116,22 +115,34 @@ function getLockPath(meshId: string): string { * to prevent deadlock (best-effort — far better than no locking at all). */ function withQueueLock(meshId: string, fn: () => T): T { - // With SQLite BeadsDB, we don't need a file lock for everything, - // but we can retain the lock if complex orchestration checks rely on it. - // However, the most robust way is to just let SQLite handle concurrency. - // We'll keep the lock signature for API compatibility but execute directly. - return fn(); + const lockPath = getLockPath(meshId); + let fd = -1; + for (let i = 0; i < 10; i++) { + try { fd = openSync(lockPath, 'wx'); break; } catch { + const deadline = Date.now() + 30; + while (Date.now() < deadline) { /* spin */ } + } + } + try { return fn(); } finally { + if (fd !== -1) try { closeSync(fd); } catch { /* noop */ } + try { unlinkSync(lockPath); } catch { /* already removed */ } + } } function readQueue(meshId: string): MeshWorkQueueEntry[] { - return BeadsDB.getInstance().getQueueEntries(meshId); + const path = getQueuePath(meshId); + if (!existsSync(path)) return []; + try { + const content = readFileSync(path, 'utf-8'); + return JSON.parse(content) as MeshWorkQueueEntry[]; + } catch { + return []; + } } function writeQueue(meshId: string, queue: MeshWorkQueueEntry[]): void { - const db = BeadsDB.getInstance(); - for (const q of queue) { - db.upsertQueueEntry(q); - } + const path = getQueuePath(meshId); + writeFileSync(path, JSON.stringify(queue, null, 2), 'utf-8'); } /** @@ -222,23 +233,6 @@ export function updateTaskStatus( const queue = readQueue(meshId); const idx = queue.findIndex(q => q.id === taskId); if (idx === -1) return null; - - // --- GasTown Refinery Gate (Auto-requeue on failure) --- - if (status === 'failed') { - const currentRequeueCount = queue[idx].requeueCount || 0; - if (currentRequeueCount < 3) { - queue[idx].status = 'pending'; - queue[idx].assignedNodeId = undefined; - queue[idx].assignedSessionId = undefined; - queue[idx].requeueCount = currentRequeueCount + 1; - queue[idx].requeueReason = `Refinery Gate: auto-requeue after failure (attempt ${currentRequeueCount + 1}/3)`; - queue[idx].requeuedAt = new Date().toISOString(); - queue[idx].updatedAt = new Date().toISOString(); - writeQueue(meshId, queue); - return queue[idx]; - } - } - queue[idx].status = status; queue[idx].updatedAt = new Date().toISOString(); writeQueue(meshId, queue); @@ -348,23 +342,6 @@ export function updateSessionTaskStatus( if (time > bestTime) { bestTime = time; bestIdx = i; } } if (bestIdx === -1) return null; - - // --- GasTown Refinery Gate (Auto-requeue on failure) --- - if (status === 'failed') { - const currentRequeueCount = queue[bestIdx].requeueCount || 0; - if (currentRequeueCount < 3) { - queue[bestIdx].status = 'pending'; - queue[bestIdx].assignedNodeId = undefined; - queue[bestIdx].assignedSessionId = undefined; - queue[bestIdx].requeueCount = currentRequeueCount + 1; - queue[bestIdx].requeueReason = `Refinery Gate: auto-requeue after failure (attempt ${currentRequeueCount + 1}/3)`; - queue[bestIdx].requeuedAt = new Date().toISOString(); - queue[bestIdx].updatedAt = new Date().toISOString(); - writeQueue(meshId, queue); - return queue[bestIdx]; - } - } - queue[bestIdx].status = status; queue[bestIdx].updatedAt = new Date().toISOString(); writeQueue(meshId, queue);