From e99423da9729fa8da8e3d73b11a775300cc3399c Mon Sep 17 00:00:00 2001 From: Eve Date: Fri, 8 May 2026 16:11:49 +0800 Subject: [PATCH] refactor: package-own watchdog orchestrator entrypoint --- .../profiles/strict-manager-mode.profile.json | 12 +-- .../src/adapters/runtime-binding.mjs | 18 +++- .../src/storage/profile-artifact.mjs | 2 +- .../src/storage/profile-generator.mjs | 14 +-- ...ecision-store-runtime.integration.test.mjs | 12 +-- .../governance-contract.integration.test.mjs | 16 ++-- .../test/profile-artifact.test.mjs | 40 ++++---- .../test/profile-generator.test.mjs | 2 +- .../runtime-integrated.integration.test.mjs | 12 +-- .../test/watchdog-chain.integration.test.mjs | 20 ++-- scripts/watchdog_auto_notify_orchestrator.mjs | 94 +++++++++++++++++++ 11 files changed, 175 insertions(+), 67 deletions(-) create mode 100644 scripts/watchdog_auto_notify_orchestrator.mjs diff --git a/plugins/reporting-governance/profiles/strict-manager-mode.profile.json b/plugins/reporting-governance/profiles/strict-manager-mode.profile.json index 4b5a522..cfe2760 100644 --- a/plugins/reporting-governance/profiles/strict-manager-mode.profile.json +++ b/plugins/reporting-governance/profiles/strict-manager-mode.profile.json @@ -15,13 +15,13 @@ }, "bindings": { "runtime": "openclaw", - "entrypoint": "scripts/watchdog_auto_notify_orchestrator.mjs", + "entrypoint": "plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs", "scripts": { - "watchdog": "scripts/long_task_watchdog.mjs", - "dispatcher": "scripts/operator_notify_dispatcher.mjs", - "bridgeSupervisor": "scripts/operator_notify_bridge_supervisor.mjs", - "senderBinding": "scripts/operator_notify_sender_binding.mjs", - "orchestrator": "scripts/watchdog_auto_notify_orchestrator.mjs" + "watchdog": "plugins/reporting-governance/scripts/long_task_watchdog.mjs", + "dispatcher": "plugins/reporting-governance/scripts/operator_notify_dispatcher.mjs", + "bridgeSupervisor": "plugins/reporting-governance/scripts/operator_notify_bridge_supervisor.mjs", + "senderBinding": "plugins/reporting-governance/scripts/operator_notify_sender_binding.mjs", + "orchestrator": "plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs" }, "artifact_roots": { "watchdogEvidence": "state/long-task-watchdog", diff --git a/plugins/reporting-governance/src/adapters/runtime-binding.mjs b/plugins/reporting-governance/src/adapters/runtime-binding.mjs index 64380ed..329254f 100644 --- a/plugins/reporting-governance/src/adapters/runtime-binding.mjs +++ b/plugins/reporting-governance/src/adapters/runtime-binding.mjs @@ -1,10 +1,14 @@ +import fs from 'node:fs'; import path from 'node:path'; import process from 'node:process'; const ENV_PREFIX = 'OPENCLAW_REPORTING_GOVERNANCE_'; const packageRoot = path.resolve(import.meta.dirname, '..', '..'); -const repoRoot = packageRoot; +const repoRoot = path.resolve(packageRoot, '..', '..'); + +const DEFAULT_SCRIPT_ROOT = path.join(packageRoot, 'scripts'); +const LEGACY_SCRIPT_ROOT = path.join(repoRoot, 'scripts'); const SCRIPT_NAMES = { watchdog: 'long_task_watchdog.mjs', @@ -26,6 +30,14 @@ function normalizeString(value) { return typeof value === 'string' && value.trim() ? value.trim() : null; } +function defaultScriptPath(fileName) { + const packagePath = path.join(DEFAULT_SCRIPT_ROOT, fileName); + if (fs.existsSync(packagePath)) { + return packagePath; + } + return path.join(LEGACY_SCRIPT_ROOT, fileName); +} + export function resolveRepoPath(...segments) { return path.join(repoRoot, ...segments); } @@ -36,7 +48,7 @@ export function createRuntimeBinding(overrides = {}) { for (const [key, fileName] of Object.entries(SCRIPT_NAMES)) { const envValue = normalizeString(process.env[SCRIPT_ENV_KEYS[key]]); const overrideValue = normalizeString(overrides?.scripts?.[key]); - scripts[key] = path.resolve(overrideValue ?? envValue ?? resolveRepoPath('scripts', fileName)); + scripts[key] = path.resolve(overrideValue ?? envValue ?? defaultScriptPath(fileName)); } return { @@ -56,4 +68,4 @@ export function resolveScriptPath(name, options = {}) { return path.resolve(scriptPath); } -export { packageRoot, repoRoot, SCRIPT_ENV_KEYS, SCRIPT_NAMES }; +export { packageRoot, repoRoot, SCRIPT_ENV_KEYS, SCRIPT_NAMES, DEFAULT_SCRIPT_ROOT, LEGACY_SCRIPT_ROOT }; diff --git a/plugins/reporting-governance/src/storage/profile-artifact.mjs b/plugins/reporting-governance/src/storage/profile-artifact.mjs index f0ec64c..0b34cdb 100644 --- a/plugins/reporting-governance/src/storage/profile-artifact.mjs +++ b/plugins/reporting-governance/src/storage/profile-artifact.mjs @@ -2,7 +2,7 @@ import fs from 'node:fs'; import path from 'node:path'; const packageRoot = path.resolve(import.meta.dirname, '..', '..'); -const repoRoot = packageRoot; +const repoRoot = path.resolve(packageRoot, '..', '..'); const EXPECTED_KIND = 'DeploymentProfileArtifact'; const EXPECTED_API_VERSION = 'reporting-governance/v1alpha1'; diff --git a/plugins/reporting-governance/src/storage/profile-generator.mjs b/plugins/reporting-governance/src/storage/profile-generator.mjs index abb8bb5..3cf9549 100644 --- a/plugins/reporting-governance/src/storage/profile-generator.mjs +++ b/plugins/reporting-governance/src/storage/profile-generator.mjs @@ -10,6 +10,7 @@ const schemaPath = path.resolve(packageRoot, 'schemas', 'reporting-governance', const artifactSchemaRefPath = './schemas/reporting-governance/deployment-profile.schema.json'; const defaultSourceProfilePath = path.join('profiles-src', 'strict-manager-mode.yaml'); const packageScriptsRoot = 'scripts'; +const packageScriptsRepoPrefix = 'plugins/reporting-governance'; function readText(filePath) { return fs.readFileSync(filePath, 'utf8'); @@ -73,6 +74,7 @@ export function generateDeploymentProfileArtifact(profile, { sourceProfile } = { const validated = validateDeploymentProfileSchema(profile); const id = validated.metadata.id; const sourceProfilePath = sourceProfile ?? (id === 'strict-manager-mode' ? defaultSourceProfilePath : path.join('profiles-src', `${id}.yaml`)); + const scriptPrefix = `${packageScriptsRepoPrefix}/${packageScriptsRoot}`; return { $schema: artifactSchemaRefPath, @@ -91,13 +93,13 @@ export function generateDeploymentProfileArtifact(profile, { sourceProfile } = { }, bindings: { runtime: validated.metadata.runtime, - entrypoint: `${packageScriptsRoot}/watchdog_auto_notify_orchestrator.mjs`, + entrypoint: `${scriptPrefix}/watchdog_auto_notify_orchestrator.mjs`, scripts: { - watchdog: `${packageScriptsRoot}/long_task_watchdog.mjs`, - dispatcher: `${packageScriptsRoot}/operator_notify_dispatcher.mjs`, - bridgeSupervisor: `${packageScriptsRoot}/operator_notify_bridge_supervisor.mjs`, - senderBinding: `${packageScriptsRoot}/operator_notify_sender_binding.mjs`, - orchestrator: `${packageScriptsRoot}/watchdog_auto_notify_orchestrator.mjs`, + watchdog: `${scriptPrefix}/long_task_watchdog.mjs`, + dispatcher: `${scriptPrefix}/operator_notify_dispatcher.mjs`, + bridgeSupervisor: `${scriptPrefix}/operator_notify_bridge_supervisor.mjs`, + senderBinding: `${scriptPrefix}/operator_notify_sender_binding.mjs`, + orchestrator: `${scriptPrefix}/watchdog_auto_notify_orchestrator.mjs`, }, artifact_roots: { watchdogEvidence: 'state/long-task-watchdog', diff --git a/plugins/reporting-governance/test/decision-store-runtime.integration.test.mjs b/plugins/reporting-governance/test/decision-store-runtime.integration.test.mjs index c7ba4b7..3fa6766 100644 --- a/plugins/reporting-governance/test/decision-store-runtime.integration.test.mjs +++ b/plugins/reporting-governance/test/decision-store-runtime.integration.test.mjs @@ -66,13 +66,13 @@ const strictProfileArtifact = { }, bindings: { runtime: 'openclaw', - entrypoint: 'scripts/watchdog_auto_notify_orchestrator.mjs', + entrypoint: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs', scripts: { - watchdog: 'scripts/long_task_watchdog.mjs', - dispatcher: 'scripts/operator_notify_dispatcher.mjs', - bridgeSupervisor: 'scripts/operator_notify_bridge_supervisor.mjs', - senderBinding: 'scripts/operator_notify_sender_binding.mjs', - orchestrator: 'scripts/watchdog_auto_notify_orchestrator.mjs' + watchdog: 'plugins/reporting-governance/scripts/long_task_watchdog.mjs', + dispatcher: 'plugins/reporting-governance/scripts/operator_notify_dispatcher.mjs', + bridgeSupervisor: 'plugins/reporting-governance/scripts/operator_notify_bridge_supervisor.mjs', + senderBinding: 'plugins/reporting-governance/scripts/operator_notify_sender_binding.mjs', + orchestrator: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs' }, artifact_roots: { queueItems: 'state/operator-notify-queue' diff --git a/plugins/reporting-governance/test/governance-contract.integration.test.mjs b/plugins/reporting-governance/test/governance-contract.integration.test.mjs index a2289f5..28ca498 100644 --- a/plugins/reporting-governance/test/governance-contract.integration.test.mjs +++ b/plugins/reporting-governance/test/governance-contract.integration.test.mjs @@ -313,13 +313,13 @@ test('executeGovernanceContract exposes deployment binding when profile artifact ...strictProfile.spec, bindings: { runtime: 'openclaw', - entrypoint: 'scripts/watchdog_auto_notify_orchestrator.mjs', + entrypoint: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs', scripts: { - watchdog: 'scripts/long_task_watchdog.mjs', - dispatcher: 'scripts/operator_notify_dispatcher.mjs', - bridgeSupervisor: 'scripts/operator_notify_bridge_supervisor.mjs', - senderBinding: 'scripts/operator_notify_sender_binding.mjs', - orchestrator: 'scripts/watchdog_auto_notify_orchestrator.mjs' + watchdog: 'plugins/reporting-governance/scripts/long_task_watchdog.mjs', + dispatcher: 'plugins/reporting-governance/scripts/operator_notify_dispatcher.mjs', + bridgeSupervisor: 'plugins/reporting-governance/scripts/operator_notify_bridge_supervisor.mjs', + senderBinding: 'plugins/reporting-governance/scripts/operator_notify_sender_binding.mjs', + orchestrator: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs' }, artifact_roots: { queueItems: 'state/operator-notify-queue' @@ -344,7 +344,7 @@ test('executeGovernanceContract exposes deployment binding when profile artifact }); assert.equal(result.preflight.status, 'pass'); - assert.equal(result.deploymentBinding.entrypoint, path.resolve(repoRoot, 'scripts/watchdog_auto_notify_orchestrator.mjs')); - assert.equal(result.deploymentBinding.scripts.dispatcher, path.resolve(repoRoot, 'scripts/operator_notify_dispatcher.mjs')); + assert.equal(result.deploymentBinding.entrypoint, path.resolve(repoRoot, 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs')); + assert.equal(result.deploymentBinding.scripts.dispatcher, path.resolve(repoRoot, 'plugins/reporting-governance/scripts/operator_notify_dispatcher.mjs')); assert.equal(result.deploymentBinding.artifactRoots.queueItems, path.resolve(repoRoot, 'state/operator-notify-queue')); }); diff --git a/plugins/reporting-governance/test/profile-artifact.test.mjs b/plugins/reporting-governance/test/profile-artifact.test.mjs index e539b6b..b7bae74 100644 --- a/plugins/reporting-governance/test/profile-artifact.test.mjs +++ b/plugins/reporting-governance/test/profile-artifact.test.mjs @@ -13,7 +13,7 @@ import { import { createRuntimeBinding } from '../src/adapters/index.mjs'; const packageRoot = path.resolve(import.meta.dirname, '..'); -const repoRoot = path.resolve(packageRoot); +const repoRoot = path.resolve(packageRoot, '..', '..'); function createArtifact(overrides = {}) { return { @@ -23,8 +23,8 @@ function createArtifact(overrides = {}) { package: { pluginVersion: '0.1.0-mainline' }, bindings: { runtime: 'openclaw', - entrypoint: 'scripts/watchdog_auto_notify_orchestrator.mjs', - scripts: { watchdog: 'scripts/long_task_watchdog.mjs' }, + entrypoint: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs', + scripts: { watchdog: 'plugins/reporting-governance/scripts/long_task_watchdog.mjs' }, artifact_roots: { queueItems: 'state/operator-notify-queue' }, }, }, @@ -49,8 +49,8 @@ test('deployment binding contract resolves package artifact into real repo scrip assert.equal(binding.runtime, 'openclaw'); assert.equal(binding.pluginVersion, '0.1.0-mainline'); assert.equal(binding.compatibilityMode, 'strict_envelope'); - assert.equal(binding.entrypoint, path.resolve(repoRoot, 'scripts/watchdog_auto_notify_orchestrator.mjs')); - assert.equal(binding.scripts.watchdog, path.resolve(repoRoot, 'scripts/long_task_watchdog.mjs')); + assert.equal(binding.entrypoint, path.resolve(repoRoot, 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs')); + assert.equal(binding.scripts.watchdog, path.resolve(repoRoot, 'plugins/reporting-governance/scripts/long_task_watchdog.mjs')); assert.equal(binding.artifactRoots.queueItems, path.resolve(repoRoot, 'state/operator-notify-queue')); assert.equal(fs.existsSync(binding.scripts.orchestrator), true); }); @@ -81,7 +81,7 @@ test('deployment profile artifact validation fails closed on boundary drift', () package: { pluginVersion: '0.1.0-mainline' }, bindings: { entrypoint: '', - scripts: { watchdog: 'scripts/long_task_watchdog.mjs' }, + scripts: { watchdog: 'plugins/reporting-governance/scripts/long_task_watchdog.mjs' }, artifact_roots: { queueItems: 'state/operator-notify-queue' }, }, }, @@ -94,7 +94,7 @@ test('deployment profile artifact validation fails closed on boundary drift', () spec: { package: { pluginVersion: '' }, bindings: { - entrypoint: 'scripts/watchdog_auto_notify_orchestrator.mjs', + entrypoint: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs', scripts: { watchdog: '' }, artifact_roots: { queueItems: 'state/operator-notify-queue' }, }, @@ -108,7 +108,7 @@ test('deployment profile artifact validation fails closed on boundary drift', () spec: { package: { pluginVersion: '0.1.0-mainline' }, bindings: { - entrypoint: 'scripts/watchdog_auto_notify_orchestrator.mjs', + entrypoint: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs', scripts: [], artifact_roots: { queueItems: 'state/operator-notify-queue' }, }, @@ -125,7 +125,7 @@ test('deployment profile artifact validation rejects absolute binding paths', () package: { pluginVersion: '0.1.0-mainline' }, bindings: { entrypoint: '/abs/path', - scripts: { watchdog: 'scripts/long_task_watchdog.mjs' }, + scripts: { watchdog: 'plugins/reporting-governance/scripts/long_task_watchdog.mjs' }, artifact_roots: { queueItems: 'state/operator-notify-queue' }, }, }, @@ -138,7 +138,7 @@ test('deployment profile artifact validation rejects absolute binding paths', () spec: { package: { pluginVersion: '0.1.0-mainline' }, bindings: { - entrypoint: 'scripts/watchdog_auto_notify_orchestrator.mjs', + entrypoint: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs', scripts: { watchdog: '/abs/path' }, artifact_roots: { queueItems: 'state/operator-notify-queue' }, }, @@ -152,8 +152,8 @@ test('deployment profile artifact validation rejects absolute binding paths', () spec: { package: { pluginVersion: '0.1.0-mainline' }, bindings: { - entrypoint: 'scripts/watchdog_auto_notify_orchestrator.mjs', - scripts: { watchdog: 'scripts/long_task_watchdog.mjs' }, + entrypoint: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs', + scripts: { watchdog: 'plugins/reporting-governance/scripts/long_task_watchdog.mjs' }, artifact_roots: { queueItems: '/abs/path' }, }, }, @@ -169,7 +169,7 @@ test('deployment profile artifact validation rejects escape paths after resoluti package: { pluginVersion: '0.1.0-mainline' }, bindings: { entrypoint: '../../escape', - scripts: { watchdog: 'scripts/long_task_watchdog.mjs' }, + scripts: { watchdog: 'plugins/reporting-governance/scripts/long_task_watchdog.mjs' }, artifact_roots: { queueItems: 'state/operator-notify-queue' }, }, }, @@ -183,7 +183,7 @@ test('deployment profile artifact validation rejects escape paths after resoluti spec: { package: { pluginVersion: '0.1.0-mainline' }, bindings: { - entrypoint: 'scripts/watchdog_auto_notify_orchestrator.mjs', + entrypoint: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs', scripts: { watchdog: '../../escape' }, artifact_roots: { queueItems: 'state/operator-notify-queue' }, }, @@ -199,8 +199,8 @@ test('deployment profile artifact validation rejects escape paths after resoluti spec: { package: { pluginVersion: '0.1.0-mainline' }, bindings: { - entrypoint: 'scripts/watchdog_auto_notify_orchestrator.mjs', - scripts: { watchdog: 'scripts/long_task_watchdog.mjs' }, + entrypoint: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs', + scripts: { watchdog: 'plugins/reporting-governance/scripts/long_task_watchdog.mjs' }, artifact_roots: { queueItems: '../escape' }, }, }, @@ -216,9 +216,9 @@ test('deployment binding contract allows normalized in-root paths that contain d package: { pluginVersion: '0.1.0-mainline' }, bindings: { runtime: 'openclaw', - entrypoint: 'scripts/../scripts/watchdog_auto_notify_orchestrator.mjs', + entrypoint: 'plugins/reporting-governance/scripts/../scripts/watchdog_auto_notify_orchestrator.mjs', scripts: { - watchdog: 'scripts/./long_task_watchdog.mjs', + watchdog: 'plugins/reporting-governance/scripts/./long_task_watchdog.mjs', }, artifact_roots: { queueItems: 'state/../state/operator-notify-queue', @@ -229,8 +229,8 @@ test('deployment binding contract allows normalized in-root paths that contain d repoRootOverride: repoRoot, }); - assert.equal(binding.entrypoint, path.resolve(repoRoot, 'scripts/watchdog_auto_notify_orchestrator.mjs')); - assert.equal(binding.scripts.watchdog, path.resolve(repoRoot, 'scripts/long_task_watchdog.mjs')); + assert.equal(binding.entrypoint, path.resolve(repoRoot, 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs')); + assert.equal(binding.scripts.watchdog, path.resolve(repoRoot, 'plugins/reporting-governance/scripts/long_task_watchdog.mjs')); assert.equal(binding.artifactRoots.queueItems, path.resolve(repoRoot, 'state/operator-notify-queue')); }); diff --git a/plugins/reporting-governance/test/profile-generator.test.mjs b/plugins/reporting-governance/test/profile-generator.test.mjs index 0f61c3b..56a4b57 100644 --- a/plugins/reporting-governance/test/profile-generator.test.mjs +++ b/plugins/reporting-governance/test/profile-generator.test.mjs @@ -380,7 +380,7 @@ test('yaml to artifact generation produces validator-compatible package artifact assert.equal(artifact.kind, 'DeploymentProfileArtifact'); assert.equal(artifact.metadata.source_profile, 'profiles/demo.yaml'); - assert.equal(artifact.spec.bindings.entrypoint, 'scripts/watchdog_auto_notify_orchestrator.mjs'); + assert.equal(artifact.spec.bindings.entrypoint, 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs'); assert.doesNotThrow(() => validateDeploymentProfileArtifact(artifact)); }); diff --git a/plugins/reporting-governance/test/runtime-integrated.integration.test.mjs b/plugins/reporting-governance/test/runtime-integrated.integration.test.mjs index 390551a..70cc899 100644 --- a/plugins/reporting-governance/test/runtime-integrated.integration.test.mjs +++ b/plugins/reporting-governance/test/runtime-integrated.integration.test.mjs @@ -93,13 +93,13 @@ const strictProfileArtifact = { }, bindings: { runtime: 'openclaw', - entrypoint: 'scripts/watchdog_auto_notify_orchestrator.mjs', + entrypoint: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs', scripts: { - watchdog: 'scripts/long_task_watchdog.mjs', - dispatcher: 'scripts/operator_notify_dispatcher.mjs', - bridgeSupervisor: 'scripts/operator_notify_bridge_supervisor.mjs', - senderBinding: 'scripts/operator_notify_sender_binding.mjs', - orchestrator: 'scripts/watchdog_auto_notify_orchestrator.mjs' + watchdog: 'plugins/reporting-governance/scripts/long_task_watchdog.mjs', + dispatcher: 'plugins/reporting-governance/scripts/operator_notify_dispatcher.mjs', + bridgeSupervisor: 'plugins/reporting-governance/scripts/operator_notify_bridge_supervisor.mjs', + senderBinding: 'plugins/reporting-governance/scripts/operator_notify_sender_binding.mjs', + orchestrator: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs' }, artifact_roots: { queueItems: 'state/operator-notify-queue' diff --git a/plugins/reporting-governance/test/watchdog-chain.integration.test.mjs b/plugins/reporting-governance/test/watchdog-chain.integration.test.mjs index e9abb52..2b2425d 100644 --- a/plugins/reporting-governance/test/watchdog-chain.integration.test.mjs +++ b/plugins/reporting-governance/test/watchdog-chain.integration.test.mjs @@ -127,7 +127,7 @@ test('orchestrator adapter can bootstrap from profile artifact loader path', () const result = runOrchestratorAdapter({ profileId: 'strict-manager-mode', - repoRootOverride: path.resolve(packageRoot), + repoRootOverride: path.resolve(packageRoot, '..', '..'), state: statePath, evidenceDir: path.join(root, 'evidence'), eventDir: path.join(root, 'events'), @@ -160,7 +160,7 @@ test('orchestrator adapter can use artifact_roots.queueItems as the default queu const result = runOrchestratorAdapter({ profileId: 'strict-manager-mode', - repoRootOverride: path.resolve(packageRoot), + repoRootOverride: path.resolve(packageRoot, '..', '..'), state: statePath, evidenceDir: path.join(root, 'evidence'), eventDir: path.join(root, 'events'), @@ -184,7 +184,7 @@ test('orchestrator adapter fails closed at use time when artifact_roots.queueIte const fakeRepoRoot = path.join(sandbox, 'repo'); const outsideRoot = path.join(sandbox, 'outside'); const realRepoRoot = path.resolve(packageRoot); - fs.mkdirSync(path.join(fakeRepoRoot, 'scripts'), { recursive: true }); + fs.mkdirSync(path.join(fakeRepoRoot, 'plugins', 'reporting-governance', 'scripts'), { recursive: true }); fs.mkdirSync(path.join(fakeRepoRoot, 'state', 'operator-notify-queue'), { recursive: true }); fs.mkdirSync(outsideRoot, { recursive: true }); for (const name of [ @@ -194,7 +194,7 @@ test('orchestrator adapter fails closed at use time when artifact_roots.queueIte 'operator_notify_bridge_supervisor.mjs', 'operator_notify_sender_binding.mjs', ]) { - fs.copyFileSync(path.join(realRepoRoot, 'scripts', name), path.join(fakeRepoRoot, 'scripts', name)); + fs.copyFileSync(path.join(realRepoRoot, 'scripts', name), path.join(fakeRepoRoot, 'plugins', 'reporting-governance', 'scripts', name)); } const deploymentBinding = createDeploymentBindingContract({ @@ -210,13 +210,13 @@ test('orchestrator adapter fails closed at use time when artifact_roots.queueIte package: { pluginVersion: '0.1.0-mainline' }, bindings: { runtime: 'openclaw', - entrypoint: 'scripts/watchdog_auto_notify_orchestrator.mjs', + entrypoint: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs', scripts: { - watchdog: 'scripts/long_task_watchdog.mjs', - dispatcher: 'scripts/operator_notify_dispatcher.mjs', - bridgeSupervisor: 'scripts/operator_notify_bridge_supervisor.mjs', - senderBinding: 'scripts/operator_notify_sender_binding.mjs', - orchestrator: 'scripts/watchdog_auto_notify_orchestrator.mjs' + watchdog: 'plugins/reporting-governance/scripts/long_task_watchdog.mjs', + dispatcher: 'plugins/reporting-governance/scripts/operator_notify_dispatcher.mjs', + bridgeSupervisor: 'plugins/reporting-governance/scripts/operator_notify_bridge_supervisor.mjs', + senderBinding: 'plugins/reporting-governance/scripts/operator_notify_sender_binding.mjs', + orchestrator: 'plugins/reporting-governance/scripts/watchdog_auto_notify_orchestrator.mjs' }, artifact_roots: { queueItems: 'state/operator-notify-queue' diff --git a/scripts/watchdog_auto_notify_orchestrator.mjs b/scripts/watchdog_auto_notify_orchestrator.mjs new file mode 100644 index 0000000..cce1877 --- /dev/null +++ b/scripts/watchdog_auto_notify_orchestrator.mjs @@ -0,0 +1,94 @@ +#!/usr/bin/env node + +import process from 'node:process'; +import { runOrchestratorAdapter } from '../plugins/reporting-governance/src/adapters/orchestrator.mjs'; + +const cliArgs = parseCliArgs(process.argv.slice(2)); + +try { + const payload = runOrchestratorAdapter({ + compact: cliArgs.compact, + ...cliArgs, + }); + process.stdout.write(`${JSON.stringify(payload, null, cliArgs.compact ? 0 : 2)}\n`); +} catch (error) { + process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`); + process.exit(1); +} + +function parseCliArgs(argv) { + const args = { + state: null, + evidenceDir: null, + eventDir: null, + queueDir: null, + spoolDir: null, + receiptDir: null, + watchdogScript: null, + dispatcherScript: null, + supervisorScript: null, + senderCommand: null, + senderMode: null, + openclawBin: 'openclaw', + now: null, + compact: false, + writeState: false, + claim: false, + dryRun: false, + help: false, + }; + + for (let i = 0; i < argv.length; i += 1) { + const token = argv[i]; + if (token === '--compact') { args.compact = true; continue; } + if (token === '--write-state') { args.writeState = true; continue; } + if (token === '--claim') { args.claim = true; continue; } + if (token === '--dry-run') { args.dryRun = true; continue; } + if (token === '--help' || token === '-h') { args.help = true; continue; } + + const pairs = [ + ['--state', 'state'], + ['--evidence-dir', 'evidenceDir'], + ['--event-dir', 'eventDir'], + ['--queue-dir', 'queueDir'], + ['--spool-dir', 'spoolDir'], + ['--receipt-dir', 'receiptDir'], + ['--watchdog-script', 'watchdogScript'], + ['--dispatcher-script', 'dispatcherScript'], + ['--supervisor-script', 'supervisorScript'], + ['--sender-command', 'senderCommand'], + ['--sender-mode', 'senderMode'], + ['--openclaw-bin', 'openclawBin'], + ['--now', 'now'], + ]; + + let matched = false; + for (const [flag, key] of pairs) { + if (token === flag) { + args[key] = argv[i + 1] ?? args[key]; + i += 1; + matched = true; + break; + } + if (token.startsWith(`${flag}=`)) { + args[key] = token.slice(flag.length + 1) || args[key]; + matched = true; + break; + } + } + if (matched) continue; + } + + if (args.help) { + process.stdout.write([ + 'Usage:', + ' node scripts/watchdog_auto_notify_orchestrator.mjs [--write-state] [--claim] [--dry-run] [--sender-command ] [--sender-mode shim|openclaw-cli] [--openclaw-bin ] [--now ] [--compact]', + '', + 'Repo-root shim that forwards to package-owned orchestrator implementation.', + 'Default runtime binding now resolves package script first; env/override can still point elsewhere.', + ].join('\n') + '\n'); + process.exit(0); + } + + return args; +}