@rune-kit/rune 2.6.0 → 2.7.0
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 +17 -6
- package/compiler/__tests__/executive-dashboards.test.js +285 -0
- package/compiler/__tests__/inject.test.js +128 -0
- package/compiler/__tests__/orchestrators.test.js +151 -0
- package/compiler/__tests__/org-templates.test.js +447 -0
- package/compiler/__tests__/parser.test.js +201 -147
- package/compiler/__tests__/skill-index.test.js +218 -218
- package/compiler/__tests__/status.test.js +336 -0
- package/compiler/__tests__/templates.test.js +245 -0
- package/compiler/__tests__/visualizer.test.js +325 -0
- package/compiler/adapters/antigravity.js +71 -71
- package/compiler/bin/rune.js +444 -355
- package/compiler/doctor.js +272 -1
- package/compiler/emitter.js +939 -678
- package/compiler/parser.js +498 -267
- package/compiler/status.js +342 -0
- package/compiler/visualizer.js +622 -0
- package/package.json +1 -1
- package/skills/autopsy/SKILL.md +48 -1
- package/skills/completion-gate/SKILL.md +26 -1
- package/skills/context-engine/SKILL.md +93 -2
- package/skills/cook/SKILL.md +137 -4
- package/skills/debug/SKILL.md +16 -1
- package/skills/docs/SKILL.md +28 -3
- package/skills/fix/SKILL.md +2 -1
- package/skills/mcp-builder/SKILL.md +53 -1
- package/skills/onboard/SKILL.md +51 -1
- package/skills/perf/SKILL.md +34 -1
- package/skills/plan/SKILL.md +29 -1
- package/skills/preflight/SKILL.md +35 -1
- package/skills/retro/SKILL.md +95 -1
- package/skills/review/SKILL.md +45 -1
- package/skills/scope-guard/SKILL.md +1 -0
- package/skills/sentinel/SKILL.md +35 -1
- package/skills/sentinel/references/policy-driven-constraints.md +424 -0
- package/skills/session-bridge/SKILL.md +57 -2
- package/skills/session-bridge/references/evolutionary-memory-patterns.md +312 -0
- package/skills/team/SKILL.md +15 -1
|
@@ -1,147 +1,201 @@
|
|
|
1
|
-
import assert from 'node:assert';
|
|
2
|
-
import { readFileSync } from 'node:fs';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import { describe, test } from 'node:test';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
6
|
-
import { parseSkill } from '../parser.js';
|
|
7
|
-
|
|
8
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
-
const SKILLS_DIR = path.resolve(__dirname, '../../skills');
|
|
10
|
-
|
|
11
|
-
test('parse cook SKILL.md', () => {
|
|
12
|
-
const content = readFileSync(path.join(SKILLS_DIR, 'cook/SKILL.md'), 'utf-8');
|
|
13
|
-
const parsed = parseSkill(content, 'cook/SKILL.md');
|
|
14
|
-
|
|
15
|
-
console.log('name:', JSON.stringify(parsed.name));
|
|
16
|
-
console.log('description:', JSON.stringify(parsed.description?.substring(0, 50)));
|
|
17
|
-
console.log('layer:', parsed.layer);
|
|
18
|
-
console.log('model:', parsed.model);
|
|
19
|
-
console.log('group:', parsed.group);
|
|
20
|
-
console.log('contextFork:', parsed.contextFork);
|
|
21
|
-
console.log('agentType:', parsed.agentType);
|
|
22
|
-
console.log('crossRefs:', parsed.crossRefs.length);
|
|
23
|
-
console.log('toolRefs:', parsed.toolRefs.length);
|
|
24
|
-
console.log('hardGates:', parsed.hardGates.length);
|
|
25
|
-
console.log('sections:', [...parsed.sections.keys()]);
|
|
26
|
-
console.log('frontmatter keys:', Object.keys(parsed.frontmatter));
|
|
27
|
-
|
|
28
|
-
assert.strictEqual(parsed.name, 'cook');
|
|
29
|
-
assert.strictEqual(parsed.layer, 'L1');
|
|
30
|
-
assert.ok(parsed.crossRefs.length > 0);
|
|
31
|
-
assert.ok(parsed.hardGates.length > 0);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
test('parse fix SKILL.md', () => {
|
|
35
|
-
const content = readFileSync(path.join(SKILLS_DIR, 'fix/SKILL.md'), 'utf-8');
|
|
36
|
-
const parsed = parseSkill(content, 'fix/SKILL.md');
|
|
37
|
-
|
|
38
|
-
console.log('fix name:', JSON.stringify(parsed.name));
|
|
39
|
-
console.log('fix layer:', parsed.layer);
|
|
40
|
-
|
|
41
|
-
assert.strictEqual(parsed.name, 'fix');
|
|
42
|
-
assert.strictEqual(parsed.layer, 'L2');
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test('parse verification SKILL.md', () => {
|
|
46
|
-
const content = readFileSync(path.join(SKILLS_DIR, 'verification/SKILL.md'), 'utf-8');
|
|
47
|
-
const parsed = parseSkill(content, 'verification/SKILL.md');
|
|
48
|
-
|
|
49
|
-
console.log('verification name:', JSON.stringify(parsed.name));
|
|
50
|
-
console.log('verification layer:', parsed.layer);
|
|
51
|
-
console.log('verification toolRefs:', parsed.toolRefs.length);
|
|
52
|
-
|
|
53
|
-
assert.strictEqual(parsed.name, 'verification');
|
|
54
|
-
assert.strictEqual(parsed.layer, 'L3');
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
describe('signals parsing', () => {
|
|
58
|
-
test('parses emit and listen from metadata', () => {
|
|
59
|
-
const content = [
|
|
60
|
-
'---',
|
|
61
|
-
'name: alpha',
|
|
62
|
-
'description: "Test skill"',
|
|
63
|
-
'metadata:',
|
|
64
|
-
' layer: L2',
|
|
65
|
-
' emit: code.changed, tests.passed',
|
|
66
|
-
' listen: plan.ready',
|
|
67
|
-
'---',
|
|
68
|
-
'',
|
|
69
|
-
'# alpha',
|
|
70
|
-
].join('\n');
|
|
71
|
-
|
|
72
|
-
const parsed = parseSkill(content);
|
|
73
|
-
assert.ok(parsed.signals, 'signals should not be null');
|
|
74
|
-
assert.deepStrictEqual(parsed.signals.emit, ['code.changed', 'tests.passed']);
|
|
75
|
-
assert.deepStrictEqual(parsed.signals.listen, ['plan.ready']);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test('emit only — no listen', () => {
|
|
79
|
-
const content = [
|
|
80
|
-
'---',
|
|
81
|
-
'name: beta',
|
|
82
|
-
'description: "Emitter only"',
|
|
83
|
-
'metadata:',
|
|
84
|
-
' layer: L3',
|
|
85
|
-
' emit: deploy.complete',
|
|
86
|
-
'---',
|
|
87
|
-
'',
|
|
88
|
-
'# beta',
|
|
89
|
-
].join('\n');
|
|
90
|
-
|
|
91
|
-
const parsed = parseSkill(content);
|
|
92
|
-
assert.ok(parsed.signals);
|
|
93
|
-
assert.deepStrictEqual(parsed.signals.emit, ['deploy.complete']);
|
|
94
|
-
assert.deepStrictEqual(parsed.signals.listen, []);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
test('listen only — no emit', () => {
|
|
98
|
-
const content = [
|
|
99
|
-
'---',
|
|
100
|
-
'name: gamma',
|
|
101
|
-
'description: "Listener only"',
|
|
102
|
-
'metadata:',
|
|
103
|
-
' layer: L3',
|
|
104
|
-
' listen: code.changed',
|
|
105
|
-
'---',
|
|
106
|
-
'',
|
|
107
|
-
'# gamma',
|
|
108
|
-
].join('\n');
|
|
109
|
-
|
|
110
|
-
const parsed = parseSkill(content);
|
|
111
|
-
assert.ok(parsed.signals);
|
|
112
|
-
assert.deepStrictEqual(parsed.signals.emit, []);
|
|
113
|
-
assert.deepStrictEqual(parsed.signals.listen, ['code.changed']);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
test('no signals — returns null', () => {
|
|
117
|
-
const content = [
|
|
118
|
-
'---',
|
|
119
|
-
'name: delta',
|
|
120
|
-
'description: "No signals"',
|
|
121
|
-
'metadata:',
|
|
122
|
-
' layer: L3',
|
|
123
|
-
'---',
|
|
124
|
-
'',
|
|
125
|
-
'# delta',
|
|
126
|
-
].join('\n');
|
|
127
|
-
|
|
128
|
-
const parsed = parseSkill(content);
|
|
129
|
-
assert.strictEqual(parsed.signals, null);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test('real cook skill has signals', () => {
|
|
133
|
-
const content = readFileSync(path.join(SKILLS_DIR, 'cook/SKILL.md'), 'utf-8');
|
|
134
|
-
const parsed = parseSkill(content, 'cook/SKILL.md');
|
|
135
|
-
assert.ok(parsed.signals, 'cook should have signals');
|
|
136
|
-
assert.ok(parsed.signals.emit.includes('phase.complete'));
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test('real test skill has emit and listen', () => {
|
|
140
|
-
const content = readFileSync(path.join(SKILLS_DIR, 'test/SKILL.md'), 'utf-8');
|
|
141
|
-
const parsed = parseSkill(content, 'test/SKILL.md');
|
|
142
|
-
assert.ok(parsed.signals, 'test should have signals');
|
|
143
|
-
assert.ok(parsed.signals.emit.includes('tests.passed'));
|
|
144
|
-
assert.ok(parsed.signals.emit.includes('tests.failed'));
|
|
145
|
-
assert.ok(parsed.signals.listen.includes('code.changed'));
|
|
146
|
-
});
|
|
147
|
-
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { describe, test } from 'node:test';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { parseSkill } from '../parser.js';
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const SKILLS_DIR = path.resolve(__dirname, '../../skills');
|
|
10
|
+
|
|
11
|
+
test('parse cook SKILL.md', () => {
|
|
12
|
+
const content = readFileSync(path.join(SKILLS_DIR, 'cook/SKILL.md'), 'utf-8');
|
|
13
|
+
const parsed = parseSkill(content, 'cook/SKILL.md');
|
|
14
|
+
|
|
15
|
+
console.log('name:', JSON.stringify(parsed.name));
|
|
16
|
+
console.log('description:', JSON.stringify(parsed.description?.substring(0, 50)));
|
|
17
|
+
console.log('layer:', parsed.layer);
|
|
18
|
+
console.log('model:', parsed.model);
|
|
19
|
+
console.log('group:', parsed.group);
|
|
20
|
+
console.log('contextFork:', parsed.contextFork);
|
|
21
|
+
console.log('agentType:', parsed.agentType);
|
|
22
|
+
console.log('crossRefs:', parsed.crossRefs.length);
|
|
23
|
+
console.log('toolRefs:', parsed.toolRefs.length);
|
|
24
|
+
console.log('hardGates:', parsed.hardGates.length);
|
|
25
|
+
console.log('sections:', [...parsed.sections.keys()]);
|
|
26
|
+
console.log('frontmatter keys:', Object.keys(parsed.frontmatter));
|
|
27
|
+
|
|
28
|
+
assert.strictEqual(parsed.name, 'cook');
|
|
29
|
+
assert.strictEqual(parsed.layer, 'L1');
|
|
30
|
+
assert.ok(parsed.crossRefs.length > 0);
|
|
31
|
+
assert.ok(parsed.hardGates.length > 0);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('parse fix SKILL.md', () => {
|
|
35
|
+
const content = readFileSync(path.join(SKILLS_DIR, 'fix/SKILL.md'), 'utf-8');
|
|
36
|
+
const parsed = parseSkill(content, 'fix/SKILL.md');
|
|
37
|
+
|
|
38
|
+
console.log('fix name:', JSON.stringify(parsed.name));
|
|
39
|
+
console.log('fix layer:', parsed.layer);
|
|
40
|
+
|
|
41
|
+
assert.strictEqual(parsed.name, 'fix');
|
|
42
|
+
assert.strictEqual(parsed.layer, 'L2');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('parse verification SKILL.md', () => {
|
|
46
|
+
const content = readFileSync(path.join(SKILLS_DIR, 'verification/SKILL.md'), 'utf-8');
|
|
47
|
+
const parsed = parseSkill(content, 'verification/SKILL.md');
|
|
48
|
+
|
|
49
|
+
console.log('verification name:', JSON.stringify(parsed.name));
|
|
50
|
+
console.log('verification layer:', parsed.layer);
|
|
51
|
+
console.log('verification toolRefs:', parsed.toolRefs.length);
|
|
52
|
+
|
|
53
|
+
assert.strictEqual(parsed.name, 'verification');
|
|
54
|
+
assert.strictEqual(parsed.layer, 'L3');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('signals parsing', () => {
|
|
58
|
+
test('parses emit and listen from metadata', () => {
|
|
59
|
+
const content = [
|
|
60
|
+
'---',
|
|
61
|
+
'name: alpha',
|
|
62
|
+
'description: "Test skill"',
|
|
63
|
+
'metadata:',
|
|
64
|
+
' layer: L2',
|
|
65
|
+
' emit: code.changed, tests.passed',
|
|
66
|
+
' listen: plan.ready',
|
|
67
|
+
'---',
|
|
68
|
+
'',
|
|
69
|
+
'# alpha',
|
|
70
|
+
].join('\n');
|
|
71
|
+
|
|
72
|
+
const parsed = parseSkill(content);
|
|
73
|
+
assert.ok(parsed.signals, 'signals should not be null');
|
|
74
|
+
assert.deepStrictEqual(parsed.signals.emit, ['code.changed', 'tests.passed']);
|
|
75
|
+
assert.deepStrictEqual(parsed.signals.listen, ['plan.ready']);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('emit only — no listen', () => {
|
|
79
|
+
const content = [
|
|
80
|
+
'---',
|
|
81
|
+
'name: beta',
|
|
82
|
+
'description: "Emitter only"',
|
|
83
|
+
'metadata:',
|
|
84
|
+
' layer: L3',
|
|
85
|
+
' emit: deploy.complete',
|
|
86
|
+
'---',
|
|
87
|
+
'',
|
|
88
|
+
'# beta',
|
|
89
|
+
].join('\n');
|
|
90
|
+
|
|
91
|
+
const parsed = parseSkill(content);
|
|
92
|
+
assert.ok(parsed.signals);
|
|
93
|
+
assert.deepStrictEqual(parsed.signals.emit, ['deploy.complete']);
|
|
94
|
+
assert.deepStrictEqual(parsed.signals.listen, []);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('listen only — no emit', () => {
|
|
98
|
+
const content = [
|
|
99
|
+
'---',
|
|
100
|
+
'name: gamma',
|
|
101
|
+
'description: "Listener only"',
|
|
102
|
+
'metadata:',
|
|
103
|
+
' layer: L3',
|
|
104
|
+
' listen: code.changed',
|
|
105
|
+
'---',
|
|
106
|
+
'',
|
|
107
|
+
'# gamma',
|
|
108
|
+
].join('\n');
|
|
109
|
+
|
|
110
|
+
const parsed = parseSkill(content);
|
|
111
|
+
assert.ok(parsed.signals);
|
|
112
|
+
assert.deepStrictEqual(parsed.signals.emit, []);
|
|
113
|
+
assert.deepStrictEqual(parsed.signals.listen, ['code.changed']);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('no signals — returns null', () => {
|
|
117
|
+
const content = [
|
|
118
|
+
'---',
|
|
119
|
+
'name: delta',
|
|
120
|
+
'description: "No signals"',
|
|
121
|
+
'metadata:',
|
|
122
|
+
' layer: L3',
|
|
123
|
+
'---',
|
|
124
|
+
'',
|
|
125
|
+
'# delta',
|
|
126
|
+
].join('\n');
|
|
127
|
+
|
|
128
|
+
const parsed = parseSkill(content);
|
|
129
|
+
assert.strictEqual(parsed.signals, null);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test('real cook skill has signals', () => {
|
|
133
|
+
const content = readFileSync(path.join(SKILLS_DIR, 'cook/SKILL.md'), 'utf-8');
|
|
134
|
+
const parsed = parseSkill(content, 'cook/SKILL.md');
|
|
135
|
+
assert.ok(parsed.signals, 'cook should have signals');
|
|
136
|
+
assert.ok(parsed.signals.emit.includes('phase.complete'));
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test('real test skill has emit and listen', () => {
|
|
140
|
+
const content = readFileSync(path.join(SKILLS_DIR, 'test/SKILL.md'), 'utf-8');
|
|
141
|
+
const parsed = parseSkill(content, 'test/SKILL.md');
|
|
142
|
+
assert.ok(parsed.signals, 'test should have signals');
|
|
143
|
+
assert.ok(parsed.signals.emit.includes('tests.passed'));
|
|
144
|
+
assert.ok(parsed.signals.emit.includes('tests.failed'));
|
|
145
|
+
assert.ok(parsed.signals.listen.includes('code.changed'));
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test('top-level emit/listen (Pro/Business pack format)', () => {
|
|
149
|
+
const content = [
|
|
150
|
+
'---',
|
|
151
|
+
'name: "feature-spec"',
|
|
152
|
+
'pack: "@rune-pro/product"',
|
|
153
|
+
'version: "1.2.0"',
|
|
154
|
+
'model: opus',
|
|
155
|
+
'tools: [Read, Write]',
|
|
156
|
+
'emit: product.spec.drafted',
|
|
157
|
+
'listen: sales.account.researched, product.research.complete',
|
|
158
|
+
'---',
|
|
159
|
+
'',
|
|
160
|
+
'# feature-spec',
|
|
161
|
+
].join('\n');
|
|
162
|
+
|
|
163
|
+
const parsed = parseSkill(content);
|
|
164
|
+
assert.ok(parsed.signals, 'top-level signals should be parsed');
|
|
165
|
+
assert.deepStrictEqual(parsed.signals.emit, ['product.spec.drafted']);
|
|
166
|
+
assert.deepStrictEqual(parsed.signals.listen, ['sales.account.researched', 'product.research.complete']);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test('top-level emit only (no listen)', () => {
|
|
170
|
+
const content = [
|
|
171
|
+
'---',
|
|
172
|
+
'name: "account-research"',
|
|
173
|
+
'emit: sales.account.researched',
|
|
174
|
+
'---',
|
|
175
|
+
'',
|
|
176
|
+
'# account-research',
|
|
177
|
+
].join('\n');
|
|
178
|
+
|
|
179
|
+
const parsed = parseSkill(content);
|
|
180
|
+
assert.ok(parsed.signals);
|
|
181
|
+
assert.deepStrictEqual(parsed.signals.emit, ['sales.account.researched']);
|
|
182
|
+
assert.deepStrictEqual(parsed.signals.listen, []);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test('metadata emit takes precedence over top-level', () => {
|
|
186
|
+
const content = [
|
|
187
|
+
'---',
|
|
188
|
+
'name: "hybrid"',
|
|
189
|
+
'emit: top.level.signal',
|
|
190
|
+
'metadata:',
|
|
191
|
+
' emit: nested.signal',
|
|
192
|
+
'---',
|
|
193
|
+
'',
|
|
194
|
+
'# hybrid',
|
|
195
|
+
].join('\n');
|
|
196
|
+
|
|
197
|
+
const parsed = parseSkill(content);
|
|
198
|
+
assert.ok(parsed.signals);
|
|
199
|
+
assert.deepStrictEqual(parsed.signals.emit, ['nested.signal']);
|
|
200
|
+
});
|
|
201
|
+
});
|