test: add packed consumer install smoke
This commit is contained in:
@@ -269,5 +269,19 @@ npm run smoke
|
|||||||
reporting-governance-package-smoke --compact
|
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.
|
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": "^8.17.1",
|
||||||
"ajv-formats": "^3.0.1",
|
"ajv-formats": "^3.0.1",
|
||||||
"yaml": "^2.8.0"
|
"yaml": "^2.8.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"reporting-governance-package-smoke": "scripts/package-smoke.mjs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ajv": {
|
"node_modules/ajv": {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"reporting-governance-package-smoke": "./scripts/package-smoke.mjs"
|
"reporting-governance-package-smoke": "./scripts/package-smoke.mjs"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"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"
|
"smoke": "node ./scripts/package-smoke.mjs --compact"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"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 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 decisionSchemaPath = path.resolve(repoRoot, 'schemas', 'reporting-governance', 'decision.schema.json');
|
||||||
const decisionRecordArtifactSchemaPath = path.resolve(repoRoot, 'schemas', 'reporting-governance', 'decision-record-artifact.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',
|
'profiles-src/strict-manager-mode.yaml',
|
||||||
'schemas/reporting-governance/deployment-profile.schema.json',
|
'schemas/reporting-governance/deployment-profile.schema.json',
|
||||||
'schemas/reporting-governance/capability-descriptor.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/package-smoke.mjs',
|
||||||
'scripts/watchdog_auto_notify_orchestrator.mjs',
|
'scripts/watchdog_auto_notify_orchestrator.mjs',
|
||||||
'scripts/long_task_watchdog.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