@soleri/core 2.11.0 → 7.0.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/data/flows/build.flow.yaml +128 -0
- package/data/flows/deliver.flow.yaml +110 -0
- package/data/flows/design.flow.yaml +108 -0
- package/data/flows/enhance.flow.yaml +90 -0
- package/data/flows/explore.flow.yaml +84 -0
- package/data/flows/fix.flow.yaml +90 -0
- package/data/flows/plan.flow.yaml +87 -0
- package/data/flows/review.flow.yaml +90 -0
- package/dist/brain/brain.d.ts.map +1 -1
- package/dist/brain/brain.js +10 -0
- package/dist/brain/brain.js.map +1 -1
- package/dist/brain/intelligence.d.ts.map +1 -1
- package/dist/brain/intelligence.js +16 -2
- package/dist/brain/intelligence.js.map +1 -1
- package/dist/capabilities/chain-mapping.d.ts +21 -0
- package/dist/capabilities/chain-mapping.d.ts.map +1 -0
- package/dist/capabilities/chain-mapping.js +86 -0
- package/dist/capabilities/chain-mapping.js.map +1 -0
- package/dist/capabilities/index.d.ts +10 -0
- package/dist/capabilities/index.d.ts.map +1 -0
- package/dist/capabilities/index.js +8 -0
- package/dist/capabilities/index.js.map +1 -0
- package/dist/capabilities/registry.d.ts +95 -0
- package/dist/capabilities/registry.d.ts.map +1 -0
- package/dist/capabilities/registry.js +227 -0
- package/dist/capabilities/registry.js.map +1 -0
- package/dist/capabilities/types.d.ts +106 -0
- package/dist/capabilities/types.d.ts.map +1 -0
- package/dist/capabilities/types.js +12 -0
- package/dist/capabilities/types.js.map +1 -0
- package/dist/control/intent-router.d.ts.map +1 -1
- package/dist/control/intent-router.js +58 -2
- package/dist/control/intent-router.js.map +1 -1
- package/dist/domain-packs/index.d.ts +8 -0
- package/dist/domain-packs/index.d.ts.map +1 -0
- package/dist/domain-packs/index.js +8 -0
- package/dist/domain-packs/index.js.map +1 -0
- package/dist/domain-packs/inject-rules.d.ts +24 -0
- package/dist/domain-packs/inject-rules.d.ts.map +1 -0
- package/dist/domain-packs/inject-rules.js +65 -0
- package/dist/domain-packs/inject-rules.js.map +1 -0
- package/dist/domain-packs/knowledge-installer.d.ts +27 -0
- package/dist/domain-packs/knowledge-installer.d.ts.map +1 -0
- package/dist/domain-packs/knowledge-installer.js +89 -0
- package/dist/domain-packs/knowledge-installer.js.map +1 -0
- package/dist/domain-packs/loader.d.ts +28 -0
- package/dist/domain-packs/loader.d.ts.map +1 -0
- package/dist/domain-packs/loader.js +105 -0
- package/dist/domain-packs/loader.js.map +1 -0
- package/dist/domain-packs/pack-runtime.d.ts +80 -0
- package/dist/domain-packs/pack-runtime.d.ts.map +1 -0
- package/dist/domain-packs/pack-runtime.js +36 -0
- package/dist/domain-packs/pack-runtime.js.map +1 -0
- package/dist/domain-packs/skills-installer.d.ts +21 -0
- package/dist/domain-packs/skills-installer.d.ts.map +1 -0
- package/dist/domain-packs/skills-installer.js +38 -0
- package/dist/domain-packs/skills-installer.js.map +1 -0
- package/dist/domain-packs/token-resolver.d.ts +37 -0
- package/dist/domain-packs/token-resolver.d.ts.map +1 -0
- package/dist/domain-packs/token-resolver.js +109 -0
- package/dist/domain-packs/token-resolver.js.map +1 -0
- package/dist/domain-packs/types.d.ts +91 -0
- package/dist/domain-packs/types.d.ts.map +1 -0
- package/dist/domain-packs/types.js +122 -0
- package/dist/domain-packs/types.js.map +1 -0
- package/dist/engine/bin/soleri-engine.d.ts +12 -0
- package/dist/engine/bin/soleri-engine.d.ts.map +1 -0
- package/dist/engine/bin/soleri-engine.js +183 -0
- package/dist/engine/bin/soleri-engine.js.map +1 -0
- package/dist/engine/core-ops.d.ts +27 -0
- package/dist/engine/core-ops.d.ts.map +1 -0
- package/dist/engine/core-ops.js +159 -0
- package/dist/engine/core-ops.js.map +1 -0
- package/dist/engine/index.d.ts +19 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +17 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/register-engine.d.ts +54 -0
- package/dist/engine/register-engine.d.ts.map +1 -0
- package/dist/engine/register-engine.js +270 -0
- package/dist/engine/register-engine.js.map +1 -0
- package/dist/engine/test-helpers.d.ts +30 -0
- package/dist/engine/test-helpers.d.ts.map +1 -0
- package/dist/engine/test-helpers.js +59 -0
- package/dist/engine/test-helpers.js.map +1 -0
- package/dist/flows/context-router.d.ts +39 -0
- package/dist/flows/context-router.d.ts.map +1 -0
- package/dist/flows/context-router.js +206 -0
- package/dist/flows/context-router.js.map +1 -0
- package/dist/flows/dispatch-registry.d.ts +24 -0
- package/dist/flows/dispatch-registry.d.ts.map +1 -0
- package/dist/flows/dispatch-registry.js +70 -0
- package/dist/flows/dispatch-registry.js.map +1 -0
- package/dist/flows/epilogue.d.ts +24 -0
- package/dist/flows/epilogue.d.ts.map +1 -0
- package/dist/flows/epilogue.js +52 -0
- package/dist/flows/epilogue.js.map +1 -0
- package/dist/flows/executor.d.ts +25 -0
- package/dist/flows/executor.d.ts.map +1 -0
- package/dist/flows/executor.js +153 -0
- package/dist/flows/executor.js.map +1 -0
- package/dist/flows/gate-evaluator.d.ts +26 -0
- package/dist/flows/gate-evaluator.d.ts.map +1 -0
- package/dist/flows/gate-evaluator.js +162 -0
- package/dist/flows/gate-evaluator.js.map +1 -0
- package/dist/flows/index.d.ts +14 -0
- package/dist/flows/index.d.ts.map +1 -0
- package/dist/flows/index.js +20 -0
- package/dist/flows/index.js.map +1 -0
- package/dist/flows/loader.d.ts +17 -0
- package/dist/flows/loader.d.ts.map +1 -0
- package/dist/flows/loader.js +61 -0
- package/dist/flows/loader.js.map +1 -0
- package/dist/flows/plan-builder.d.ts +40 -0
- package/dist/flows/plan-builder.d.ts.map +1 -0
- package/dist/flows/plan-builder.js +213 -0
- package/dist/flows/plan-builder.js.map +1 -0
- package/dist/flows/probes.d.ts +11 -0
- package/dist/flows/probes.d.ts.map +1 -0
- package/dist/flows/probes.js +62 -0
- package/dist/flows/probes.js.map +1 -0
- package/dist/flows/types.d.ts +950 -0
- package/dist/flows/types.d.ts.map +1 -0
- package/dist/flows/types.js +105 -0
- package/dist/flows/types.js.map +1 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/intelligence/loader.d.ts +19 -0
- package/dist/intelligence/loader.d.ts.map +1 -1
- package/dist/intelligence/loader.js +86 -5
- package/dist/intelligence/loader.js.map +1 -1
- package/dist/intelligence/types.d.ts +1 -0
- package/dist/intelligence/types.d.ts.map +1 -1
- package/dist/packs/types.d.ts +58 -19
- package/dist/packs/types.d.ts.map +1 -1
- package/dist/packs/types.js +14 -0
- package/dist/packs/types.js.map +1 -1
- package/dist/playbooks/generic/onboarding.d.ts +9 -0
- package/dist/playbooks/generic/onboarding.d.ts.map +1 -0
- package/dist/playbooks/generic/onboarding.js +74 -0
- package/dist/playbooks/generic/onboarding.js.map +1 -0
- package/dist/playbooks/playbook-registry.d.ts.map +1 -1
- package/dist/playbooks/playbook-registry.js +2 -0
- package/dist/playbooks/playbook-registry.js.map +1 -1
- package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
- package/dist/runtime/admin-extra-ops.js +15 -9
- package/dist/runtime/admin-extra-ops.js.map +1 -1
- package/dist/runtime/admin-ops.js +4 -4
- package/dist/runtime/admin-ops.js.map +1 -1
- package/dist/runtime/capture-ops.d.ts.map +1 -1
- package/dist/runtime/capture-ops.js +33 -1
- package/dist/runtime/capture-ops.js.map +1 -1
- package/dist/runtime/domain-ops.d.ts +21 -5
- package/dist/runtime/domain-ops.d.ts.map +1 -1
- package/dist/runtime/domain-ops.js +85 -8
- package/dist/runtime/domain-ops.js.map +1 -1
- package/dist/runtime/facades/cognee-facade.d.ts.map +1 -1
- package/dist/runtime/facades/cognee-facade.js +3 -1
- package/dist/runtime/facades/cognee-facade.js.map +1 -1
- package/dist/runtime/facades/index.d.ts.map +1 -1
- package/dist/runtime/facades/index.js +10 -6
- package/dist/runtime/facades/index.js.map +1 -1
- package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
- package/dist/runtime/facades/vault-facade.js +2 -0
- package/dist/runtime/facades/vault-facade.js.map +1 -1
- package/dist/runtime/orchestrate-ops.d.ts +8 -7
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
- package/dist/runtime/orchestrate-ops.js +227 -58
- package/dist/runtime/orchestrate-ops.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +23 -17
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +6 -2
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/vault-linking-ops.d.ts +13 -0
- package/dist/runtime/vault-linking-ops.d.ts.map +1 -0
- package/dist/runtime/vault-linking-ops.js +367 -0
- package/dist/runtime/vault-linking-ops.js.map +1 -0
- package/dist/vault/linking.d.ts +46 -0
- package/dist/vault/linking.d.ts.map +1 -0
- package/dist/vault/linking.js +275 -0
- package/dist/vault/linking.js.map +1 -0
- package/dist/vault/vault-types.d.ts +37 -0
- package/dist/vault/vault-types.d.ts.map +1 -1
- package/dist/vault/vault.d.ts +12 -0
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +85 -6
- package/dist/vault/vault.js.map +1 -1
- package/package.json +4 -1
- package/src/__tests__/admin-extra-ops.test.ts +1 -1
- package/src/__tests__/admin-ops.test.ts +2 -1
- package/src/__tests__/cognee-client-gaps.test.ts +470 -0
- package/src/__tests__/cognee-hybrid-search.test.ts +478 -0
- package/src/__tests__/cognee-sync-manager-deep.test.ts +630 -0
- package/src/__tests__/cognee-sync-manager.test.ts +1 -0
- package/src/__tests__/core-ops.test.ts +9 -61
- package/src/__tests__/domain-packs.test.ts +421 -0
- package/src/__tests__/flows.test.ts +604 -0
- package/src/__tests__/playbook-registry.test.ts +2 -2
- package/src/__tests__/playbook-seeder.test.ts +8 -8
- package/src/__tests__/playbook.test.ts +5 -5
- package/src/__tests__/token-resolver.test.ts +79 -0
- package/src/brain/brain.ts +12 -0
- package/src/brain/intelligence.ts +21 -2
- package/src/capabilities/chain-mapping.ts +93 -0
- package/src/capabilities/index.ts +21 -0
- package/src/capabilities/registry.ts +290 -0
- package/src/capabilities/types.ts +143 -0
- package/src/control/intent-router.ts +46 -2
- package/src/domain-packs/index.ts +27 -0
- package/src/domain-packs/inject-rules.ts +74 -0
- package/src/domain-packs/knowledge-installer.ts +116 -0
- package/src/domain-packs/loader.ts +124 -0
- package/src/domain-packs/pack-runtime.ts +99 -0
- package/src/domain-packs/skills-installer.ts +56 -0
- package/src/domain-packs/token-resolver.ts +126 -0
- package/src/domain-packs/types.ts +229 -0
- package/src/engine/__tests__/register-engine.test.ts +104 -0
- package/src/engine/bin/soleri-engine.ts +217 -0
- package/src/engine/core-ops.ts +178 -0
- package/src/engine/index.ts +19 -0
- package/src/engine/register-engine.ts +385 -0
- package/src/engine/test-helpers.ts +83 -0
- package/src/flows/context-router.ts +257 -0
- package/src/flows/dispatch-registry.ts +80 -0
- package/src/flows/epilogue.ts +65 -0
- package/src/flows/executor.ts +182 -0
- package/src/flows/gate-evaluator.ts +171 -0
- package/src/flows/index.ts +52 -0
- package/src/flows/loader.ts +63 -0
- package/src/flows/plan-builder.ts +250 -0
- package/src/flows/probes.ts +70 -0
- package/src/flows/types.ts +217 -0
- package/src/index.ts +68 -1
- package/src/intelligence/loader.ts +96 -5
- package/src/intelligence/types.ts +1 -0
- package/src/packs/types.ts +19 -0
- package/src/playbooks/generic/onboarding.ts +79 -0
- package/src/playbooks/playbook-registry.ts +2 -0
- package/src/runtime/admin-extra-ops.ts +14 -8
- package/src/runtime/admin-ops.ts +4 -4
- package/src/runtime/capture-ops.ts +40 -1
- package/src/runtime/domain-ops.ts +92 -7
- package/src/runtime/facades/cognee-facade.ts +3 -1
- package/src/runtime/facades/index.ts +12 -6
- package/src/runtime/facades/vault-facade.ts +2 -0
- package/src/runtime/orchestrate-ops.ts +271 -62
- package/src/runtime/runtime.ts +27 -18
- package/src/runtime/types.ts +6 -2
- package/src/runtime/vault-linking-ops.ts +454 -0
- package/src/vault/linking.ts +333 -0
- package/src/vault/vault-types.ts +46 -0
- package/src/vault/vault.ts +94 -7
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills installer for domain packs.
|
|
3
|
+
*
|
|
4
|
+
* Copies skill .md files from the pack to the agent's skills directory.
|
|
5
|
+
* Does not overwrite existing skills unless force flag is set.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { existsSync, copyFileSync, mkdirSync } from 'node:fs';
|
|
9
|
+
import { join, resolve } from 'node:path';
|
|
10
|
+
import type { DomainPack } from './types.js';
|
|
11
|
+
|
|
12
|
+
export interface SkillsInstallResult {
|
|
13
|
+
installed: number;
|
|
14
|
+
skipped: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Install skills from a domain pack.
|
|
19
|
+
*
|
|
20
|
+
* @param pack - The domain pack with skills
|
|
21
|
+
* @param targetDir - Agent's skills directory
|
|
22
|
+
* @param rootDir - Absolute path to the pack's root directory
|
|
23
|
+
* @param force - Overwrite existing skills if true
|
|
24
|
+
*/
|
|
25
|
+
export function installSkills(
|
|
26
|
+
pack: DomainPack,
|
|
27
|
+
targetDir: string,
|
|
28
|
+
rootDir: string,
|
|
29
|
+
force = false,
|
|
30
|
+
): SkillsInstallResult {
|
|
31
|
+
const result: SkillsInstallResult = { installed: 0, skipped: 0 };
|
|
32
|
+
|
|
33
|
+
if (!pack.skills || pack.skills.length === 0) return result;
|
|
34
|
+
|
|
35
|
+
mkdirSync(targetDir, { recursive: true });
|
|
36
|
+
|
|
37
|
+
for (const skill of pack.skills) {
|
|
38
|
+
const sourcePath = resolve(rootDir, skill.path);
|
|
39
|
+
const targetPath = join(targetDir, `${skill.name}.md`);
|
|
40
|
+
|
|
41
|
+
if (!existsSync(sourcePath)) {
|
|
42
|
+
result.skipped++;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (existsSync(targetPath) && !force) {
|
|
47
|
+
result.skipped++;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
copyFileSync(sourcePath, targetPath);
|
|
52
|
+
result.installed++;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TokenResolver — resolves design token names to hex values.
|
|
3
|
+
*
|
|
4
|
+
* Ported from Salvador MCP src/registry/token-resolver.ts.
|
|
5
|
+
* Supports: #HEX passthrough, SCALE[SHADE] (e.g., PRIMARY[500]),
|
|
6
|
+
* Tailwind classes (bg-primary-500), semantic tokens (text-inverse),
|
|
7
|
+
* and named colors (white, black).
|
|
8
|
+
*
|
|
9
|
+
* Stateless — create per-invocation with a ProjectContext.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { PackProjectContext } from './pack-runtime.js';
|
|
13
|
+
|
|
14
|
+
const NAMED_COLORS: Record<string, string> = {
|
|
15
|
+
white: '#FFFFFF',
|
|
16
|
+
black: '#000000',
|
|
17
|
+
transparent: '#00000000',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Resolve a token or color reference to a hex value.
|
|
22
|
+
*
|
|
23
|
+
* @param tokenOrHex - Token name, hex value, or color reference
|
|
24
|
+
* @param project - Project context with color scales and semantic tokens
|
|
25
|
+
* @returns Uppercase hex string (e.g., "#DC0000")
|
|
26
|
+
* @throws If the token cannot be resolved
|
|
27
|
+
*/
|
|
28
|
+
export function resolveToken(tokenOrHex: string, project: PackProjectContext): string {
|
|
29
|
+
// Passthrough hex values
|
|
30
|
+
if (tokenOrHex.startsWith('#')) {
|
|
31
|
+
return tokenOrHex.toUpperCase();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Named colors
|
|
35
|
+
const named = NAMED_COLORS[tokenOrHex.toLowerCase()];
|
|
36
|
+
if (named) return named;
|
|
37
|
+
|
|
38
|
+
// Semantic tokens (e.g., "text-inverse", "bg-surface")
|
|
39
|
+
if (project.semanticTokens) {
|
|
40
|
+
const semantic = project.semanticTokens[tokenOrHex];
|
|
41
|
+
if (semantic) return semantic.toUpperCase();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// SCALE[SHADE] format (e.g., "PRIMARY[500]", "neutral[900]")
|
|
45
|
+
const scaleMatch = tokenOrHex.match(/^(\w+)\[(\d+)\]$/);
|
|
46
|
+
if (scaleMatch) {
|
|
47
|
+
const [, scaleName, shade] = scaleMatch;
|
|
48
|
+
return resolveScale(scaleName.toLowerCase(), shade, project);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Tailwind-style: bg-primary-500, text-neutral-700
|
|
52
|
+
const tailwindMatch = tokenOrHex.match(/^(?:bg|text|border|ring|fill|stroke)-(\w+)-(\d+)$/);
|
|
53
|
+
if (tailwindMatch) {
|
|
54
|
+
const [, scaleName, shade] = tailwindMatch;
|
|
55
|
+
return resolveScale(scaleName, shade, project);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
throw new Error(`Cannot resolve token: "${tokenOrHex}"`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function resolveScale(scaleName: string, shade: string, project: PackProjectContext): string {
|
|
62
|
+
if (!project.colors) {
|
|
63
|
+
throw new Error(`Project "${project.name}" has no color scales`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const scale = project.colors[scaleName];
|
|
67
|
+
if (!scale) {
|
|
68
|
+
const available = Object.keys(project.colors).join(', ');
|
|
69
|
+
throw new Error(`Unknown color scale "${scaleName}". Available: ${available}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const hex = scale.scale[shade];
|
|
73
|
+
if (!hex) {
|
|
74
|
+
const available = Object.keys(scale.scale).join(', ');
|
|
75
|
+
throw new Error(`Unknown shade "${shade}" in scale "${scaleName}". Available: ${available}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return hex.toUpperCase();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* List all tokens available in a project.
|
|
83
|
+
*
|
|
84
|
+
* @param project - Project context
|
|
85
|
+
* @returns Array of { token, hex, scale } for all scale + semantic tokens
|
|
86
|
+
*/
|
|
87
|
+
export function listProjectTokens(
|
|
88
|
+
project: PackProjectContext,
|
|
89
|
+
): Array<{ token: string; hex: string; scale: string }> {
|
|
90
|
+
const tokens: Array<{ token: string; hex: string; scale: string }> = [];
|
|
91
|
+
|
|
92
|
+
// Scale tokens
|
|
93
|
+
if (project.colors) {
|
|
94
|
+
for (const [scaleName, scaleData] of Object.entries(project.colors)) {
|
|
95
|
+
for (const [shade, hex] of Object.entries(scaleData.scale)) {
|
|
96
|
+
tokens.push({
|
|
97
|
+
token: `${scaleName}-${shade}`,
|
|
98
|
+
hex: hex.toUpperCase(),
|
|
99
|
+
scale: scaleName,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Semantic tokens
|
|
106
|
+
if (project.semanticTokens) {
|
|
107
|
+
for (const [name, hex] of Object.entries(project.semanticTokens)) {
|
|
108
|
+
tokens.push({ token: name, hex: hex.toUpperCase(), scale: 'semantic' });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return tokens;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Build a reverse index: hex → token name.
|
|
117
|
+
* Useful for detecting hardcoded colors.
|
|
118
|
+
*/
|
|
119
|
+
export function buildReverseIndex(project: PackProjectContext): Map<string, string> {
|
|
120
|
+
const index = new Map<string, string>();
|
|
121
|
+
const tokens = listProjectTokens(project);
|
|
122
|
+
for (const t of tokens) {
|
|
123
|
+
index.set(t.hex.toUpperCase(), t.token);
|
|
124
|
+
}
|
|
125
|
+
return index;
|
|
126
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain Pack types — the contract for plug-and-play domain intelligence.
|
|
3
|
+
*
|
|
4
|
+
* A DomainPack is an npm package that bundles:
|
|
5
|
+
* - Custom ops with real algorithmic logic (e.g., WCAG contrast checking)
|
|
6
|
+
* - Optional standalone facades (one pack can register multiple MCP tools)
|
|
7
|
+
* - Tiered knowledge (canonical/curated/captured)
|
|
8
|
+
* - CLAUDE.md behavioral rules
|
|
9
|
+
* - Skills
|
|
10
|
+
*
|
|
11
|
+
* One pack = one npm package, can register multiple facades.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import type { OpDefinition, FacadeConfig } from '../facades/types.js';
|
|
16
|
+
import type { AgentRuntime } from '../runtime/types.js';
|
|
17
|
+
import type { PackRuntime } from './pack-runtime.js';
|
|
18
|
+
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Reserved names — packs cannot claim these as facade names
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
export const SEMANTIC_FACADE_NAMES: ReadonlyArray<string> = [
|
|
24
|
+
'vault',
|
|
25
|
+
'plan',
|
|
26
|
+
'brain',
|
|
27
|
+
'memory',
|
|
28
|
+
'admin',
|
|
29
|
+
'curator',
|
|
30
|
+
'loop',
|
|
31
|
+
'orchestrate',
|
|
32
|
+
'control',
|
|
33
|
+
'cognee',
|
|
34
|
+
'governance',
|
|
35
|
+
'context',
|
|
36
|
+
'agency',
|
|
37
|
+
'chat',
|
|
38
|
+
'playbook',
|
|
39
|
+
] as const;
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Knowledge Manifest — tiered knowledge with different lifecycle rules
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
/** Three-tier knowledge structure. Each tier has different lifecycle rules. */
|
|
46
|
+
export interface KnowledgeManifest {
|
|
47
|
+
/** Immutable rules and axioms. Never overwritten by curator. Highest search authority. */
|
|
48
|
+
canonical?: string;
|
|
49
|
+
/** Patterns and anti-patterns. Curator can groom, deduplicate, enrich. */
|
|
50
|
+
curated?: string;
|
|
51
|
+
/** Seed learnings. Rarely shipped — normally emerges from agent usage. */
|
|
52
|
+
captured?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Skill Definition (for pack-bundled skills)
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
export interface PackSkillDefinition {
|
|
60
|
+
/** Skill file name (without .md extension) */
|
|
61
|
+
name: string;
|
|
62
|
+
/** Path to the .md skill file relative to the pack */
|
|
63
|
+
path: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// DomainPack — the main interface
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
/** The contract every domain pack must implement. */
|
|
71
|
+
export interface DomainPack {
|
|
72
|
+
/** Unique pack name (e.g., 'design', 'security-intelligence') */
|
|
73
|
+
name: string;
|
|
74
|
+
/** Semver version */
|
|
75
|
+
version: string;
|
|
76
|
+
/** Domains this pack claims. Ops inject into these domain facades. */
|
|
77
|
+
domains: string[];
|
|
78
|
+
/** Custom operations with real logic — injected into claimed domain facades. */
|
|
79
|
+
ops: OpDefinition[];
|
|
80
|
+
/** Additional standalone facades (one pack can register multiple MCP tools). */
|
|
81
|
+
facades?: FacadeConfig[];
|
|
82
|
+
/** Tiered knowledge to install into the agent's vault. */
|
|
83
|
+
knowledge?: KnowledgeManifest;
|
|
84
|
+
/** CLAUDE.md behavioral rules fragment (markdown). */
|
|
85
|
+
rules?: string;
|
|
86
|
+
/** Skills to install into the agent's skills directory. */
|
|
87
|
+
skills?: PackSkillDefinition[];
|
|
88
|
+
/** Capability handler factory — returns handlers for declared capabilities */
|
|
89
|
+
capabilities?: (
|
|
90
|
+
runtime: PackRuntime,
|
|
91
|
+
) => Map<string, import('../capabilities/types.js').CapabilityHandler>;
|
|
92
|
+
/** Other packs this pack depends on (by name). */
|
|
93
|
+
requires?: string[];
|
|
94
|
+
/** Called after pack is installed (one-time setup). */
|
|
95
|
+
onInstall?: (runtime: AgentRuntime) => Promise<void>;
|
|
96
|
+
/** Called each time the agent starts (runtime initialization). */
|
|
97
|
+
onActivate?: (runtime: AgentRuntime) => Promise<void>;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// DomainPackRef — lightweight reference for AgentConfig
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
|
|
104
|
+
/** Reference to a domain pack in agent configuration. */
|
|
105
|
+
export interface DomainPackRef {
|
|
106
|
+
/** Display name */
|
|
107
|
+
name: string;
|
|
108
|
+
/** npm package name (e.g., '@soleri/domain-design') */
|
|
109
|
+
package: string;
|
|
110
|
+
/** Optional version constraint */
|
|
111
|
+
version?: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// DomainPackManifest — validated and resolved pack
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
/** A DomainPack that has been validated and resolved. */
|
|
119
|
+
export interface DomainPackManifest extends DomainPack {
|
|
120
|
+
/** Resolved from npm package name */
|
|
121
|
+
packageName: string;
|
|
122
|
+
/** Absolute path to the pack's root directory */
|
|
123
|
+
rootDir?: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// Validation
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
|
|
130
|
+
const knowledgeManifestSchema = z.object({
|
|
131
|
+
canonical: z.string().optional(),
|
|
132
|
+
curated: z.string().optional(),
|
|
133
|
+
captured: z.string().optional(),
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const packSkillSchema = z.object({
|
|
137
|
+
name: z.string(),
|
|
138
|
+
path: z.string(),
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
/** Zod schema for validating DomainPack structure (data fields only). */
|
|
142
|
+
const domainPackSchema = z.object({
|
|
143
|
+
name: z.string().min(1),
|
|
144
|
+
version: z.string().min(1),
|
|
145
|
+
domains: z.array(z.string().min(1)).min(1),
|
|
146
|
+
ops: z.array(
|
|
147
|
+
z.object({
|
|
148
|
+
name: z.string().min(1),
|
|
149
|
+
description: z.string(),
|
|
150
|
+
auth: z.enum(['read', 'write', 'admin']),
|
|
151
|
+
handler: z.function(),
|
|
152
|
+
schema: z.any().optional(),
|
|
153
|
+
hot: z.boolean().optional(),
|
|
154
|
+
}),
|
|
155
|
+
),
|
|
156
|
+
facades: z
|
|
157
|
+
.array(
|
|
158
|
+
z.object({
|
|
159
|
+
name: z.string().min(1),
|
|
160
|
+
description: z.string(),
|
|
161
|
+
ops: z.array(z.any()),
|
|
162
|
+
}),
|
|
163
|
+
)
|
|
164
|
+
.optional(),
|
|
165
|
+
knowledge: knowledgeManifestSchema.optional(),
|
|
166
|
+
rules: z.string().optional(),
|
|
167
|
+
skills: z.array(packSkillSchema).optional(),
|
|
168
|
+
requires: z.array(z.string()).optional(),
|
|
169
|
+
onInstall: z.function().optional(),
|
|
170
|
+
onActivate: z.function().optional(),
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
export type ValidateResult =
|
|
174
|
+
| { success: true; data: DomainPack }
|
|
175
|
+
| { success: false; errors: z.ZodError };
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Validate an unknown value as a DomainPack.
|
|
179
|
+
*
|
|
180
|
+
* Beyond Zod shape validation, also checks:
|
|
181
|
+
* - Op names are unique within the pack
|
|
182
|
+
* - Facade names don't collide with semantic facades
|
|
183
|
+
*/
|
|
184
|
+
export function validateDomainPack(value: unknown): ValidateResult {
|
|
185
|
+
const parsed = domainPackSchema.safeParse(value);
|
|
186
|
+
if (!parsed.success) {
|
|
187
|
+
return { success: false, errors: parsed.error };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const pack = parsed.data as DomainPack;
|
|
191
|
+
|
|
192
|
+
// Check for duplicate op names
|
|
193
|
+
const opNames = new Set<string>();
|
|
194
|
+
for (const op of pack.ops) {
|
|
195
|
+
if (opNames.has(op.name)) {
|
|
196
|
+
return {
|
|
197
|
+
success: false,
|
|
198
|
+
errors: new z.ZodError([
|
|
199
|
+
{
|
|
200
|
+
code: 'custom',
|
|
201
|
+
path: ['ops'],
|
|
202
|
+
message: `Duplicate op name: "${op.name}"`,
|
|
203
|
+
},
|
|
204
|
+
]),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
opNames.add(op.name);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Check facade name collisions with semantic facades
|
|
211
|
+
if (pack.facades) {
|
|
212
|
+
for (const facade of pack.facades) {
|
|
213
|
+
if (SEMANTIC_FACADE_NAMES.includes(facade.name)) {
|
|
214
|
+
return {
|
|
215
|
+
success: false,
|
|
216
|
+
errors: new z.ZodError([
|
|
217
|
+
{
|
|
218
|
+
code: 'custom',
|
|
219
|
+
path: ['facades'],
|
|
220
|
+
message: `Facade name "${facade.name}" collides with semantic facade. Reserved names: ${SEMANTIC_FACADE_NAMES.join(', ')}`,
|
|
221
|
+
},
|
|
222
|
+
]),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return { success: true, data: pack };
|
|
229
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the direct engine registration (replaces facade factory).
|
|
3
|
+
*
|
|
4
|
+
* Validates that registerEngine() produces the same tools and behavior
|
|
5
|
+
* as the old createSemanticFacades() + registerAllFacades() pattern.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
9
|
+
import { createAgentRuntime } from '../../runtime/runtime.js';
|
|
10
|
+
import { captureOps, executeOp } from '../test-helpers.js';
|
|
11
|
+
import { createVaultFacadeOps } from '../../runtime/facades/vault-facade.js';
|
|
12
|
+
import { createBrainFacadeOps } from '../../runtime/facades/brain-facade.js';
|
|
13
|
+
import { createPlanFacadeOps } from '../../runtime/facades/plan-facade.js';
|
|
14
|
+
import { createCuratorFacadeOps } from '../../runtime/facades/curator-facade.js';
|
|
15
|
+
import { createLoopFacadeOps } from '../../runtime/facades/loop-facade.js';
|
|
16
|
+
import type { AgentRuntime } from '../../runtime/types.js';
|
|
17
|
+
|
|
18
|
+
let runtime: AgentRuntime;
|
|
19
|
+
|
|
20
|
+
beforeAll(() => {
|
|
21
|
+
runtime = createAgentRuntime({
|
|
22
|
+
agentId: 'test-engine',
|
|
23
|
+
vaultPath: ':memory:',
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
afterAll(() => {
|
|
28
|
+
runtime.close();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('Direct op execution (no facade factory)', () => {
|
|
32
|
+
it('vault ops work without facade dispatch', async () => {
|
|
33
|
+
const ops = captureOps(createVaultFacadeOps(runtime));
|
|
34
|
+
|
|
35
|
+
// Capture a pattern
|
|
36
|
+
const captureResult = await executeOp(ops, 'capture_enriched', {
|
|
37
|
+
projectPath: '.',
|
|
38
|
+
title: 'Test Pattern',
|
|
39
|
+
description: 'A test pattern for engine registration',
|
|
40
|
+
type: 'pattern',
|
|
41
|
+
category: 'testing',
|
|
42
|
+
severity: 'suggestion',
|
|
43
|
+
tags: ['test'],
|
|
44
|
+
});
|
|
45
|
+
expect(captureResult.success).toBe(true);
|
|
46
|
+
|
|
47
|
+
// Search for it
|
|
48
|
+
const searchResult = await executeOp(ops, 'search', {
|
|
49
|
+
query: 'test pattern engine',
|
|
50
|
+
});
|
|
51
|
+
expect(searchResult.success).toBe(true);
|
|
52
|
+
expect(searchResult.data).toBeDefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('brain ops work without facade dispatch', async () => {
|
|
56
|
+
const ops = captureOps(createBrainFacadeOps(runtime));
|
|
57
|
+
|
|
58
|
+
const statsResult = await executeOp(ops, 'brain_stats', {});
|
|
59
|
+
expect(statsResult.success).toBe(true);
|
|
60
|
+
expect(statsResult.data).toBeDefined();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('plan ops work without facade dispatch', async () => {
|
|
64
|
+
const ops = captureOps(createPlanFacadeOps(runtime));
|
|
65
|
+
|
|
66
|
+
const createResult = await executeOp(ops, 'create_plan', {
|
|
67
|
+
objective: 'Test objective',
|
|
68
|
+
scope: 'Test scope',
|
|
69
|
+
});
|
|
70
|
+
expect(createResult.success).toBe(true);
|
|
71
|
+
expect(createResult.data).toBeDefined();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('curator ops work without facade dispatch', async () => {
|
|
75
|
+
const ops = captureOps(createCuratorFacadeOps(runtime));
|
|
76
|
+
|
|
77
|
+
const statusResult = await executeOp(ops, 'curator_status', {});
|
|
78
|
+
expect(statusResult.success).toBe(true);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('loop ops work without facade dispatch', async () => {
|
|
82
|
+
const ops = captureOps(createLoopFacadeOps(runtime));
|
|
83
|
+
|
|
84
|
+
const statusResult = await executeOp(ops, 'loop_status', {});
|
|
85
|
+
expect(statusResult.success).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('returns error for unknown ops', async () => {
|
|
89
|
+
const ops = captureOps(createVaultFacadeOps(runtime));
|
|
90
|
+
|
|
91
|
+
const result = await executeOp(ops, 'nonexistent_op', {});
|
|
92
|
+
expect(result.success).toBe(false);
|
|
93
|
+
expect(result.error).toContain('Unknown operation');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('response envelope matches old format', async () => {
|
|
97
|
+
const ops = captureOps(createVaultFacadeOps(runtime));
|
|
98
|
+
|
|
99
|
+
const result = await executeOp(ops, 'vault_stats', {}, 'test_vault');
|
|
100
|
+
expect(result).toHaveProperty('success');
|
|
101
|
+
expect(result).toHaveProperty('op', 'vault_stats');
|
|
102
|
+
expect(result).toHaveProperty('facade', 'test_vault');
|
|
103
|
+
});
|
|
104
|
+
});
|