feat: ship ponytail to OpenClaw (ClawHub skill package) (#102)

Adds .openclaw/skills/ (ponytail + review/audit/debt/help) generated from the canonical skills/ (verbatim body, no drift), a generator script, and a drift test. Verified live: loads as Ready in OpenClaw 2026.6.6.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
DietrichGebert
2026-06-16 13:35:35 +02:00
committed by GitHub
co-authored by Claude Opus 4.8
parent caf138df56
commit 41d6c2f761
8 changed files with 382 additions and 0 deletions
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env node
// The OpenClaw skill package (.openclaw/skills/) is generated from skills/ by
// scripts/build-openclaw-skills.js. These tests fail if the committed copies are
// stale (ruleset drift) or if a description breaks OpenClaw's one-line <160 rule.
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('fs');
const { NAMES, render, outPath, sourceBody, DESCRIPTIONS } = require('../scripts/build-openclaw-skills');
for (const name of NAMES) {
test(`${name}: committed OpenClaw skill matches the generator`, () => {
const onDisk = fs.readFileSync(outPath(name), 'utf8').replace(/\r\n/g, '\n');
assert.equal(onDisk, render(name), 'stale — run: node scripts/build-openclaw-skills.js');
});
test(`${name}: body is the canonical skills/${name} body, verbatim`, () => {
const onDisk = fs.readFileSync(outPath(name), 'utf8').replace(/\r\n/g, '\n');
assert.ok(onDisk.endsWith(sourceBody(name)), 'body drifted from skills/' + name);
});
test(`${name}: description is one line under 160 chars`, () => {
const d = DESCRIPTIONS[name];
assert.ok(d.length <= 160 && !d.includes('\n'), 'description too long or multiline');
});
}