diff --git a/plugins/reporting-governance/src/core/runtime-integrated.mjs b/plugins/reporting-governance/src/core/runtime-integrated.mjs index 24c4c04..ce888cf 100644 --- a/plugins/reporting-governance/src/core/runtime-integrated.mjs +++ b/plugins/reporting-governance/src/core/runtime-integrated.mjs @@ -1,10 +1,10 @@ import { executeGovernanceContract } from './execute-governance-contract.mjs'; import { runOrchestratorAdapter } from '../adapters/orchestrator.mjs'; -const ACTION_ADAPTER_ROUTING = Object.freeze({ +const ADAPTER_ACTION_RUNNER_ROUTES = Object.freeze({ notify_operator: { adapter: 'orchestrator', - reason: 'deployment binding + adapter action routed into orchestrator adapter', + reason: 'adapter_action notify_operator routed to orchestrator adapter runner', run: ({ governance, repoRootOverride, runtime }) => runOrchestratorAdapter({ deploymentBinding: governance.deploymentBinding, repoRootOverride, @@ -13,35 +13,27 @@ const ACTION_ADAPTER_ROUTING = Object.freeze({ }, }); +function createNotAttemptedResult(reason) { + return { + attempted: false, + adapter: null, + action: null, + reason, + runtimeExecution: null, + }; +} + function resolveRuntimeRoute({ governance, runtime, repoRootOverride }) { if (!runtime) { - return { - attempted: false, - adapter: null, - action: null, - reason: 'runtime execution not attempted', - runtimeExecution: null, - }; + return createNotAttemptedResult('runtime execution not attempted'); } if (governance.preflight?.status !== 'pass') { - return { - attempted: false, - adapter: null, - action: null, - reason: 'runtime execution not attempted: compatibility preflight did not pass', - runtimeExecution: null, - }; + return createNotAttemptedResult('runtime execution not attempted: compatibility preflight did not pass'); } if (!governance.deploymentBinding) { - return { - attempted: false, - adapter: null, - action: null, - reason: 'runtime execution not attempted: deployment binding is missing', - runtimeExecution: null, - }; + return createNotAttemptedResult('runtime execution not attempted: deployment binding is missing'); } const adapterActions = Array.isArray(governance.contract?.adapter_actions) @@ -49,7 +41,7 @@ function resolveRuntimeRoute({ governance, runtime, repoRootOverride }) { : []; for (const action of adapterActions) { - const route = ACTION_ADAPTER_ROUTING[action]; + const route = ADAPTER_ACTION_RUNNER_ROUTES[action]; if (!route) continue; return { @@ -61,13 +53,7 @@ function resolveRuntimeRoute({ governance, runtime, repoRootOverride }) { }; } - return { - attempted: false, - adapter: null, - action: null, - reason: 'runtime execution not attempted: no routed adapter action matched runtime integration table', - runtimeExecution: null, - }; + return createNotAttemptedResult('runtime execution not attempted: no adapter_action matched an adapter runner route'); } export function executeRuntimeIntegratedGovernance({ @@ -111,6 +97,7 @@ export function executeRuntimeIntegratedGovernance({ } export const __testables = { - ACTION_ADAPTER_ROUTING, + ADAPTER_ACTION_RUNNER_ROUTES, + createNotAttemptedResult, resolveRuntimeRoute, }; diff --git a/plugins/reporting-governance/test/runtime-integrated.integration.test.mjs b/plugins/reporting-governance/test/runtime-integrated.integration.test.mjs index 81c34ae..53b57f9 100644 --- a/plugins/reporting-governance/test/runtime-integrated.integration.test.mjs +++ b/plugins/reporting-governance/test/runtime-integrated.integration.test.mjs @@ -45,6 +45,33 @@ const noSilencePack = { } }; +const unknownActionPack = { + metadata: { id: 'unknown-action-pack', severity_default: 'high' }, + spec: { + evaluation_mode: 'any_rule_match', + rules: [ + { + id: 'unknown-action-pack.route-to-unsupported-action', + title: 'Route to unsupported action for matrix coverage', + triggers: { event_types: ['silence_timeout'] }, + conditions: { + all: [ + { fact: 'checkpoint.is_overdue', equals: true } + ] + }, + decision_output: { + decision: 'force_checkpoint', + severity: 'high', + reason: 'checkpoint overdue triggered unsupported adapter action for route matrix coverage', + required_actions: [ + { action: 'rewrite_message', target: 'message_body', mandatory: true } + ] + } + } + ] + } +}; + const strictProfileArtifact = { kind: 'DeploymentProfileArtifact', apiVersion: 'reporting-governance/v1alpha1', @@ -127,30 +154,111 @@ function readSingleJson(dirPath) { return JSON.parse(fs.readFileSync(path.join(dirPath, files[0]), 'utf8')); } -test('runtime-integrated path wires executeGovernanceContract deployment binding into orchestrator execution', () => { +function createBaseArgs(overrides = {}) { + return { + event: { + type: 'silence_timeout', + payload: { + checkpoint_overdue: true, + } + }, + evidence: [ + { id: 'ev-watchdog', quality: 'moderate', is_new: true } + ], + capabilityDescriptor, + policyPacks: [noSilencePack], + context: { + signals: ['checkpoint_overdue'], + }, + profile: strictProfileArtifact, + packageVersion: '0.1.0-mainline', + repoRootOverride: repoRoot, + ...overrides, + }; +} + +function createStubRuntime() { + return { + state: path.join(repoRoot, 'tmp', 'unused-state.json'), + evidenceDir: path.join(repoRoot, 'tmp', 'unused-evidence'), + eventDir: path.join(repoRoot, 'tmp', 'unused-events'), + queueDir: path.join(repoRoot, 'tmp', 'unused-queue'), + spoolDir: path.join(repoRoot, 'tmp', 'unused-spool'), + receiptDir: path.join(repoRoot, 'tmp', 'unused-receipts'), + dryRun: true, + now: '2026-05-07T08:20:00.000Z', + }; +} + +test('runtime-integrated route matrix: no runtime stays planning-only', () => { + const result = executeRuntimeIntegratedGovernance(createBaseArgs()); + + assert.equal(result.preflight.status, 'pass'); + assert.equal(result.runtimeIntegration.attempted, false); + assert.equal(result.runtimeIntegration.reason, 'runtime execution not attempted'); + assert.equal(result.runtimeExecution, null); +}); + +test('runtime-integrated route matrix: preflight fail blocks runtime route', () => { + const result = executeRuntimeIntegratedGovernance(createBaseArgs({ + profile: { + ...strictProfileArtifact, + spec: { + ...strictProfileArtifact.spec, + package: { pluginVersion: '0.9.9-mismatch' }, + }, + }, + runtime: createStubRuntime(), + })); + + assert.equal(result.preflight.status, 'fail_closed'); + assert.equal(result.runtimeIntegration.attempted, false); + assert.equal(result.runtimeIntegration.reason, 'runtime execution not attempted: compatibility preflight did not pass'); + assert.equal(result.runtimeExecution, null); +}); + +test('runtime-integrated route matrix: missing deploymentBinding blocks runtime route', () => { + const profileWithoutBindings = { + ...strictProfileArtifact, + spec: { + ...strictProfileArtifact.spec, + }, + }; + delete profileWithoutBindings.spec.bindings; + + const result = executeRuntimeIntegratedGovernance(createBaseArgs({ + profile: profileWithoutBindings, + runtime: createStubRuntime(), + })); + + assert.equal(result.preflight.status, 'pass'); + assert.equal(result.deploymentBinding, null); + assert.equal(result.runtimeIntegration.attempted, false); + assert.equal(result.runtimeIntegration.reason, 'runtime execution not attempted: deployment binding is missing'); + assert.equal(result.runtimeExecution, null); +}); + +test('runtime-integrated route matrix: unknown adapter_action stays planning-only', () => { + const result = executeRuntimeIntegratedGovernance(createBaseArgs({ + policyPacks: [unknownActionPack], + runtime: createStubRuntime(), + })); + + assert.equal(result.preflight.status, 'pass'); + assert.deepEqual(result.contract.adapter_actions, []); + assert.deepEqual(result.contract.blocked_actions, ['rewrite_message']); + assert.equal(result.runtimeIntegration.attempted, false); + assert.equal(result.runtimeIntegration.reason, 'runtime execution not attempted: no adapter_action matched an adapter runner route'); + assert.equal(result.runtimeExecution, null); +}); + +test('runtime-integrated route matrix: matched adapter_action runs orchestrator adapter runner', () => { const root = createFixtureRoot(); try { mkdirs(root, ['evidence', 'events', 'queue', 'spool', 'receipts']); const statePath = writeState(root); - const result = executeRuntimeIntegratedGovernance({ - event: { - type: 'silence_timeout', - payload: { - checkpoint_overdue: true, - } - }, - evidence: [ - { id: 'ev-watchdog', quality: 'moderate', is_new: true } - ], - capabilityDescriptor, - policyPacks: [noSilencePack], - context: { - signals: ['checkpoint_overdue'], - }, - profile: strictProfileArtifact, - packageVersion: '0.1.0-mainline', - repoRootOverride: repoRoot, + const result = executeRuntimeIntegratedGovernance(createBaseArgs({ runtime: { state: statePath, evidenceDir: path.join(root, 'evidence'), @@ -162,13 +270,14 @@ test('runtime-integrated path wires executeGovernanceContract deployment binding dryRun: true, now: '2026-05-07T08:20:00.000Z', }, - }); + })); assert.equal(result.preflight.status, 'pass'); assert.equal(result.contract.decision, 'force_checkpoint'); assert.equal(result.runtimeIntegration.attempted, true); assert.equal(result.runtimeIntegration.adapter, 'orchestrator'); assert.equal(result.runtimeIntegration.action, 'notify_operator'); + assert.equal(result.runtimeIntegration.reason, 'adapter_action notify_operator routed to orchestrator adapter runner'); assert.equal(result.runtimeExecution.ok, true); assert.equal(result.runtimeExecution.result.dispatcher.dispatchedCount, 1); assert.equal(result.runtimeExecution.result.supervisor.pendingCount, 1); @@ -183,26 +292,3 @@ test('runtime-integrated path wires executeGovernanceContract deployment binding fs.rmSync(root, { recursive: true, force: true }); } }); - -test('runtime-integrated path stays planning-only when no runtime payload is supplied', () => { - const result = executeRuntimeIntegratedGovernance({ - event: { - type: 'silence_timeout', - payload: { - checkpoint_overdue: true, - } - }, - capabilityDescriptor, - policyPacks: [noSilencePack], - context: { - signals: ['checkpoint_overdue'], - }, - profile: strictProfileArtifact, - packageVersion: '0.1.0-mainline', - repoRootOverride: repoRoot, - }); - - assert.equal(result.preflight.status, 'pass'); - assert.equal(result.runtimeIntegration.attempted, false); - assert.equal(result.runtimeExecution, null); -});