@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.
Files changed (157) hide show
  1. package/README.md +40 -34
  2. package/compiler/__tests__/pack-split.test.js +145 -0
  3. package/compiler/adapters/antigravity.js +1 -1
  4. package/compiler/adapters/codex.js +77 -0
  5. package/compiler/adapters/cursor.js +1 -1
  6. package/compiler/adapters/generic.js +1 -1
  7. package/compiler/adapters/index.js +4 -0
  8. package/compiler/adapters/opencode.js +86 -0
  9. package/compiler/adapters/windsurf.js +1 -1
  10. package/compiler/bin/rune.js +10 -7
  11. package/compiler/doctor.js +42 -0
  12. package/compiler/emitter.js +64 -10
  13. package/compiler/parser.js +42 -3
  14. package/compiler/transformer.js +10 -6
  15. package/compiler/transforms/branding.js +1 -1
  16. package/compiler/transforms/compliance.js +40 -0
  17. package/extensions/ai-ml/PACK.md +38 -474
  18. package/extensions/ai-ml/skills/ai-agents.md +172 -0
  19. package/extensions/ai-ml/skills/code-sandbox.md +187 -0
  20. package/extensions/ai-ml/skills/deep-research.md +146 -0
  21. package/extensions/ai-ml/skills/embedding-search.md +66 -0
  22. package/extensions/ai-ml/skills/fine-tuning-guide.md +74 -0
  23. package/extensions/ai-ml/skills/llm-architect.md +125 -0
  24. package/extensions/ai-ml/skills/llm-integration.md +64 -0
  25. package/extensions/ai-ml/skills/prompt-patterns.md +72 -0
  26. package/extensions/ai-ml/skills/rag-patterns.md +66 -0
  27. package/extensions/ai-ml/skills/web-extraction.md +114 -0
  28. package/extensions/analytics/PACK.md +19 -484
  29. package/extensions/analytics/skills/ab-testing.md +72 -0
  30. package/extensions/analytics/skills/dashboard-patterns.md +83 -0
  31. package/extensions/analytics/skills/data-validation.md +68 -0
  32. package/extensions/analytics/skills/funnel-analysis.md +81 -0
  33. package/extensions/analytics/skills/sql-patterns.md +57 -0
  34. package/extensions/analytics/skills/statistical-analysis.md +79 -0
  35. package/extensions/analytics/skills/tracking-setup.md +71 -0
  36. package/extensions/backend/PACK.md +44 -618
  37. package/extensions/backend/skills/api-patterns.md +84 -0
  38. package/extensions/backend/skills/async-pipeline.md +193 -0
  39. package/extensions/backend/skills/auth-patterns.md +97 -0
  40. package/extensions/backend/skills/background-jobs.md +133 -0
  41. package/extensions/backend/skills/caching-patterns.md +108 -0
  42. package/extensions/backend/skills/cli-generation.md +133 -0
  43. package/extensions/backend/skills/database-patterns.md +87 -0
  44. package/extensions/backend/skills/middleware-patterns.md +104 -0
  45. package/extensions/chrome-ext/PACK.md +19 -921
  46. package/extensions/chrome-ext/skills/cws-preflight.md +143 -0
  47. package/extensions/chrome-ext/skills/cws-publish.md +104 -0
  48. package/extensions/chrome-ext/skills/ext-ai-integration.md +251 -0
  49. package/extensions/chrome-ext/skills/ext-messaging.md +139 -0
  50. package/extensions/chrome-ext/skills/ext-storage.md +133 -0
  51. package/extensions/chrome-ext/skills/mv3-scaffold.md +164 -0
  52. package/extensions/content/PACK.md +43 -335
  53. package/extensions/content/skills/blog-patterns.md +88 -0
  54. package/extensions/content/skills/cms-integration.md +131 -0
  55. package/extensions/content/skills/content-scoring.md +107 -0
  56. package/extensions/content/skills/i18n.md +83 -0
  57. package/extensions/content/skills/mdx-authoring.md +137 -0
  58. package/extensions/content/skills/reference.md +1014 -0
  59. package/extensions/content/skills/seo-patterns.md +67 -0
  60. package/extensions/content/skills/video-repurpose.md +153 -0
  61. package/extensions/devops/PACK.md +38 -457
  62. package/extensions/devops/skills/chaos-testing.md +67 -0
  63. package/extensions/devops/skills/ci-cd.md +75 -0
  64. package/extensions/devops/skills/docker.md +58 -0
  65. package/extensions/devops/skills/edge-serverless.md +163 -0
  66. package/extensions/devops/skills/infra-as-code.md +158 -0
  67. package/extensions/devops/skills/kubernetes.md +110 -0
  68. package/extensions/devops/skills/monitoring.md +57 -0
  69. package/extensions/devops/skills/server-setup.md +64 -0
  70. package/extensions/devops/skills/ssl-domain.md +42 -0
  71. package/extensions/ecommerce/PACK.md +62 -226
  72. package/extensions/ecommerce/skills/cart-system.md +79 -0
  73. package/extensions/ecommerce/skills/inventory-mgmt.md +102 -0
  74. package/extensions/ecommerce/skills/order-management.md +126 -0
  75. package/extensions/ecommerce/skills/payment-integration.md +472 -0
  76. package/extensions/ecommerce/skills/shopify-dev.md +69 -0
  77. package/extensions/ecommerce/skills/subscription-billing.md +93 -0
  78. package/extensions/ecommerce/skills/tax-compliance.md +117 -0
  79. package/extensions/gamedev/PACK.md +66 -317
  80. package/extensions/gamedev/skills/asset-pipeline.md +74 -0
  81. package/extensions/gamedev/skills/audio-system.md +129 -0
  82. package/extensions/gamedev/skills/camera-system.md +87 -0
  83. package/extensions/gamedev/skills/ecs.md +98 -0
  84. package/extensions/gamedev/skills/game-loops.md +72 -0
  85. package/extensions/gamedev/skills/input-system.md +199 -0
  86. package/extensions/gamedev/skills/multiplayer.md +180 -0
  87. package/extensions/gamedev/skills/particles.md +105 -0
  88. package/extensions/gamedev/skills/physics-engine.md +89 -0
  89. package/extensions/gamedev/skills/scene-management.md +146 -0
  90. package/extensions/gamedev/skills/threejs-patterns.md +90 -0
  91. package/extensions/gamedev/skills/webgl.md +71 -0
  92. package/extensions/mobile/PACK.md +56 -223
  93. package/extensions/mobile/skills/app-store-connect.md +152 -0
  94. package/extensions/mobile/skills/app-store-prep.md +66 -0
  95. package/extensions/mobile/skills/deep-linking.md +109 -0
  96. package/extensions/mobile/skills/flutter.md +60 -0
  97. package/extensions/mobile/skills/ios-build-pipeline.md +142 -0
  98. package/extensions/mobile/skills/native-bridge.md +66 -0
  99. package/extensions/mobile/skills/ota-updates.md +97 -0
  100. package/extensions/mobile/skills/push-notifications.md +111 -0
  101. package/extensions/mobile/skills/react-native.md +82 -0
  102. package/extensions/saas/PACK.md +26 -720
  103. package/extensions/saas/skills/billing-integration.md +121 -0
  104. package/extensions/saas/skills/feature-flags.md +130 -0
  105. package/extensions/saas/skills/multi-tenant.md +103 -0
  106. package/extensions/saas/skills/onboarding-flow.md +139 -0
  107. package/extensions/saas/skills/subscription-flow.md +95 -0
  108. package/extensions/saas/skills/team-management.md +144 -0
  109. package/extensions/security/PACK.md +10 -448
  110. package/extensions/security/skills/api-security.md +140 -0
  111. package/extensions/security/skills/compliance.md +68 -0
  112. package/extensions/security/skills/owasp-audit.md +64 -0
  113. package/extensions/security/skills/pentest-patterns.md +77 -0
  114. package/extensions/security/skills/secret-mgmt.md +65 -0
  115. package/extensions/security/skills/supply-chain.md +65 -0
  116. package/extensions/trading/PACK.md +18 -535
  117. package/extensions/trading/skills/chart-components.md +55 -0
  118. package/extensions/trading/skills/experiment-loop.md +125 -0
  119. package/extensions/trading/skills/fintech-patterns.md +47 -0
  120. package/extensions/trading/skills/indicator-library.md +58 -0
  121. package/extensions/trading/skills/quant-analysis.md +111 -0
  122. package/extensions/trading/skills/realtime-data.md +58 -0
  123. package/extensions/trading/skills/trade-logic.md +104 -0
  124. package/extensions/ui/PACK.md +34 -853
  125. package/extensions/ui/skills/a11y-audit.md +91 -0
  126. package/extensions/ui/skills/animation-patterns.md +106 -0
  127. package/extensions/ui/skills/component-patterns.md +75 -0
  128. package/extensions/ui/skills/design-decision.md +98 -0
  129. package/extensions/ui/skills/design-system.md +68 -0
  130. package/extensions/ui/skills/landing-patterns.md +155 -0
  131. package/extensions/ui/skills/palette-picker.md +162 -0
  132. package/extensions/ui/skills/react-health.md +90 -0
  133. package/extensions/ui/skills/type-system.md +125 -0
  134. package/extensions/ui/skills/web-vitals.md +153 -0
  135. package/extensions/zalo/PACK.md +117 -0
  136. package/extensions/zalo/skills/zalo-oa-mcp.md +317 -0
  137. package/extensions/zalo/skills/zalo-oa-messaging.md +429 -0
  138. package/extensions/zalo/skills/zalo-oa-setup.md +236 -0
  139. package/extensions/zalo/skills/zalo-oa-webhook.md +189 -0
  140. package/extensions/zalo/skills/zalo-personal-messaging.md +194 -0
  141. package/extensions/zalo/skills/zalo-personal-setup.md +153 -0
  142. package/extensions/zalo/skills/zalo-rate-guard.md +219 -0
  143. package/package.json +5 -2
  144. package/skills/brainstorm/SKILL.md +63 -1
  145. package/skills/cook/SKILL.md +89 -6
  146. package/skills/debug/SKILL.md +5 -0
  147. package/skills/fix/SKILL.md +5 -0
  148. package/skills/mcp-builder/SKILL.md +48 -1
  149. package/skills/neural-memory/SKILL.md +362 -0
  150. package/skills/plan/SKILL.md +3 -0
  151. package/skills/rescue/SKILL.md +5 -0
  152. package/skills/review/SKILL.md +44 -5
  153. package/skills/review-intake/SKILL.md +17 -1
  154. package/skills/skill-router/SKILL.md +106 -8
  155. package/skills/team/SKILL.md +24 -1
  156. package/skills/test/SKILL.md +18 -0
  157. package/skills/verification/SKILL.md +40 -1
@@ -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
- const fileName = outputFileName(parsed.name, adapter);
128
- const outputPath = path.join(outputDir, fileName);
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(fileName);
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
- const packName = path.basename(path.dirname(packPath));
149
- const fileName = outputFileName(`ext-${packName}`, adapter);
150
- const outputPath = path.join(outputDir, fileName);
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(fileName);
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.includes('ext-') && !f.includes('index'))
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.includes('ext-'));
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
  }
@@ -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
+ }
@@ -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. Platform-specific post-processing
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
- // 5. Generate header (platform-specific frontmatter/preamble)
50
+ // 6. Generate header (platform-specific frontmatter/preamble)
47
51
  const header = adapter.generateHeader(parsedSkill);
48
52
 
49
- // 6. Generate hook constraints section
53
+ // 7. Generate hook constraints section
50
54
  const hookConstraints = generateHookConstraints(parsedSkill, adapter);
51
55
 
52
- // 7. Inject hook constraints after the first heading
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
- // 8. Generate footer (branding + CTA)
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** — 49 skills, 170+ connections',
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
+ }