test: add packed consumer install smoke
This commit is contained in:
@@ -269,5 +269,19 @@ npm run smoke
|
||||
reporting-governance-package-smoke --compact
|
||||
```
|
||||
|
||||
This smoke path uses package-local `profiles-src/`, `schemas/`, and `scripts/` only.
|
||||
Repeatable packed-consumer install smoke is now also covered by package test:
|
||||
|
||||
```bash
|
||||
cd plugins/reporting-governance
|
||||
npm pack
|
||||
node --test test/packed-consumer-install.smoke.test.mjs
|
||||
```
|
||||
|
||||
That path verifies a clean temp consumer can `npm install <tarball>` and then use only declared public surfaces:
|
||||
|
||||
- package root export: `@openclaw/plugin-reporting-governance`
|
||||
- exported subpath: `@openclaw/plugin-reporting-governance/adapters/orchestrator`
|
||||
- package bin: `reporting-governance-package-smoke`
|
||||
|
||||
This smoke path uses package-local `profiles-src/`, `schemas/`, and `scripts` only.
|
||||
It writes temp runtime artifacts under a caller-provided or temp workspace and verifies the dry-run orchestrator path end to end.
|
||||
|
||||
3
plugins/reporting-governance/package-lock.json
generated
3
plugins/reporting-governance/package-lock.json
generated
@@ -11,6 +11,9 @@
|
||||
"ajv": "^8.17.1",
|
||||
"ajv-formats": "^3.0.1",
|
||||
"yaml": "^2.8.0"
|
||||
},
|
||||
"bin": {
|
||||
"reporting-governance-package-smoke": "scripts/package-smoke.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"reporting-governance-package-smoke": "./scripts/package-smoke.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node --test test/package-structure.test.mjs test/policy-evaluator.test.mjs test/compatibility-preflight.test.mjs test/profile-artifact.test.mjs test/profile-generator.test.mjs test/decision-runner.test.mjs test/decision-store.test.mjs test/decision-store-runtime.integration.test.mjs test/governance-contract.integration.test.mjs test/watchdog-chain.integration.test.mjs test/runtime-integrated.integration.test.mjs test/exports-boundary.integration.test.mjs",
|
||||
"test": "node --test test/package-structure.test.mjs test/policy-evaluator.test.mjs test/compatibility-preflight.test.mjs test/profile-artifact.test.mjs test/profile-generator.test.mjs test/decision-runner.test.mjs test/decision-store.test.mjs test/decision-store-runtime.integration.test.mjs test/governance-contract.integration.test.mjs test/watchdog-chain.integration.test.mjs test/runtime-integrated.integration.test.mjs test/exports-boundary.integration.test.mjs test/packed-consumer-install.smoke.test.mjs",
|
||||
"smoke": "node ./scripts/package-smoke.mjs --compact"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://cowbay.org/schemas/reporting-governance/decision-record-artifact.schema.json",
|
||||
"title": "Reporting Governance Decision Record Artifact",
|
||||
"description": "Portable decision storage artifact combining canonical decision output, truthful receipt state, and source linkage.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["kind", "apiVersion", "metadata", "spec"],
|
||||
"properties": {
|
||||
"kind": { "const": "DecisionRecordArtifact" },
|
||||
"apiVersion": { "const": "reporting-governance/v1alpha1" },
|
||||
"metadata": { "$ref": "#/$defs/metadata" },
|
||||
"spec": { "$ref": "#/$defs/spec" }
|
||||
},
|
||||
"$defs": {
|
||||
"canonicalTimestamp": {
|
||||
"type": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$"
|
||||
},
|
||||
"sourceEventId": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"pattern": "^(?:evt_[A-Za-z0-9._:-]+|/?[A-Za-z0-9._-]+(?:/[A-Za-z0-9._-]+)+|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["record_id", "recorded_at", "policy_id", "decision", "correlation_id", "task_id", "event_id"],
|
||||
"properties": {
|
||||
"record_id": { "type": "string", "minLength": 1 },
|
||||
"recorded_at": { "$ref": "#/$defs/canonicalTimestamp" },
|
||||
"policy_id": { "type": "string", "minLength": 1 },
|
||||
"decision": { "type": "string", "minLength": 1 },
|
||||
"correlation_id": { "type": ["string", "null"] },
|
||||
"task_id": { "type": ["string", "null"] },
|
||||
"event_id": {
|
||||
"oneOf": [
|
||||
{ "$ref": "#/$defs/sourceEventId" },
|
||||
{ "type": "null" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"receiptAction": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"required": ["action", "mandatory"],
|
||||
"properties": {
|
||||
"action": { "type": "string", "minLength": 1 },
|
||||
"mandatory": { "type": "boolean" }
|
||||
}
|
||||
},
|
||||
"blockedAction": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"required": ["action", "mandatory"],
|
||||
"properties": {
|
||||
"action": { "type": "string", "minLength": 1 },
|
||||
"mandatory": { "type": "boolean" },
|
||||
"reason": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"receipt": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"required": [
|
||||
"policy_id",
|
||||
"decision",
|
||||
"status",
|
||||
"delivery_state",
|
||||
"enforcement_intent",
|
||||
"blocked_actions",
|
||||
"notes"
|
||||
],
|
||||
"properties": {
|
||||
"policy_id": { "type": "string", "minLength": 1 },
|
||||
"decision": { "type": "string", "minLength": 1 },
|
||||
"status": { "enum": ["planned", "acked", "blocked", "degraded", "failed"] },
|
||||
"delivery_state": { "enum": ["prepared", "queued", "dispatched", "pending_external_send", "acked", "blocked", "failed", "partial"] },
|
||||
"operator_notice_required": { "type": "boolean" },
|
||||
"enforcement_intent": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/receiptAction" }
|
||||
},
|
||||
"blocked_actions": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/blockedAction" }
|
||||
},
|
||||
"notes": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"failure_reason": { "type": "string", "minLength": 1 }
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"if": {
|
||||
"properties": { "status": { "const": "failed" } },
|
||||
"required": ["status"]
|
||||
},
|
||||
"then": { "required": ["failure_reason"] }
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": { "delivery_state": { "const": "partial" } },
|
||||
"required": ["delivery_state"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"blocked_actions": { "minItems": 1 },
|
||||
"enforcement_intent": { "minItems": 1 }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": { "status": { "const": "planned" } },
|
||||
"required": ["status"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"delivery_state": { "enum": ["prepared", "queued", "dispatched", "pending_external_send", "partial"] }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": { "status": { "const": "acked" } },
|
||||
"required": ["status"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"delivery_state": { "const": "acked" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": { "status": { "const": "blocked" } },
|
||||
"required": ["status"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"delivery_state": { "const": "blocked" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": { "status": { "const": "degraded" } },
|
||||
"required": ["status"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"delivery_state": { "enum": ["partial", "failed", "blocked"] }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": { "status": { "const": "failed" } },
|
||||
"required": ["status"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"delivery_state": { "const": "failed" }
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["event_id", "task_id", "correlation_id"],
|
||||
"properties": {
|
||||
"event_id": {
|
||||
"oneOf": [
|
||||
{ "$ref": "#/$defs/sourceEventId" },
|
||||
{ "type": "null" }
|
||||
]
|
||||
},
|
||||
"task_id": { "type": ["string", "null"] },
|
||||
"correlation_id": { "type": ["string", "null"] }
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["decision", "receipt", "source"],
|
||||
"properties": {
|
||||
"decision": { "$ref": "decision.schema.json" },
|
||||
"receipt": { "$ref": "#/$defs/receipt" },
|
||||
"source": { "$ref": "#/$defs/source" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"metadata": {
|
||||
"properties": {
|
||||
"event_id": { "type": "null" }
|
||||
},
|
||||
"required": ["event_id"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"spec": {
|
||||
"properties": {
|
||||
"source": {
|
||||
"properties": {
|
||||
"event_id": { "type": "null" }
|
||||
},
|
||||
"required": ["event_id"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"else": {
|
||||
"properties": {
|
||||
"spec": {
|
||||
"properties": {
|
||||
"source": {
|
||||
"properties": {
|
||||
"event_id": { "$ref": "#/$defs/sourceEventId" }
|
||||
},
|
||||
"required": ["event_id"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"spec": {
|
||||
"properties": {
|
||||
"source": {
|
||||
"properties": {
|
||||
"task_id": { "type": "null" },
|
||||
"correlation_id": { "type": "null" },
|
||||
"event_id": { "type": "null" }
|
||||
},
|
||||
"required": ["task_id", "correlation_id", "event_id"]
|
||||
}
|
||||
},
|
||||
"required": ["source"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://cowbay.org/schemas/reporting-governance/decision.schema.json",
|
||||
"title": "Reporting Governance Decision",
|
||||
"description": "Canonical policy decision schema for the reporting-governance plugin.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"decision",
|
||||
"policy_id",
|
||||
"severity",
|
||||
"reason",
|
||||
"rewritten_message",
|
||||
"suggested_status",
|
||||
"required_actions",
|
||||
"operator_notice"
|
||||
],
|
||||
"properties": {
|
||||
"decision": {
|
||||
"$ref": "#/$defs/decision",
|
||||
"description": "Canonical enforcement disposition."
|
||||
},
|
||||
"policy_id": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Stable policy rule identifier that produced the decision."
|
||||
},
|
||||
"severity": {
|
||||
"$ref": "#/$defs/severity",
|
||||
"description": "Risk or urgency classification for the decision."
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"description": "Human-readable rationale for the decision."
|
||||
},
|
||||
"rewritten_message": {
|
||||
"type": ["string", "null"],
|
||||
"description": "Replacement or annotated outgoing message text when governance rewrites or forces placeholder disclosure."
|
||||
},
|
||||
"suggested_status": {
|
||||
"$ref": "#/$defs/suggestedStatusOrNull",
|
||||
"description": "Recommended workflow status after enforcement, if any."
|
||||
},
|
||||
"required_actions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/requiredAction"
|
||||
},
|
||||
"description": "Ordered list of required enforcement actions."
|
||||
},
|
||||
"operator_notice": {
|
||||
"$ref": "#/$defs/operatorNoticeOrNull",
|
||||
"description": "Operator-visible notice requirement produced by the policy."
|
||||
}
|
||||
},
|
||||
"$defs": {
|
||||
"decision": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"allow",
|
||||
"rewrite",
|
||||
"block",
|
||||
"require_review",
|
||||
"force_checkpoint",
|
||||
"escalate",
|
||||
"downgrade_status",
|
||||
"annotate_placeholder"
|
||||
]
|
||||
},
|
||||
"severity": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"info",
|
||||
"low",
|
||||
"medium",
|
||||
"high",
|
||||
"critical"
|
||||
]
|
||||
},
|
||||
"suggestedStatus": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"in_progress",
|
||||
"pending_verification",
|
||||
"blocked",
|
||||
"failed",
|
||||
"awaiting_review",
|
||||
"completed"
|
||||
]
|
||||
},
|
||||
"suggestedStatusOrNull": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/$defs/suggestedStatus"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"actionVerb": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"dispatch_message",
|
||||
"rewrite_message",
|
||||
"append_audit_note",
|
||||
"block_transition",
|
||||
"set_status",
|
||||
"request_review",
|
||||
"emit_event",
|
||||
"notify_operator",
|
||||
"start_watchdog",
|
||||
"raise_escalation",
|
||||
"record_placeholder"
|
||||
]
|
||||
},
|
||||
"actionTarget": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"outgoing_report",
|
||||
"status_transition",
|
||||
"operator_channel",
|
||||
"task_record",
|
||||
"event_stream",
|
||||
"watchdog",
|
||||
"review_queue"
|
||||
]
|
||||
},
|
||||
"requiredAction": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"action",
|
||||
"target",
|
||||
"mandatory"
|
||||
],
|
||||
"properties": {
|
||||
"action": {
|
||||
"$ref": "#/$defs/actionVerb"
|
||||
},
|
||||
"target": {
|
||||
"$ref": "#/$defs/actionTarget"
|
||||
},
|
||||
"mandatory": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"details": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"urgency": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"info",
|
||||
"low",
|
||||
"medium",
|
||||
"high",
|
||||
"critical"
|
||||
]
|
||||
},
|
||||
"operatorNotice": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"required",
|
||||
"channel",
|
||||
"urgency",
|
||||
"message",
|
||||
"deadline"
|
||||
],
|
||||
"properties": {
|
||||
"required": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"channel": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"urgency": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/$defs/urgency"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"must_reference": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"deadline": {
|
||||
"type": ["string", "null"],
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"operatorNoticeOrNull": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/$defs/operatorNotice"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"decision": {
|
||||
"const": "rewrite"
|
||||
}
|
||||
},
|
||||
"required": ["decision"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"rewritten_message": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"decision": {
|
||||
"const": "annotate_placeholder"
|
||||
}
|
||||
},
|
||||
"required": ["decision"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"rewritten_message": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"operator_notice": {
|
||||
"$ref": "#/$defs/operatorNotice"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"decision": {
|
||||
"const": "force_checkpoint"
|
||||
}
|
||||
},
|
||||
"required": ["decision"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"operator_notice": {
|
||||
"$ref": "#/$defs/operatorNotice"
|
||||
}
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"operator_notice": {
|
||||
"properties": {
|
||||
"required": {
|
||||
"const": true
|
||||
}
|
||||
},
|
||||
"required": ["required"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"required_actions": {
|
||||
"contains": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"enum": ["notify_operator", "dispatch_message"]
|
||||
},
|
||||
"mandatory": {
|
||||
"const": true
|
||||
}
|
||||
},
|
||||
"required": ["action", "mandatory"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"decision": {
|
||||
"const": "downgrade_status"
|
||||
}
|
||||
},
|
||||
"required": ["decision"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"suggested_status": {
|
||||
"const": "pending_verification"
|
||||
},
|
||||
"required_actions": {
|
||||
"contains": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"const": "set_status"
|
||||
},
|
||||
"mandatory": {
|
||||
"const": true
|
||||
},
|
||||
"details": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"to": {
|
||||
"const": "pending_verification"
|
||||
}
|
||||
},
|
||||
"required": ["to"]
|
||||
}
|
||||
},
|
||||
"required": ["action", "mandatory", "details"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"decision": {
|
||||
"const": "block"
|
||||
}
|
||||
},
|
||||
"required": ["decision"]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"required_actions": {
|
||||
"contains": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"const": "block_transition"
|
||||
},
|
||||
"mandatory": {
|
||||
"const": true
|
||||
}
|
||||
},
|
||||
"required": ["action", "mandatory"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -20,7 +20,7 @@ const RECEIPT_STATUS_RULES = {
|
||||
};
|
||||
|
||||
const packageRoot = path.resolve(import.meta.dirname, '..', '..');
|
||||
const repoRoot = path.resolve(packageRoot, '..', '..');
|
||||
const repoRoot = packageRoot;
|
||||
const decisionSchemaPath = path.resolve(repoRoot, 'schemas', 'reporting-governance', 'decision.schema.json');
|
||||
const decisionRecordArtifactSchemaPath = path.resolve(repoRoot, 'schemas', 'reporting-governance', 'decision-record-artifact.schema.json');
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ const requiredPaths = [
|
||||
'profiles-src/strict-manager-mode.yaml',
|
||||
'schemas/reporting-governance/deployment-profile.schema.json',
|
||||
'schemas/reporting-governance/capability-descriptor.schema.json',
|
||||
'schemas/reporting-governance/decision.schema.json',
|
||||
'schemas/reporting-governance/decision-record-artifact.schema.json',
|
||||
'scripts/package-smoke.mjs',
|
||||
'scripts/watchdog_auto_notify_orchestrator.mjs',
|
||||
'scripts/long_task_watchdog.mjs',
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
const packageRoot = path.resolve(import.meta.dirname, '..');
|
||||
|
||||
function run(command, args, { cwd, env = {} } = {}) {
|
||||
const result = spawnSync(command, args, {
|
||||
cwd,
|
||||
encoding: 'utf8',
|
||||
env: {
|
||||
...process.env,
|
||||
...env,
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(
|
||||
result.status,
|
||||
0,
|
||||
[
|
||||
`command failed: ${command} ${args.join(' ')}`,
|
||||
`cwd: ${cwd}`,
|
||||
result.stdout && `stdout:\n${result.stdout.trim()}`,
|
||||
result.stderr && `stderr:\n${result.stderr.trim()}`,
|
||||
].filter(Boolean).join('\n\n')
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
test('packed tarball installs into clean consumer and works via public exports/bin only', () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'reporting-governance-packed-consumer-'));
|
||||
|
||||
try {
|
||||
const packResult = run('npm', ['pack', '--json'], { cwd: packageRoot });
|
||||
const packPayload = JSON.parse(packResult.stdout.trim());
|
||||
const tarballName = packPayload.at(-1)?.filename;
|
||||
assert.ok(tarballName, 'npm pack should return tarball filename');
|
||||
|
||||
const tarballPath = path.join(packageRoot, tarballName);
|
||||
assert.equal(fs.existsSync(tarballPath), true, 'tarball should exist after npm pack');
|
||||
|
||||
const consumerRoot = path.join(root, 'consumer');
|
||||
fs.mkdirSync(consumerRoot, { recursive: true });
|
||||
run('npm', ['init', '-y'], { cwd: consumerRoot });
|
||||
run('npm', ['install', tarballPath], { cwd: consumerRoot });
|
||||
|
||||
const exportProbe = run(process.execPath, ['--input-type=module', '--eval', `
|
||||
import * as plugin from '@openclaw/plugin-reporting-governance';
|
||||
import { runOrchestratorAdapter } from '@openclaw/plugin-reporting-governance/adapters/orchestrator';
|
||||
process.stdout.write(JSON.stringify({
|
||||
packageName: plugin.packageName,
|
||||
hasRunWatchdogChain: typeof plugin.runWatchdogChain,
|
||||
hasRunOrchestratorAdapter: typeof runOrchestratorAdapter,
|
||||
}));
|
||||
`], { cwd: consumerRoot });
|
||||
const exportPayload = JSON.parse(exportProbe.stdout.trim());
|
||||
assert.equal(exportPayload.packageName, '@openclaw/plugin-reporting-governance');
|
||||
assert.equal(exportPayload.hasRunWatchdogChain, 'function');
|
||||
assert.equal(exportPayload.hasRunOrchestratorAdapter, 'function');
|
||||
|
||||
const smokeResult = run(
|
||||
path.join(consumerRoot, 'node_modules', '.bin', 'reporting-governance-package-smoke'),
|
||||
['--compact'],
|
||||
{ cwd: consumerRoot }
|
||||
);
|
||||
const smokePayload = JSON.parse(smokeResult.stdout.trim());
|
||||
assert.equal(smokePayload.ok, true);
|
||||
assert.equal(smokePayload.tool, 'reporting-governance-package-smoke');
|
||||
assert.equal(smokePayload.orchestrator.ok, true);
|
||||
assert.equal(smokePayload.orchestrator.dispatchedCount, 1);
|
||||
assert.equal(smokePayload.orchestrator.pendingCount, 1);
|
||||
assert.equal(smokePayload.orchestrator.notificationCount, 1);
|
||||
} finally {
|
||||
fs.rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user