@rune-kit/rune 2.1.1 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -34
- package/compiler/__tests__/pack-split.test.js +145 -0
- package/compiler/adapters/antigravity.js +1 -1
- package/compiler/adapters/codex.js +77 -0
- package/compiler/adapters/cursor.js +1 -1
- package/compiler/adapters/generic.js +1 -1
- package/compiler/adapters/index.js +4 -0
- package/compiler/adapters/opencode.js +86 -0
- package/compiler/adapters/windsurf.js +1 -1
- package/compiler/bin/rune.js +10 -7
- package/compiler/doctor.js +42 -0
- package/compiler/emitter.js +64 -10
- package/compiler/parser.js +42 -3
- package/compiler/transformer.js +10 -6
- package/compiler/transforms/branding.js +1 -1
- package/compiler/transforms/compliance.js +40 -0
- package/extensions/ai-ml/PACK.md +38 -474
- package/extensions/ai-ml/skills/ai-agents.md +172 -0
- package/extensions/ai-ml/skills/code-sandbox.md +187 -0
- package/extensions/ai-ml/skills/deep-research.md +146 -0
- package/extensions/ai-ml/skills/embedding-search.md +66 -0
- package/extensions/ai-ml/skills/fine-tuning-guide.md +74 -0
- package/extensions/ai-ml/skills/llm-architect.md +125 -0
- package/extensions/ai-ml/skills/llm-integration.md +64 -0
- package/extensions/ai-ml/skills/prompt-patterns.md +72 -0
- package/extensions/ai-ml/skills/rag-patterns.md +66 -0
- package/extensions/ai-ml/skills/web-extraction.md +114 -0
- package/extensions/analytics/PACK.md +19 -484
- package/extensions/analytics/skills/ab-testing.md +72 -0
- package/extensions/analytics/skills/dashboard-patterns.md +83 -0
- package/extensions/analytics/skills/data-validation.md +68 -0
- package/extensions/analytics/skills/funnel-analysis.md +81 -0
- package/extensions/analytics/skills/sql-patterns.md +57 -0
- package/extensions/analytics/skills/statistical-analysis.md +79 -0
- package/extensions/analytics/skills/tracking-setup.md +71 -0
- package/extensions/backend/PACK.md +44 -618
- package/extensions/backend/skills/api-patterns.md +84 -0
- package/extensions/backend/skills/async-pipeline.md +193 -0
- package/extensions/backend/skills/auth-patterns.md +97 -0
- package/extensions/backend/skills/background-jobs.md +133 -0
- package/extensions/backend/skills/caching-patterns.md +108 -0
- package/extensions/backend/skills/cli-generation.md +133 -0
- package/extensions/backend/skills/database-patterns.md +87 -0
- package/extensions/backend/skills/middleware-patterns.md +104 -0
- package/extensions/chrome-ext/PACK.md +19 -921
- package/extensions/chrome-ext/skills/cws-preflight.md +143 -0
- package/extensions/chrome-ext/skills/cws-publish.md +104 -0
- package/extensions/chrome-ext/skills/ext-ai-integration.md +251 -0
- package/extensions/chrome-ext/skills/ext-messaging.md +139 -0
- package/extensions/chrome-ext/skills/ext-storage.md +133 -0
- package/extensions/chrome-ext/skills/mv3-scaffold.md +164 -0
- package/extensions/content/PACK.md +43 -335
- package/extensions/content/skills/blog-patterns.md +88 -0
- package/extensions/content/skills/cms-integration.md +131 -0
- package/extensions/content/skills/content-scoring.md +107 -0
- package/extensions/content/skills/i18n.md +83 -0
- package/extensions/content/skills/mdx-authoring.md +137 -0
- package/extensions/content/skills/reference.md +1014 -0
- package/extensions/content/skills/seo-patterns.md +67 -0
- package/extensions/content/skills/video-repurpose.md +153 -0
- package/extensions/devops/PACK.md +38 -457
- package/extensions/devops/skills/chaos-testing.md +67 -0
- package/extensions/devops/skills/ci-cd.md +75 -0
- package/extensions/devops/skills/docker.md +58 -0
- package/extensions/devops/skills/edge-serverless.md +163 -0
- package/extensions/devops/skills/infra-as-code.md +158 -0
- package/extensions/devops/skills/kubernetes.md +110 -0
- package/extensions/devops/skills/monitoring.md +57 -0
- package/extensions/devops/skills/server-setup.md +64 -0
- package/extensions/devops/skills/ssl-domain.md +42 -0
- package/extensions/ecommerce/PACK.md +62 -226
- package/extensions/ecommerce/skills/cart-system.md +79 -0
- package/extensions/ecommerce/skills/inventory-mgmt.md +102 -0
- package/extensions/ecommerce/skills/order-management.md +126 -0
- package/extensions/ecommerce/skills/payment-integration.md +472 -0
- package/extensions/ecommerce/skills/shopify-dev.md +69 -0
- package/extensions/ecommerce/skills/subscription-billing.md +93 -0
- package/extensions/ecommerce/skills/tax-compliance.md +117 -0
- package/extensions/gamedev/PACK.md +66 -317
- package/extensions/gamedev/skills/asset-pipeline.md +74 -0
- package/extensions/gamedev/skills/audio-system.md +129 -0
- package/extensions/gamedev/skills/camera-system.md +87 -0
- package/extensions/gamedev/skills/ecs.md +98 -0
- package/extensions/gamedev/skills/game-loops.md +72 -0
- package/extensions/gamedev/skills/input-system.md +199 -0
- package/extensions/gamedev/skills/multiplayer.md +180 -0
- package/extensions/gamedev/skills/particles.md +105 -0
- package/extensions/gamedev/skills/physics-engine.md +89 -0
- package/extensions/gamedev/skills/scene-management.md +146 -0
- package/extensions/gamedev/skills/threejs-patterns.md +90 -0
- package/extensions/gamedev/skills/webgl.md +71 -0
- package/extensions/mobile/PACK.md +56 -223
- package/extensions/mobile/skills/app-store-connect.md +152 -0
- package/extensions/mobile/skills/app-store-prep.md +66 -0
- package/extensions/mobile/skills/deep-linking.md +109 -0
- package/extensions/mobile/skills/flutter.md +60 -0
- package/extensions/mobile/skills/ios-build-pipeline.md +142 -0
- package/extensions/mobile/skills/native-bridge.md +66 -0
- package/extensions/mobile/skills/ota-updates.md +97 -0
- package/extensions/mobile/skills/push-notifications.md +111 -0
- package/extensions/mobile/skills/react-native.md +82 -0
- package/extensions/saas/PACK.md +26 -720
- package/extensions/saas/skills/billing-integration.md +121 -0
- package/extensions/saas/skills/feature-flags.md +130 -0
- package/extensions/saas/skills/multi-tenant.md +103 -0
- package/extensions/saas/skills/onboarding-flow.md +139 -0
- package/extensions/saas/skills/subscription-flow.md +95 -0
- package/extensions/saas/skills/team-management.md +144 -0
- package/extensions/security/PACK.md +10 -448
- package/extensions/security/skills/api-security.md +140 -0
- package/extensions/security/skills/compliance.md +68 -0
- package/extensions/security/skills/owasp-audit.md +64 -0
- package/extensions/security/skills/pentest-patterns.md +77 -0
- package/extensions/security/skills/secret-mgmt.md +65 -0
- package/extensions/security/skills/supply-chain.md +65 -0
- package/extensions/trading/PACK.md +18 -535
- package/extensions/trading/skills/chart-components.md +55 -0
- package/extensions/trading/skills/experiment-loop.md +125 -0
- package/extensions/trading/skills/fintech-patterns.md +47 -0
- package/extensions/trading/skills/indicator-library.md +58 -0
- package/extensions/trading/skills/quant-analysis.md +111 -0
- package/extensions/trading/skills/realtime-data.md +58 -0
- package/extensions/trading/skills/trade-logic.md +104 -0
- package/extensions/ui/PACK.md +34 -853
- package/extensions/ui/skills/a11y-audit.md +91 -0
- package/extensions/ui/skills/animation-patterns.md +106 -0
- package/extensions/ui/skills/component-patterns.md +75 -0
- package/extensions/ui/skills/design-decision.md +98 -0
- package/extensions/ui/skills/design-system.md +68 -0
- package/extensions/ui/skills/landing-patterns.md +155 -0
- package/extensions/ui/skills/palette-picker.md +162 -0
- package/extensions/ui/skills/react-health.md +90 -0
- package/extensions/ui/skills/type-system.md +125 -0
- package/extensions/ui/skills/web-vitals.md +153 -0
- package/extensions/zalo/PACK.md +117 -0
- package/extensions/zalo/skills/zalo-oa-mcp.md +317 -0
- package/extensions/zalo/skills/zalo-oa-messaging.md +429 -0
- package/extensions/zalo/skills/zalo-oa-setup.md +236 -0
- package/extensions/zalo/skills/zalo-oa-webhook.md +189 -0
- package/extensions/zalo/skills/zalo-personal-messaging.md +194 -0
- package/extensions/zalo/skills/zalo-personal-setup.md +153 -0
- package/extensions/zalo/skills/zalo-rate-guard.md +219 -0
- package/package.json +5 -2
- package/skills/brainstorm/SKILL.md +63 -1
- package/skills/cook/SKILL.md +89 -6
- package/skills/debug/SKILL.md +5 -0
- package/skills/fix/SKILL.md +5 -0
- package/skills/mcp-builder/SKILL.md +48 -1
- package/skills/neural-memory/SKILL.md +362 -0
- package/skills/plan/SKILL.md +3 -0
- package/skills/rescue/SKILL.md +5 -0
- package/skills/review/SKILL.md +44 -5
- package/skills/review-intake/SKILL.md +17 -1
- package/skills/skill-router/SKILL.md +106 -8
- package/skills/team/SKILL.md +24 -1
- package/skills/test/SKILL.md +18 -0
- package/skills/verification/SKILL.md +40 -1
package/compiler/emitter.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { readdir, readFile, mkdir, writeFile } from 'node:fs/promises';
|
|
9
9
|
import { existsSync } from 'node:fs';
|
|
10
10
|
import path from 'node:path';
|
|
11
|
-
import { parseSkill, parsePack } from './parser.js';
|
|
11
|
+
import { parseSkill, parsePack, extractCrossRefs, extractToolRefs } from './parser.js';
|
|
12
12
|
import { transformSkill } from './transformer.js';
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -124,15 +124,29 @@ export async function buildAll({ runeRoot, outputRoot, adapter, disabledSkills =
|
|
|
124
124
|
|
|
125
125
|
const { header, body, footer } = transformSkill(parsed, adapter);
|
|
126
126
|
const output = [header, body, footer].filter(Boolean).join('\n');
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
|
|
128
|
+
let outputPath;
|
|
129
|
+
let displayName;
|
|
130
|
+
|
|
131
|
+
if (adapter.useSkillDirectories) {
|
|
132
|
+
// Directory-per-skill: .codex/skills/rune-{name}/SKILL.md
|
|
133
|
+
const dirName = `${adapter.skillPrefix}${parsed.name}`;
|
|
134
|
+
const skillDir = path.join(outputDir, dirName);
|
|
135
|
+
await mkdir(skillDir, { recursive: true });
|
|
136
|
+
outputPath = path.join(skillDir, adapter.skillFileName || 'SKILL.md');
|
|
137
|
+
displayName = `${dirName}/${adapter.skillFileName || 'SKILL.md'}`;
|
|
138
|
+
} else {
|
|
139
|
+
const fileName = outputFileName(parsed.name, adapter);
|
|
140
|
+
outputPath = path.join(outputDir, fileName);
|
|
141
|
+
displayName = fileName;
|
|
142
|
+
}
|
|
129
143
|
|
|
130
144
|
await writeFile(outputPath, output, 'utf-8');
|
|
131
145
|
|
|
132
146
|
stats.skillCount++;
|
|
133
147
|
stats.crossRefsResolved += parsed.crossRefs.length;
|
|
134
148
|
stats.toolRefsResolved += parsed.toolRefs.length;
|
|
135
|
-
stats.files.push(
|
|
149
|
+
stats.files.push(displayName);
|
|
136
150
|
} catch (err) {
|
|
137
151
|
stats.errors.push({ file: skillPath, error: err.message });
|
|
138
152
|
}
|
|
@@ -143,16 +157,56 @@ export async function buildAll({ runeRoot, outputRoot, adapter, disabledSkills =
|
|
|
143
157
|
try {
|
|
144
158
|
const content = await readFile(packPath, 'utf-8');
|
|
145
159
|
const parsed = parsePack(content, packPath);
|
|
160
|
+
const packName = path.basename(path.dirname(packPath));
|
|
161
|
+
const packDir = path.dirname(packPath);
|
|
162
|
+
|
|
163
|
+
// For split packs, load individual skill files and concatenate into body
|
|
164
|
+
if (parsed.isSplit && parsed.skillManifest.length > 0) {
|
|
165
|
+
const skillBodies = [];
|
|
166
|
+
for (const skill of parsed.skillManifest) {
|
|
167
|
+
const skillPath = path.join(packDir, skill.file);
|
|
168
|
+
if (existsSync(skillPath)) {
|
|
169
|
+
const skillContent = await readFile(skillPath, 'utf-8');
|
|
170
|
+
// Strip frontmatter from skill file — we only need the body
|
|
171
|
+
const skillBodyMatch = skillContent.replace(/\r\n/g, '\n').match(/^---\n[\s\S]*?\n---\n?([\s\S]*)$/);
|
|
172
|
+
const skillBody = skillBodyMatch ? skillBodyMatch[1].trim() : skillContent.trim();
|
|
173
|
+
skillBodies.push(skillBody);
|
|
174
|
+
} else {
|
|
175
|
+
stats.errors.push({ file: skillPath, error: `Skill file not found (listed in ${packPath} manifest)` });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Concatenate: index body + all skill bodies
|
|
179
|
+
parsed.body = parsed.body + '\n\n' + skillBodies.join('\n\n---\n\n');
|
|
180
|
+
// Re-extract refs from the full concatenated body
|
|
181
|
+
parsed.crossRefs = extractCrossRefs(parsed.body);
|
|
182
|
+
parsed.toolRefs = extractToolRefs(parsed.body);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Normalize pack name for headers (ext-trading instead of @rune/trading)
|
|
186
|
+
parsed.name = `ext-${packName}`;
|
|
187
|
+
|
|
146
188
|
const { header, body, footer } = transformSkill(parsed, adapter);
|
|
147
189
|
const output = [header, body, footer].filter(Boolean).join('\n');
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
190
|
+
|
|
191
|
+
let outputPath;
|
|
192
|
+
let displayName;
|
|
193
|
+
|
|
194
|
+
if (adapter.useSkillDirectories) {
|
|
195
|
+
const dirName = `${adapter.skillPrefix}ext-${packName}`;
|
|
196
|
+
const outPackDir = path.join(outputDir, dirName);
|
|
197
|
+
await mkdir(outPackDir, { recursive: true });
|
|
198
|
+
outputPath = path.join(outPackDir, adapter.skillFileName || 'SKILL.md');
|
|
199
|
+
displayName = `${dirName}/${adapter.skillFileName || 'SKILL.md'}`;
|
|
200
|
+
} else {
|
|
201
|
+
const fileName = outputFileName(`ext-${packName}`, adapter);
|
|
202
|
+
outputPath = path.join(outputDir, fileName);
|
|
203
|
+
displayName = fileName;
|
|
204
|
+
}
|
|
151
205
|
|
|
152
206
|
await writeFile(outputPath, output, 'utf-8');
|
|
153
207
|
|
|
154
208
|
stats.packCount++;
|
|
155
|
-
stats.files.push(
|
|
209
|
+
stats.files.push(displayName);
|
|
156
210
|
} catch (err) {
|
|
157
211
|
stats.errors.push({ file: packPath, error: err.message });
|
|
158
212
|
}
|
|
@@ -221,12 +275,12 @@ function generateIndex(stats, adapter) {
|
|
|
221
275
|
'## Core Skills',
|
|
222
276
|
'',
|
|
223
277
|
...stats.files
|
|
224
|
-
.filter(f => !f.
|
|
278
|
+
.filter(f => !f.match(/[-/]ext-/) && !f.includes('index'))
|
|
225
279
|
.map(f => `- ${f}`),
|
|
226
280
|
'',
|
|
227
281
|
];
|
|
228
282
|
|
|
229
|
-
const extFiles = stats.files.filter(f => f.
|
|
283
|
+
const extFiles = stats.files.filter(f => f.match(/[-/]ext-/));
|
|
230
284
|
if (extFiles.length > 0) {
|
|
231
285
|
lines.push('## Extension Packs', '', ...extFiles.map(f => `- ${f}`), '');
|
|
232
286
|
}
|
package/compiler/parser.js
CHANGED
|
@@ -65,7 +65,7 @@ function parseFrontmatter(content) {
|
|
|
65
65
|
/**
|
|
66
66
|
* Extract all rune:<name> cross-references from body
|
|
67
67
|
*/
|
|
68
|
-
function extractCrossRefs(body) {
|
|
68
|
+
export function extractCrossRefs(body) {
|
|
69
69
|
const refs = [];
|
|
70
70
|
const lines = body.split('\n');
|
|
71
71
|
|
|
@@ -90,7 +90,7 @@ function extractCrossRefs(body) {
|
|
|
90
90
|
/**
|
|
91
91
|
* Extract all Claude Code tool references from body
|
|
92
92
|
*/
|
|
93
|
-
function extractToolRefs(body) {
|
|
93
|
+
export function extractToolRefs(body) {
|
|
94
94
|
const refs = [];
|
|
95
95
|
const lines = body.split('\n');
|
|
96
96
|
|
|
@@ -188,15 +188,25 @@ export function parseSkill(content, filePath = '') {
|
|
|
188
188
|
|
|
189
189
|
/**
|
|
190
190
|
* Parse a PACK.md extension file (same format, slightly different metadata)
|
|
191
|
+
* Supports both monolith format (all skills inline) and split format (skills in separate files)
|
|
192
|
+
*
|
|
193
|
+
* Split format detection: metadata.format === "split" OR metadata.skills array present
|
|
191
194
|
*/
|
|
192
195
|
export function parsePack(content, filePath = '') {
|
|
193
196
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
197
|
+
const metadata = frontmatter.metadata || {};
|
|
198
|
+
|
|
199
|
+
// Detect split format
|
|
200
|
+
const isSplit = metadata.format === 'split' || Array.isArray(metadata.skills);
|
|
194
201
|
|
|
195
202
|
return {
|
|
196
203
|
name: frontmatter.name || '',
|
|
197
204
|
description: frontmatter.description || '',
|
|
198
|
-
version: frontmatter.version || '1.0.0',
|
|
205
|
+
version: metadata.version || frontmatter.version || '1.0.0',
|
|
199
206
|
layer: 'L4',
|
|
207
|
+
group: 'extension',
|
|
208
|
+
isSplit,
|
|
209
|
+
skillManifest: isSplit ? parseSkillManifest(metadata.skills || []) : [],
|
|
200
210
|
body,
|
|
201
211
|
crossRefs: extractCrossRefs(body),
|
|
202
212
|
toolRefs: extractToolRefs(body),
|
|
@@ -206,3 +216,32 @@ export function parsePack(content, filePath = '') {
|
|
|
206
216
|
frontmatter,
|
|
207
217
|
};
|
|
208
218
|
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Parse the skills manifest from split PACK.md frontmatter
|
|
222
|
+
*
|
|
223
|
+
* @param {Array} skills - array of skill entries from frontmatter metadata.skills
|
|
224
|
+
* @returns {Array<{name: string, file: string, model: string, description: string}>}
|
|
225
|
+
*/
|
|
226
|
+
function parseSkillManifest(skills) {
|
|
227
|
+
if (!Array.isArray(skills)) return [];
|
|
228
|
+
|
|
229
|
+
return skills.map(skill => {
|
|
230
|
+
// Handle both string format ("skill-name") and object format ({name, file, model, description})
|
|
231
|
+
if (typeof skill === 'string') {
|
|
232
|
+
return {
|
|
233
|
+
name: skill,
|
|
234
|
+
file: `skills/${skill}.md`,
|
|
235
|
+
model: 'sonnet',
|
|
236
|
+
description: '',
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
name: skill.name || '',
|
|
242
|
+
file: skill.file || `skills/${skill.name}.md`,
|
|
243
|
+
model: skill.model || 'sonnet',
|
|
244
|
+
description: skill.description || '',
|
|
245
|
+
};
|
|
246
|
+
});
|
|
247
|
+
}
|
package/compiler/transformer.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Transform Pipeline
|
|
3
3
|
*
|
|
4
4
|
* Applies all transforms in order to convert a parsed skill into platform-specific output.
|
|
5
|
-
* Pipeline: frontmatter → cross-refs → tool-names → subagents → hooks → branding
|
|
5
|
+
* Pipeline: frontmatter → cross-refs → tool-names → subagents → compliance → hooks → branding
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { transformCrossReferences } from './transforms/cross-references.js';
|
|
@@ -10,6 +10,7 @@ import { transformToolNames } from './transforms/tool-names.js';
|
|
|
10
10
|
import { transformFrontmatter } from './transforms/frontmatter.js';
|
|
11
11
|
import { transformSubagents } from './transforms/subagents.js';
|
|
12
12
|
import { generateHookConstraints } from './transforms/hooks.js';
|
|
13
|
+
import { transformCompliance } from './transforms/compliance.js';
|
|
13
14
|
import { addBranding } from './transforms/branding.js';
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -40,16 +41,19 @@ export function transformSkill(parsedSkill, adapter) {
|
|
|
40
41
|
// 3. Convert subagent/parallel instructions to sequential
|
|
41
42
|
body = transformSubagents(body, adapter);
|
|
42
43
|
|
|
43
|
-
// 4.
|
|
44
|
+
// 4. Inject compliance preamble (enforcement for non-Claude platforms)
|
|
45
|
+
body = transformCompliance(body, adapter);
|
|
46
|
+
|
|
47
|
+
// 5. Platform-specific post-processing
|
|
44
48
|
body = adapter.postProcess(body);
|
|
45
49
|
|
|
46
|
-
//
|
|
50
|
+
// 6. Generate header (platform-specific frontmatter/preamble)
|
|
47
51
|
const header = adapter.generateHeader(parsedSkill);
|
|
48
52
|
|
|
49
|
-
//
|
|
53
|
+
// 7. Generate hook constraints section
|
|
50
54
|
const hookConstraints = generateHookConstraints(parsedSkill, adapter);
|
|
51
55
|
|
|
52
|
-
//
|
|
56
|
+
// 8. Inject hook constraints after the first heading
|
|
53
57
|
if (hookConstraints) {
|
|
54
58
|
const firstHeadingEnd = body.indexOf('\n## ');
|
|
55
59
|
if (firstHeadingEnd !== -1) {
|
|
@@ -62,7 +66,7 @@ export function transformSkill(parsedSkill, adapter) {
|
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
68
|
|
|
65
|
-
//
|
|
69
|
+
// 9. Generate footer (branding + CTA)
|
|
66
70
|
const footer = adapter.generateFooter();
|
|
67
71
|
|
|
68
72
|
return { header, body, footer };
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
const DEFAULT_FOOTER = [
|
|
8
8
|
'',
|
|
9
9
|
'---',
|
|
10
|
-
'> **Rune Skill Mesh** —
|
|
10
|
+
'> **Rune Skill Mesh** — 58 skills, 200+ connections',
|
|
11
11
|
'> Source: https://github.com/rune-kit/rune',
|
|
12
12
|
'> For the full experience with subagents, hooks, adaptive routing, and mesh analytics — use Rune as a Claude Code plugin.',
|
|
13
13
|
].join('\n');
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compliance Transform
|
|
3
|
+
*
|
|
4
|
+
* Injects a compliance preamble into every compiled skill file.
|
|
5
|
+
* This distributes enforcement to ALL platforms (Cursor, Windsurf, etc.)
|
|
6
|
+
* so the AI is reminded of routing discipline even if skill-router
|
|
7
|
+
* itself is not loaded in context.
|
|
8
|
+
*
|
|
9
|
+
* Only applies to non-Claude platforms (Claude has native plugin enforcement).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const COMPLIANCE_PREAMBLE = [
|
|
13
|
+
'',
|
|
14
|
+
'> **RUNE COMPLIANCE**: Before ANY code response, you MUST:',
|
|
15
|
+
'> 1. Classify this request (CODE_CHANGE | QUESTION | DEBUG | REVIEW | EXPLORE)',
|
|
16
|
+
'> 2. Route through the correct Rune skill (see skill-router routing table)',
|
|
17
|
+
"> 3. Follow the skill's workflow — do NOT freelance or skip steps",
|
|
18
|
+
'> Violation: writing code without skill routing = incorrect behavior.',
|
|
19
|
+
'',
|
|
20
|
+
].join('\n');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Inject compliance preamble after the first heading in a skill body.
|
|
24
|
+
*
|
|
25
|
+
* @param {string} body - skill body text
|
|
26
|
+
* @param {object} adapter - platform adapter
|
|
27
|
+
* @returns {string} body with compliance preamble injected
|
|
28
|
+
*/
|
|
29
|
+
export function transformCompliance(body, adapter) {
|
|
30
|
+
if (adapter.name === 'claude') return body;
|
|
31
|
+
|
|
32
|
+
// Insert after first heading (# skill-name), before first ## section
|
|
33
|
+
const firstH2 = body.indexOf('\n## ');
|
|
34
|
+
if (firstH2 !== -1) {
|
|
35
|
+
return body.slice(0, firstH2) + COMPLIANCE_PREAMBLE + body.slice(firstH2);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Fallback: append at end if no ## sections found
|
|
39
|
+
return body + COMPLIANCE_PREAMBLE;
|
|
40
|
+
}
|