@soleri/core 9.13.0 → 9.14.4
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/dist/engine/bin/soleri-engine.js +7 -2
- package/dist/engine/bin/soleri-engine.js.map +1 -1
- package/dist/flows/types.d.ts +34 -30
- package/dist/flows/types.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/knowledge-packs/community/.gitkeep +0 -0
- package/dist/knowledge-packs/salvador/salvador-craft/soleri-pack.json +10 -0
- package/dist/knowledge-packs/salvador/salvador-craft/vault/accessibility.json +53 -0
- package/dist/knowledge-packs/salvador/salvador-craft/vault/design-tokens.json +26 -0
- package/dist/knowledge-packs/salvador/salvador-craft/vault/design.json +33 -0
- package/dist/knowledge-packs/salvador/salvador-craft/vault/styling.json +44 -0
- package/dist/knowledge-packs/salvador/salvador-craft/vault/ux-laws.json +36 -0
- package/dist/knowledge-packs/salvador/salvador-craft/vault/ux.json +36 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/soleri-pack.json +10 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/architecture.json +143 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/commercial.json +16 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/communication.json +33 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/component.json +16 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/express.json +34 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/leadership.json +33 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/methodology.json +33 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/monorepo.json +33 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/other.json +73 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/performance.json +35 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/prisma.json +33 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/product-strategy.json +42 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/react.json +47 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/security.json +34 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/testing.json +33 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/tooling.json +85 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/typescript.json +34 -0
- package/dist/knowledge-packs/salvador/salvador-engineering/vault/workflow.json +46 -0
- package/dist/knowledge-packs/salvador/salvador-uipro/soleri-pack.json +10 -0
- package/dist/knowledge-packs/salvador/salvador-uipro/vault/design.json +2589 -0
- package/dist/knowledge-packs/starter/api-design/soleri-pack.json +9 -0
- package/dist/knowledge-packs/starter/api-design/vault/patterns.json +137 -0
- package/dist/knowledge-packs/starter/architecture/soleri-pack.json +10 -0
- package/dist/knowledge-packs/starter/architecture/vault/patterns.json +137 -0
- package/dist/knowledge-packs/starter/design/soleri-pack.json +10 -0
- package/dist/knowledge-packs/starter/design/vault/patterns.json +137 -0
- package/dist/knowledge-packs/starter/nodejs/soleri-pack.json +9 -0
- package/dist/knowledge-packs/starter/nodejs/vault/patterns.json +137 -0
- package/dist/knowledge-packs/starter/react/soleri-pack.json +9 -0
- package/dist/knowledge-packs/starter/react/vault/patterns.json +164 -0
- package/dist/knowledge-packs/starter/security/soleri-pack.json +10 -0
- package/dist/knowledge-packs/starter/security/vault/patterns.json +137 -0
- package/dist/knowledge-packs/starter/testing/soleri-pack.json +9 -0
- package/dist/knowledge-packs/starter/testing/vault/patterns.json +128 -0
- package/dist/knowledge-packs/starter/typescript/soleri-pack.json +9 -0
- package/dist/knowledge-packs/starter/typescript/vault/patterns.json +164 -0
- package/dist/packs/index.d.ts +1 -1
- package/dist/packs/index.d.ts.map +1 -1
- package/dist/packs/index.js +1 -1
- package/dist/packs/index.js.map +1 -1
- package/dist/packs/resolver.d.ts +6 -0
- package/dist/packs/resolver.d.ts.map +1 -1
- package/dist/packs/resolver.js +20 -1
- package/dist/packs/resolver.js.map +1 -1
- package/dist/runtime/admin-setup-ops.js +1 -1
- package/dist/runtime/admin-setup-ops.js.map +1 -1
- package/dist/runtime/capture-ops.d.ts.map +1 -1
- package/dist/runtime/capture-ops.js +2 -1
- package/dist/runtime/capture-ops.js.map +1 -1
- package/dist/runtime/intake-ops.d.ts.map +1 -1
- package/dist/runtime/intake-ops.js +5 -5
- package/dist/runtime/intake-ops.js.map +1 -1
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
- package/dist/runtime/orchestrate-ops.js +26 -2
- package/dist/runtime/orchestrate-ops.js.map +1 -1
- package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
- package/dist/runtime/planning-extra-ops.js +5 -7
- package/dist/runtime/planning-extra-ops.js.map +1 -1
- package/dist/runtime/playbook-ops.d.ts.map +1 -1
- package/dist/runtime/playbook-ops.js +2 -1
- package/dist/runtime/playbook-ops.js.map +1 -1
- package/dist/runtime/schema-helpers.d.ts +7 -0
- package/dist/runtime/schema-helpers.d.ts.map +1 -0
- package/dist/runtime/schema-helpers.js +21 -0
- package/dist/runtime/schema-helpers.js.map +1 -0
- package/dist/runtime/sync-ops.d.ts.map +1 -1
- package/dist/runtime/sync-ops.js +3 -4
- package/dist/runtime/sync-ops.js.map +1 -1
- package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
- package/dist/runtime/vault-extra-ops.js +5 -4
- package/dist/runtime/vault-extra-ops.js.map +1 -1
- package/dist/skills/sync-skills.d.ts +26 -7
- package/dist/skills/sync-skills.d.ts.map +1 -1
- package/dist/skills/sync-skills.js +132 -32
- package/dist/skills/sync-skills.js.map +1 -1
- package/dist/skills/validate-skill-docs.d.ts +24 -0
- package/dist/skills/validate-skill-docs.d.ts.map +1 -0
- package/dist/skills/validate-skill-docs.js +476 -0
- package/dist/skills/validate-skill-docs.js.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/deviation-detection.test.ts +49 -0
- package/src/enforcement/adapters/claude-code.test.ts +9 -9
- package/src/engine/bin/soleri-engine.ts +7 -2
- package/src/flows/types.ts +4 -0
- package/src/index.ts +15 -2
- package/src/packs/index.ts +6 -1
- package/src/packs/resolver.ts +24 -1
- package/src/runtime/admin-setup-ops.test.ts +2 -0
- package/src/runtime/admin-setup-ops.ts +1 -1
- package/src/runtime/capture-ops.ts +2 -1
- package/src/runtime/intake-ops.ts +7 -7
- package/src/runtime/orchestrate-ops.ts +29 -2
- package/src/runtime/planning-extra-ops.ts +35 -37
- package/src/runtime/playbook-ops.ts +2 -1
- package/src/runtime/schema-helpers.test.ts +45 -0
- package/src/runtime/schema-helpers.ts +19 -0
- package/src/runtime/sync-ops.ts +8 -9
- package/src/runtime/vault-extra-ops.ts +5 -4
- package/src/skills/__tests__/sync-skills.test.ts +102 -29
- package/src/skills/__tests__/validate-skill-docs.test.ts +58 -0
- package/src/skills/sync-skills.ts +152 -32
- package/src/skills/validate-skill-docs.ts +562 -0
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build-time validator for SKILL.md inline op-call examples.
|
|
3
|
+
*
|
|
4
|
+
* Parses `YOUR_AGENT_core op:<name> params: { ... }` blocks in SKILL.md files
|
|
5
|
+
* and validates the params against the actual Zod schemas defined in the
|
|
6
|
+
* facade source files.
|
|
7
|
+
*
|
|
8
|
+
* Usage: tsx packages/core/src/skills/validate-skill-docs.ts
|
|
9
|
+
* Exit 0 = all valid, Exit 1 = mismatches found.
|
|
10
|
+
*/
|
|
11
|
+
import { readFileSync, readdirSync, existsSync } from 'node:fs';
|
|
12
|
+
import { join, resolve, relative } from 'node:path';
|
|
13
|
+
// ── Facade factory imports ──────────────────────────────────────────────
|
|
14
|
+
import { createVaultFacadeOps } from '../runtime/facades/vault-facade.js';
|
|
15
|
+
import { createPlanFacadeOps } from '../runtime/facades/plan-facade.js';
|
|
16
|
+
import { createBrainFacadeOps } from '../runtime/facades/brain-facade.js';
|
|
17
|
+
import { createMemoryFacadeOps } from '../runtime/facades/memory-facade.js';
|
|
18
|
+
import { createAdminFacadeOps } from '../runtime/facades/admin-facade.js';
|
|
19
|
+
import { createCuratorFacadeOps } from '../runtime/facades/curator-facade.js';
|
|
20
|
+
import { createLoopFacadeOps } from '../runtime/facades/loop-facade.js';
|
|
21
|
+
import { createOrchestrateFacadeOps } from '../runtime/facades/orchestrate-facade.js';
|
|
22
|
+
import { createControlFacadeOps } from '../runtime/facades/control-facade.js';
|
|
23
|
+
import { createContextFacadeOps } from '../runtime/facades/context-facade.js';
|
|
24
|
+
import { createAgencyFacadeOps } from '../runtime/facades/agency-facade.js';
|
|
25
|
+
import { createChatFacadeOps } from '../runtime/facades/chat-facade.js';
|
|
26
|
+
import { createOperatorFacadeOps } from '../runtime/facades/operator-facade.js';
|
|
27
|
+
import { createArchiveFacadeOps } from '../runtime/facades/archive-facade.js';
|
|
28
|
+
import { createSyncFacadeOps } from '../runtime/facades/sync-facade.js';
|
|
29
|
+
import { createReviewFacadeOps } from '../runtime/facades/review-facade.js';
|
|
30
|
+
import { createIntakeFacadeOps } from '../runtime/facades/intake-facade.js';
|
|
31
|
+
import { createLinksFacadeOps } from '../runtime/facades/links-facade.js';
|
|
32
|
+
import { createBranchingFacadeOps } from '../runtime/facades/branching-facade.js';
|
|
33
|
+
import { createTierFacadeOps } from '../runtime/facades/tier-facade.js';
|
|
34
|
+
import { createEmbeddingFacadeOps } from '../runtime/facades/embedding-facade.js';
|
|
35
|
+
// ── Mock runtime ────────────────────────────────────────────────────────
|
|
36
|
+
// Schemas are constructed during factory calls but handlers are never invoked,
|
|
37
|
+
// so a recursive proxy that returns itself for any property access is enough.
|
|
38
|
+
function createNoopProxy() {
|
|
39
|
+
const handler = {
|
|
40
|
+
get(_target, prop) {
|
|
41
|
+
// Return primitives for common property checks
|
|
42
|
+
if (prop === Symbol.toPrimitive)
|
|
43
|
+
return () => '';
|
|
44
|
+
if (prop === Symbol.iterator)
|
|
45
|
+
return undefined;
|
|
46
|
+
if (prop === 'then')
|
|
47
|
+
return undefined; // prevent Promise detection
|
|
48
|
+
if (prop === 'toString')
|
|
49
|
+
return () => '[mock]';
|
|
50
|
+
if (prop === 'valueOf')
|
|
51
|
+
return () => 0;
|
|
52
|
+
if (prop === 'length')
|
|
53
|
+
return 0;
|
|
54
|
+
// Return a callable proxy for methods
|
|
55
|
+
return new Proxy(function () { }, handler);
|
|
56
|
+
},
|
|
57
|
+
apply() {
|
|
58
|
+
// When called as a function, return a new proxy
|
|
59
|
+
return new Proxy({}, handler);
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
return new Proxy({}, handler);
|
|
63
|
+
}
|
|
64
|
+
// ── Schema registry ─────────────────────────────────────────────────────
|
|
65
|
+
// Build a flat map of opName → ZodSchema from all facades.
|
|
66
|
+
function buildSchemaRegistry() {
|
|
67
|
+
const runtime = createNoopProxy();
|
|
68
|
+
const registry = new Map();
|
|
69
|
+
const facadeFactories = [
|
|
70
|
+
createVaultFacadeOps,
|
|
71
|
+
createPlanFacadeOps,
|
|
72
|
+
createBrainFacadeOps,
|
|
73
|
+
createMemoryFacadeOps,
|
|
74
|
+
createAdminFacadeOps,
|
|
75
|
+
createCuratorFacadeOps,
|
|
76
|
+
createLoopFacadeOps,
|
|
77
|
+
createOrchestrateFacadeOps,
|
|
78
|
+
createControlFacadeOps,
|
|
79
|
+
createContextFacadeOps,
|
|
80
|
+
createAgencyFacadeOps,
|
|
81
|
+
createChatFacadeOps,
|
|
82
|
+
createOperatorFacadeOps,
|
|
83
|
+
createArchiveFacadeOps,
|
|
84
|
+
createSyncFacadeOps,
|
|
85
|
+
createReviewFacadeOps,
|
|
86
|
+
createIntakeFacadeOps,
|
|
87
|
+
createLinksFacadeOps,
|
|
88
|
+
createBranchingFacadeOps,
|
|
89
|
+
createTierFacadeOps,
|
|
90
|
+
createEmbeddingFacadeOps,
|
|
91
|
+
];
|
|
92
|
+
for (const factory of facadeFactories) {
|
|
93
|
+
try {
|
|
94
|
+
const ops = factory(runtime);
|
|
95
|
+
for (const op of ops) {
|
|
96
|
+
if (op.schema) {
|
|
97
|
+
registry.set(op.name, op.schema);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// Some facades may fail with the mock runtime — skip them.
|
|
103
|
+
// Schemas from other facades still get registered.
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return registry;
|
|
107
|
+
}
|
|
108
|
+
// ── SKILL.md parser ─────────────────────────────────────────────────────
|
|
109
|
+
// Extracts op-call examples from fenced code blocks.
|
|
110
|
+
//
|
|
111
|
+
// Formats matched:
|
|
112
|
+
// YOUR_AGENT_core op:<name>
|
|
113
|
+
// YOUR_AGENT_core op:<name> params: { ... }
|
|
114
|
+
// YOUR_AGENT_core op:<name>
|
|
115
|
+
// params: { ... }
|
|
116
|
+
function extractOpExamples(filePath) {
|
|
117
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
118
|
+
const lines = content.split('\n');
|
|
119
|
+
const examples = [];
|
|
120
|
+
// Track code blocks
|
|
121
|
+
let inCodeBlock = false;
|
|
122
|
+
let codeBlockStart = -1;
|
|
123
|
+
let codeBlockLines = [];
|
|
124
|
+
for (let i = 0; i < lines.length; i++) {
|
|
125
|
+
const line = lines[i];
|
|
126
|
+
if (line.trimStart().startsWith('```')) {
|
|
127
|
+
if (!inCodeBlock) {
|
|
128
|
+
inCodeBlock = true;
|
|
129
|
+
codeBlockStart = i + 1;
|
|
130
|
+
codeBlockLines = [];
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// Process the code block
|
|
134
|
+
extractFromCodeBlock(filePath, codeBlockStart, codeBlockLines, examples);
|
|
135
|
+
inCodeBlock = false;
|
|
136
|
+
codeBlockLines = [];
|
|
137
|
+
}
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (inCodeBlock) {
|
|
141
|
+
codeBlockLines.push(line);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return examples;
|
|
145
|
+
}
|
|
146
|
+
function extractFromCodeBlock(filePath, startLine, blockLines, results) {
|
|
147
|
+
// Pattern: YOUR_AGENT_core op:<name> [params: { ... }]
|
|
148
|
+
// Also matches: op:<name> params: { ... } (without facade prefix)
|
|
149
|
+
const opPattern = /(?:YOUR_AGENT_\w+\s+)?op:(\w+)(?:\s+params:\s*(.*))?/;
|
|
150
|
+
for (let i = 0; i < blockLines.length; i++) {
|
|
151
|
+
const line = blockLines[i];
|
|
152
|
+
const match = line.match(opPattern);
|
|
153
|
+
if (!match)
|
|
154
|
+
continue;
|
|
155
|
+
const opName = match[1];
|
|
156
|
+
const lineNum = startLine + i + 1; // 1-indexed
|
|
157
|
+
// Collect params — may be inline or on following lines
|
|
158
|
+
let rawParams = '';
|
|
159
|
+
if (match[2]) {
|
|
160
|
+
// Params start on same line
|
|
161
|
+
rawParams = match[2].trim();
|
|
162
|
+
}
|
|
163
|
+
else if (i + 1 < blockLines.length && blockLines[i + 1].trim().startsWith('params:')) {
|
|
164
|
+
// Params on next line(s)
|
|
165
|
+
const paramsLine = blockLines[i + 1].trim();
|
|
166
|
+
const paramsMatch = paramsLine.match(/^params:\s*(.*)/);
|
|
167
|
+
if (paramsMatch) {
|
|
168
|
+
rawParams = paramsMatch[1].trim();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// If we found params start, collect the full multi-line object
|
|
172
|
+
if (rawParams) {
|
|
173
|
+
// Collect continuation lines for multi-line objects
|
|
174
|
+
const fullParams = collectMultiLineParams(blockLines, i, rawParams);
|
|
175
|
+
const { parsed, error } = parseLooseJson(fullParams);
|
|
176
|
+
results.push({
|
|
177
|
+
file: filePath,
|
|
178
|
+
line: lineNum,
|
|
179
|
+
opName,
|
|
180
|
+
rawParams: fullParams,
|
|
181
|
+
parsedParams: parsed,
|
|
182
|
+
parseError: error,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
// Op without params — nothing to validate
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Collect multi-line params from code block lines.
|
|
192
|
+
* Handles the common pattern where params span multiple indented lines:
|
|
193
|
+
* params: {
|
|
194
|
+
* key: "value",
|
|
195
|
+
* nested: { ... }
|
|
196
|
+
* }
|
|
197
|
+
*/
|
|
198
|
+
function collectMultiLineParams(blockLines, opLineIdx, initial) {
|
|
199
|
+
// If the initial string already has balanced braces, return it
|
|
200
|
+
if (isBalanced(initial))
|
|
201
|
+
return initial;
|
|
202
|
+
// Start from the line after the op line (or after params: line)
|
|
203
|
+
let startIdx = opLineIdx + 1;
|
|
204
|
+
if (!blockLines[opLineIdx].includes('params:') && startIdx < blockLines.length) {
|
|
205
|
+
if (blockLines[startIdx].trim().startsWith('params:')) {
|
|
206
|
+
startIdx++;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
let result = initial;
|
|
210
|
+
for (let j = startIdx; j < blockLines.length; j++) {
|
|
211
|
+
const nextLine = blockLines[j].trim();
|
|
212
|
+
if (!nextLine)
|
|
213
|
+
continue;
|
|
214
|
+
// Stop if we hit another op: line
|
|
215
|
+
if (nextLine.match(/(?:YOUR_AGENT_\w+\s+)?op:\w+/))
|
|
216
|
+
break;
|
|
217
|
+
result += '\n' + nextLine;
|
|
218
|
+
if (isBalanced(result))
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
return result;
|
|
222
|
+
}
|
|
223
|
+
/** Check if braces/brackets are balanced in a string. */
|
|
224
|
+
function isBalanced(s) {
|
|
225
|
+
let depth = 0;
|
|
226
|
+
for (const ch of s) {
|
|
227
|
+
if (ch === '{' || ch === '[')
|
|
228
|
+
depth++;
|
|
229
|
+
if (ch === '}' || ch === ']')
|
|
230
|
+
depth--;
|
|
231
|
+
if (depth < 0)
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
return depth === 0;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Parse loose JS-like object notation into a JS object.
|
|
238
|
+
* Handles: unquoted keys, single quotes, trailing commas, [...] arrays,
|
|
239
|
+
* template strings like "<placeholder>".
|
|
240
|
+
*/
|
|
241
|
+
function parseLooseJson(raw) {
|
|
242
|
+
if (!raw.trim())
|
|
243
|
+
return { parsed: null };
|
|
244
|
+
try {
|
|
245
|
+
// Normalize to valid JSON-ish:
|
|
246
|
+
const normalized = raw
|
|
247
|
+
// Replace <placeholder> values with "placeholder"
|
|
248
|
+
.replace(/"<([^">]+)>"/g, '"$1"')
|
|
249
|
+
// Unquoted keys → quoted keys
|
|
250
|
+
.replace(/([{,]\s*)(\w+)\s*:/g, '$1"$2":')
|
|
251
|
+
// Single quotes → double quotes (simple cases)
|
|
252
|
+
.replace(/'/g, '"')
|
|
253
|
+
// Trailing commas before } or ]
|
|
254
|
+
.replace(/,\s*([}\]])/g, '$1')
|
|
255
|
+
// Spread syntax [...] → placeholder
|
|
256
|
+
.replace(/\.\.\./g, '')
|
|
257
|
+
// Handle array shorthand [item1, item2, ...]
|
|
258
|
+
.replace(/\["?<[^>]+>"?\]/g, '["placeholder"]');
|
|
259
|
+
// Try to parse
|
|
260
|
+
const result = JSON.parse(normalized);
|
|
261
|
+
return { parsed: result };
|
|
262
|
+
}
|
|
263
|
+
catch (e) {
|
|
264
|
+
// Second attempt: extract key-value pairs manually for simple flat objects
|
|
265
|
+
try {
|
|
266
|
+
const result = extractFlatParams(raw);
|
|
267
|
+
if (result && Object.keys(result).length > 0) {
|
|
268
|
+
return { parsed: result };
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
// fall through
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
parsed: null,
|
|
276
|
+
error: `Cannot parse params: ${e.message}`,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Extract flat key-value pairs from loose notation.
|
|
282
|
+
* Handles: `key: "value"`, `key: true`, `key: 123`
|
|
283
|
+
*/
|
|
284
|
+
function extractFlatParams(raw) {
|
|
285
|
+
const result = {};
|
|
286
|
+
// Match patterns like: key: "value" or key: value or key: [...] or key: {...}
|
|
287
|
+
const kvPattern = /(\w+)\s*:\s*(?:"([^"]*)"|\[([^\]]*)\]|(\{[^}]*\})|(\w+))/g;
|
|
288
|
+
let match;
|
|
289
|
+
let found = false;
|
|
290
|
+
while ((match = kvPattern.exec(raw)) !== null) {
|
|
291
|
+
found = true;
|
|
292
|
+
const key = match[1];
|
|
293
|
+
if (match[2] !== undefined) {
|
|
294
|
+
// Quoted string
|
|
295
|
+
result[key] = match[2].replace(/<[^>]+>/g, 'placeholder');
|
|
296
|
+
}
|
|
297
|
+
else if (match[3] !== undefined) {
|
|
298
|
+
// Array
|
|
299
|
+
result[key] = ['placeholder'];
|
|
300
|
+
}
|
|
301
|
+
else if (match[4] !== undefined) {
|
|
302
|
+
// Object — keep as generic object
|
|
303
|
+
result[key] = {};
|
|
304
|
+
}
|
|
305
|
+
else if (match[5] !== undefined) {
|
|
306
|
+
// Unquoted value
|
|
307
|
+
const val = match[5];
|
|
308
|
+
if (val === 'true')
|
|
309
|
+
result[key] = true;
|
|
310
|
+
else if (val === 'false')
|
|
311
|
+
result[key] = false;
|
|
312
|
+
else if (/^\d+$/.test(val))
|
|
313
|
+
result[key] = parseInt(val, 10);
|
|
314
|
+
else
|
|
315
|
+
result[key] = val;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return found ? result : null;
|
|
319
|
+
}
|
|
320
|
+
// ── Validation ──────────────────────────────────────────────────────────
|
|
321
|
+
/**
|
|
322
|
+
* Check if a value looks like a placeholder (e.g., "correct-tier", "type",
|
|
323
|
+
* "critical|warning|suggestion") rather than a concrete example value.
|
|
324
|
+
*/
|
|
325
|
+
function isPlaceholder(value) {
|
|
326
|
+
if (typeof value !== 'string')
|
|
327
|
+
return false;
|
|
328
|
+
// Pipe-separated enum hints like "critical|warning|suggestion"
|
|
329
|
+
if (value.includes('|'))
|
|
330
|
+
return true;
|
|
331
|
+
// Common placeholder patterns
|
|
332
|
+
if (/^<.*>$/.test(value))
|
|
333
|
+
return true;
|
|
334
|
+
// Generic placeholder words (including hyphenated like "correct-tier", "entry-id")
|
|
335
|
+
if (/^(placeholder|example|value|name|id|title|description|type|domain)$/i.test(value))
|
|
336
|
+
return true;
|
|
337
|
+
if (/^[\w]+-[\w]+$/.test(value) &&
|
|
338
|
+
/\b(correct|your|my|the|this|some|new|old|entry|item|current)\b/i.test(value))
|
|
339
|
+
return true;
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Filter Zod issues to exclude those caused by placeholder values.
|
|
344
|
+
* Keeps structural issues (missing required fields, wrong types) but
|
|
345
|
+
* skips enum mismatches on placeholder strings.
|
|
346
|
+
*/
|
|
347
|
+
function isPlaceholderIssue(issue, params) {
|
|
348
|
+
// "Invalid enum value" on a placeholder string
|
|
349
|
+
if (issue.code === 'invalid_enum_value') {
|
|
350
|
+
const received = issue.received ?? getNestedValue(params, issue.path);
|
|
351
|
+
if (isPlaceholder(received))
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
/** Traverse nested object by path segments. */
|
|
357
|
+
function getNestedValue(obj, path) {
|
|
358
|
+
let current = obj;
|
|
359
|
+
for (const key of path) {
|
|
360
|
+
if (current === null || current === undefined || typeof current !== 'object')
|
|
361
|
+
return undefined;
|
|
362
|
+
current = current[key];
|
|
363
|
+
}
|
|
364
|
+
return current;
|
|
365
|
+
}
|
|
366
|
+
function validateExamples(examples, registry) {
|
|
367
|
+
const errors = [];
|
|
368
|
+
for (const ex of examples) {
|
|
369
|
+
// Skip examples where params couldn't be parsed
|
|
370
|
+
if (ex.parseError) {
|
|
371
|
+
// Don't report parse errors — many SKILL.md examples use placeholder syntax
|
|
372
|
+
// that's intentionally not valid JSON (e.g., "<title>", "...")
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
if (!ex.parsedParams)
|
|
376
|
+
continue;
|
|
377
|
+
const schema = registry.get(ex.opName);
|
|
378
|
+
if (!schema) {
|
|
379
|
+
// Op not found in registry — may be from a facade that failed to load,
|
|
380
|
+
// or a typo in the SKILL.md. Report it.
|
|
381
|
+
errors.push({
|
|
382
|
+
file: ex.file,
|
|
383
|
+
line: ex.line,
|
|
384
|
+
opName: ex.opName,
|
|
385
|
+
message: `unknown op — not found in any facade schema registry`,
|
|
386
|
+
});
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
// Validate params against schema
|
|
390
|
+
const result = schema.safeParse(ex.parsedParams);
|
|
391
|
+
if (!result.success && result.error) {
|
|
392
|
+
for (const issue of result.error.issues) {
|
|
393
|
+
// Skip issues caused by placeholder values
|
|
394
|
+
if (isPlaceholderIssue(issue, ex.parsedParams)) {
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
const path = issue.path.join('.');
|
|
398
|
+
errors.push({
|
|
399
|
+
file: ex.file,
|
|
400
|
+
line: ex.line,
|
|
401
|
+
opName: ex.opName,
|
|
402
|
+
message: `${path ? path + ': ' : ''}${issue.message}`,
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return errors;
|
|
408
|
+
}
|
|
409
|
+
// ── SKILL.md discovery ──────────────────────────────────────────────────
|
|
410
|
+
function discoverSkillDocs(rootDir) {
|
|
411
|
+
const skillsDir = join(rootDir, 'packages', 'forge', 'src', 'skills');
|
|
412
|
+
const paths = [];
|
|
413
|
+
if (!existsSync(skillsDir))
|
|
414
|
+
return paths;
|
|
415
|
+
const entries = readdirSync(skillsDir, { withFileTypes: true });
|
|
416
|
+
for (const entry of entries) {
|
|
417
|
+
if (!entry.isDirectory())
|
|
418
|
+
continue;
|
|
419
|
+
const skillMd = join(skillsDir, entry.name, 'SKILL.md');
|
|
420
|
+
if (existsSync(skillMd)) {
|
|
421
|
+
paths.push(skillMd);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return paths;
|
|
425
|
+
}
|
|
426
|
+
// ── Main ────────────────────────────────────────────────────────────────
|
|
427
|
+
export function validateSkillDocs(rootDir) {
|
|
428
|
+
const registry = buildSchemaRegistry();
|
|
429
|
+
const skillFiles = discoverSkillDocs(rootDir);
|
|
430
|
+
let totalExamples = 0;
|
|
431
|
+
const allErrors = [];
|
|
432
|
+
for (const file of skillFiles) {
|
|
433
|
+
const examples = extractOpExamples(file);
|
|
434
|
+
totalExamples += examples.length;
|
|
435
|
+
const errors = validateExamples(examples, registry);
|
|
436
|
+
allErrors.push(...errors);
|
|
437
|
+
}
|
|
438
|
+
return {
|
|
439
|
+
errors: allErrors,
|
|
440
|
+
totalExamples,
|
|
441
|
+
totalFiles: skillFiles.length,
|
|
442
|
+
registrySize: registry.size,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
// ── CLI entry point ─────────────────────────────────────────────────────
|
|
446
|
+
function main() {
|
|
447
|
+
// Find project root — walk up from this file's location
|
|
448
|
+
const thisDir = new URL('.', import.meta.url).pathname;
|
|
449
|
+
const rootDir = resolve(thisDir, '..', '..', '..', '..');
|
|
450
|
+
console.log('Validating SKILL.md op-call examples against Zod schemas...\n');
|
|
451
|
+
const { errors, totalExamples, totalFiles, registrySize } = validateSkillDocs(rootDir);
|
|
452
|
+
console.log(` Schema registry: ${registrySize} ops`);
|
|
453
|
+
console.log(` Skill files: ${totalFiles}`);
|
|
454
|
+
console.log(` Op examples: ${totalExamples}`);
|
|
455
|
+
console.log('');
|
|
456
|
+
if (errors.length === 0) {
|
|
457
|
+
console.log('All examples validate against their schemas.');
|
|
458
|
+
process.exit(0);
|
|
459
|
+
}
|
|
460
|
+
console.log(`Found ${errors.length} validation error(s):\n`);
|
|
461
|
+
for (const err of errors) {
|
|
462
|
+
const relPath = relative(rootDir, err.file);
|
|
463
|
+
console.log(` ${relPath}:${err.line} — ${err.opName}: ${err.message}`);
|
|
464
|
+
}
|
|
465
|
+
console.log('');
|
|
466
|
+
process.exit(1);
|
|
467
|
+
}
|
|
468
|
+
// Run if invoked directly
|
|
469
|
+
const isMainModule = typeof process !== 'undefined' &&
|
|
470
|
+
process.argv[1] &&
|
|
471
|
+
(process.argv[1].endsWith('validate-skill-docs.ts') ||
|
|
472
|
+
process.argv[1].endsWith('validate-skill-docs.js'));
|
|
473
|
+
if (isMainModule) {
|
|
474
|
+
main();
|
|
475
|
+
}
|
|
476
|
+
//# sourceMappingURL=validate-skill-docs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-skill-docs.js","sourceRoot":"","sources":["../../src/skills/validate-skill-docs.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soleri/core",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.14.4",
|
|
4
4
|
"description": "Shared engine for Soleri agents — vault, brain, planner, LLM utilities, and facade infrastructure.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"access": "public"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
|
-
"build": "tsc",
|
|
48
|
+
"build": "tsc && rm -rf dist/knowledge-packs && cp -r ../../knowledge-packs dist/knowledge-packs",
|
|
49
49
|
"typecheck": "tsc --noEmit",
|
|
50
50
|
"test": "vitest run",
|
|
51
51
|
"test:watch": "vitest",
|
|
@@ -156,6 +156,55 @@ describe('deviation-detection', () => {
|
|
|
156
156
|
expect(plan.steps[1].allowedTools).toEqual(['tool_b']);
|
|
157
157
|
});
|
|
158
158
|
|
|
159
|
+
it('injects workflowPrompt and workflowName when override has prompt', () => {
|
|
160
|
+
const plan = makePlan([
|
|
161
|
+
{
|
|
162
|
+
id: 'step-1',
|
|
163
|
+
name: 'Step one',
|
|
164
|
+
tools: [],
|
|
165
|
+
parallel: false,
|
|
166
|
+
requires: [],
|
|
167
|
+
status: 'pending',
|
|
168
|
+
},
|
|
169
|
+
]);
|
|
170
|
+
|
|
171
|
+
const override: WorkflowOverride = {
|
|
172
|
+
name: 'feature-dev',
|
|
173
|
+
prompt: '# Feature Development\nFollow TDD approach.',
|
|
174
|
+
gates: [],
|
|
175
|
+
tools: [],
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
applyWorkflowOverride(plan, override);
|
|
179
|
+
|
|
180
|
+
expect(plan.workflowPrompt).toBe('# Feature Development\nFollow TDD approach.');
|
|
181
|
+
expect(plan.workflowName).toBe('feature-dev');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('does not set workflowPrompt when override has no prompt', () => {
|
|
185
|
+
const plan = makePlan([
|
|
186
|
+
{
|
|
187
|
+
id: 'step-1',
|
|
188
|
+
name: 'Step one',
|
|
189
|
+
tools: [],
|
|
190
|
+
parallel: false,
|
|
191
|
+
requires: [],
|
|
192
|
+
status: 'pending',
|
|
193
|
+
},
|
|
194
|
+
]);
|
|
195
|
+
|
|
196
|
+
const override: WorkflowOverride = {
|
|
197
|
+
name: 'test-workflow',
|
|
198
|
+
gates: [],
|
|
199
|
+
tools: [],
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
applyWorkflowOverride(plan, override);
|
|
203
|
+
|
|
204
|
+
expect(plan.workflowPrompt).toBeUndefined();
|
|
205
|
+
expect(plan.workflowName).toBeUndefined();
|
|
206
|
+
});
|
|
207
|
+
|
|
159
208
|
it('does not set allowedTools on steps that remain tool-less', () => {
|
|
160
209
|
const plan = makePlan([
|
|
161
210
|
{
|
|
@@ -130,22 +130,22 @@ describe('ClaudeCodeAdapter', () => {
|
|
|
130
130
|
|
|
131
131
|
it('should generate hookify file for pre-commit trigger', () => {
|
|
132
132
|
const rule = createRule({
|
|
133
|
-
id: 'no-
|
|
133
|
+
id: 'no-console-log',
|
|
134
134
|
trigger: 'pre-commit',
|
|
135
|
-
pattern: '
|
|
136
|
-
message: 'No
|
|
137
|
-
description: 'Blocks
|
|
135
|
+
pattern: 'console\\.log',
|
|
136
|
+
message: 'No console.log in commits',
|
|
137
|
+
description: 'Blocks console.log statements',
|
|
138
138
|
});
|
|
139
139
|
const result = adapter.translate(createConfig([rule]));
|
|
140
140
|
|
|
141
141
|
expect(result.files).toHaveLength(1);
|
|
142
|
-
expect(result.files[0].path).toBe('.claude/hookify.no-
|
|
142
|
+
expect(result.files[0].path).toBe('.claude/hookify.no-console-log.local.md');
|
|
143
143
|
|
|
144
144
|
const content = result.files[0].content;
|
|
145
|
-
expect(content).toContain('name: no-
|
|
146
|
-
expect(content).toContain('Blocks
|
|
147
|
-
expect(content).toContain('Pattern: `
|
|
148
|
-
expect(content).toContain('No
|
|
145
|
+
expect(content).toContain('name: no-console-log');
|
|
146
|
+
expect(content).toContain('Blocks console.log statements');
|
|
147
|
+
expect(content).toContain('Pattern: `console\\.log`');
|
|
148
|
+
expect(content).toContain('No console.log in commits');
|
|
149
149
|
});
|
|
150
150
|
|
|
151
151
|
it('should generate hookify file without pattern when none provided', () => {
|
|
@@ -163,10 +163,12 @@ async function main(): Promise<void> {
|
|
|
163
163
|
.join(', ')})`,
|
|
164
164
|
);
|
|
165
165
|
|
|
166
|
-
// 6b. Auto-sync skills to
|
|
166
|
+
// 6b. Auto-sync skills to project-local .claude/skills/
|
|
167
167
|
const skillsDir = join(agentDir, 'skills');
|
|
168
168
|
if (existsSync(skillsDir)) {
|
|
169
|
-
const syncResult = syncSkillsToClaudeCode([skillsDir], config.name as string
|
|
169
|
+
const syncResult = syncSkillsToClaudeCode([skillsDir], config.name as string, {
|
|
170
|
+
projectRoot: process.cwd(),
|
|
171
|
+
});
|
|
170
172
|
const total = syncResult.installed.length + syncResult.updated.length;
|
|
171
173
|
if (total > 0) {
|
|
172
174
|
console.error(
|
|
@@ -176,6 +178,9 @@ async function main(): Promise<void> {
|
|
|
176
178
|
if (syncResult.removed.length) {
|
|
177
179
|
console.error(`${tag} Removed ${syncResult.removed.length} orphaned skill(s)`);
|
|
178
180
|
}
|
|
181
|
+
if (syncResult.cleanedGlobal.length) {
|
|
182
|
+
console.error(`${tag} Cleaned ${syncResult.cleanedGlobal.length} stale global skill(s)`);
|
|
183
|
+
}
|
|
179
184
|
}
|
|
180
185
|
|
|
181
186
|
// 7. Load domain packs
|
package/src/flows/types.ts
CHANGED
|
@@ -194,6 +194,10 @@ export interface OrchestrationPlan {
|
|
|
194
194
|
estimatedTools: number;
|
|
195
195
|
context: OrchestrationContext;
|
|
196
196
|
deviations?: ToolDeviation[];
|
|
197
|
+
/** Workflow prompt.md content injected by applyWorkflowOverride */
|
|
198
|
+
workflowPrompt?: string;
|
|
199
|
+
/** Name of the matched workflow */
|
|
200
|
+
workflowName?: string;
|
|
197
201
|
}
|
|
198
202
|
|
|
199
203
|
export interface OrchestrationContext {
|