From 704e41fa27a33f0a2761e5304af9b19f4090c5d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Boschi?= Date: Mon, 30 Mar 2026 16:55:06 +0200 Subject: [PATCH] Fix trailing commas in openclaw.plugin.json and add JSON manifest CI tests (#774) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #771 — two trailing commas in openclaw.plugin.json caused OpenClaw's strict JSON parser to reject the plugin manifest during installation. Also adds JSON validation tests for both the openclaw plugin manifest and the claude-code hooks.json so CI catches invalid JSON before release. --- .../claude-code/tests/test_manifest.py | 14 ++++++++++++ .../openclaw/openclaw.plugin.json | 4 ++-- .../openclaw/src/manifest.test.ts | 22 +++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 hindsight-integrations/claude-code/tests/test_manifest.py create mode 100644 hindsight-integrations/openclaw/src/manifest.test.ts diff --git a/hindsight-integrations/claude-code/tests/test_manifest.py b/hindsight-integrations/claude-code/tests/test_manifest.py new file mode 100644 index 00000000..bd52efc2 --- /dev/null +++ b/hindsight-integrations/claude-code/tests/test_manifest.py @@ -0,0 +1,14 @@ +"""Validate that JSON manifests are strict-valid JSON (no trailing commas, etc.).""" + +import json +from pathlib import Path + +INTEGRATION_ROOT = Path(__file__).resolve().parent.parent + + +def test_hooks_json_is_valid(): + path = INTEGRATION_ROOT / "hooks" / "hooks.json" + raw = path.read_text() + parsed = json.loads(raw) + assert "hooks" in parsed + assert isinstance(parsed["hooks"], dict) diff --git a/hindsight-integrations/openclaw/openclaw.plugin.json b/hindsight-integrations/openclaw/openclaw.plugin.json index f70fad0f..4fc6b610 100644 --- a/hindsight-integrations/openclaw/openclaw.plugin.json +++ b/hindsight-integrations/openclaw/openclaw.plugin.json @@ -215,7 +215,7 @@ "type": "number", "description": "Interval in ms to batch retain/recall log summaries. 0 = log every event individually. Default: 300000 (5 min).", "default": 300000 - }, + } }, "additionalProperties": false }, @@ -349,6 +349,6 @@ "logSummaryIntervalMs": { "label": "Log Summary Interval (ms)", "placeholder": "300000" - }, + } } } diff --git a/hindsight-integrations/openclaw/src/manifest.test.ts b/hindsight-integrations/openclaw/src/manifest.test.ts new file mode 100644 index 00000000..2438ff62 --- /dev/null +++ b/hindsight-integrations/openclaw/src/manifest.test.ts @@ -0,0 +1,22 @@ +import { describe, it, expect } from 'vitest'; +import { readFileSync } from 'fs'; +import { resolve, dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const manifestPath = resolve(__dirname, '..', 'openclaw.plugin.json'); + +describe('openclaw.plugin.json', () => { + it('is valid JSON', () => { + const raw = readFileSync(manifestPath, 'utf-8'); + expect(() => JSON.parse(raw)).not.toThrow(); + }); + + it('has required top-level fields', () => { + const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8')); + expect(manifest.id).toBe('hindsight-openclaw'); + expect(manifest.name).toBeTypeOf('string'); + expect(manifest.configSchema).toBeDefined(); + expect(manifest.configSchema.properties).toBeDefined(); + }); +});