@soleri/core 2.12.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/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 +35 -0
- 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 +64 -6
- 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 +217 -61
- 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/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 +38 -0
- 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 +71 -5
- 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 +261 -65
- 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
|
@@ -189,7 +189,7 @@ describe('playbook_create op', () => {
|
|
|
189
189
|
vaultPath: ':memory:',
|
|
190
190
|
plansPath: join(plannerDir, 'plans.json'),
|
|
191
191
|
});
|
|
192
|
-
ops = createSemanticFacades(runtime, 'test').flatMap(f => f.ops);
|
|
192
|
+
ops = createSemanticFacades(runtime, 'test').flatMap((f) => f.ops);
|
|
193
193
|
});
|
|
194
194
|
|
|
195
195
|
afterEach(() => {
|
|
@@ -300,7 +300,7 @@ describe('playbook_match op', () => {
|
|
|
300
300
|
vaultPath: ':memory:',
|
|
301
301
|
plansPath: join(plannerDir, 'plans.json'),
|
|
302
302
|
});
|
|
303
|
-
ops = createSemanticFacades(runtime, 'test').flatMap(f => f.ops);
|
|
303
|
+
ops = createSemanticFacades(runtime, 'test').flatMap((f) => f.ops);
|
|
304
304
|
});
|
|
305
305
|
|
|
306
306
|
afterEach(() => {
|
|
@@ -356,7 +356,7 @@ describe('playbook_seed op', () => {
|
|
|
356
356
|
vaultPath: ':memory:',
|
|
357
357
|
plansPath: join(plannerDir, 'plans.json'),
|
|
358
358
|
});
|
|
359
|
-
ops = createSemanticFacades(runtime, 'test').flatMap(f => f.ops);
|
|
359
|
+
ops = createSemanticFacades(runtime, 'test').flatMap((f) => f.ops);
|
|
360
360
|
});
|
|
361
361
|
|
|
362
362
|
afterEach(() => {
|
|
@@ -371,7 +371,7 @@ describe('playbook_seed op', () => {
|
|
|
371
371
|
errors: number;
|
|
372
372
|
};
|
|
373
373
|
|
|
374
|
-
expect(result.seeded).toBe(
|
|
374
|
+
expect(result.seeded).toBe(7);
|
|
375
375
|
expect(result.skipped).toBe(0);
|
|
376
376
|
expect(result.errors).toBe(0);
|
|
377
377
|
});
|
|
@@ -384,6 +384,6 @@ describe('playbook_seed op', () => {
|
|
|
384
384
|
};
|
|
385
385
|
|
|
386
386
|
expect(result.seeded).toBe(0);
|
|
387
|
-
expect(result.skipped).toBe(
|
|
387
|
+
expect(result.skipped).toBe(7);
|
|
388
388
|
});
|
|
389
389
|
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
resolveToken,
|
|
4
|
+
listProjectTokens,
|
|
5
|
+
buildReverseIndex,
|
|
6
|
+
} from '../domain-packs/token-resolver.js';
|
|
7
|
+
import type { PackProjectContext } from '../domain-packs/pack-runtime.js';
|
|
8
|
+
|
|
9
|
+
const mockProject: PackProjectContext = {
|
|
10
|
+
id: 'test-project',
|
|
11
|
+
name: 'Test Project',
|
|
12
|
+
path: '/test',
|
|
13
|
+
colors: {
|
|
14
|
+
primary: {
|
|
15
|
+
base: '#3B82F6',
|
|
16
|
+
scale: { '50': '#EFF6FF', '100': '#DBEAFE', '500': '#3B82F6', '900': '#1E3A5F' },
|
|
17
|
+
},
|
|
18
|
+
neutral: {
|
|
19
|
+
base: '#6B7280',
|
|
20
|
+
scale: { '50': '#F9FAFB', '100': '#F3F4F6', '500': '#6B7280', '900': '#111827' },
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
semanticTokens: {
|
|
24
|
+
'text-inverse': '#FFFFFF',
|
|
25
|
+
'bg-surface': '#F9FAFB',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
describe('resolveToken', () => {
|
|
30
|
+
it('should pass through hex values', () => {
|
|
31
|
+
expect(resolveToken('#FF0000', mockProject)).toBe('#FF0000');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should resolve named colors', () => {
|
|
35
|
+
expect(resolveToken('white', mockProject)).toBe('#FFFFFF');
|
|
36
|
+
expect(resolveToken('black', mockProject)).toBe('#000000');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should resolve semantic tokens', () => {
|
|
40
|
+
expect(resolveToken('text-inverse', mockProject)).toBe('#FFFFFF');
|
|
41
|
+
expect(resolveToken('bg-surface', mockProject)).toBe('#F9FAFB');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should resolve SCALE[SHADE] format', () => {
|
|
45
|
+
expect(resolveToken('PRIMARY[500]', mockProject)).toBe('#3B82F6');
|
|
46
|
+
expect(resolveToken('neutral[900]', mockProject)).toBe('#111827');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should resolve Tailwind-style tokens', () => {
|
|
50
|
+
expect(resolveToken('bg-primary-500', mockProject)).toBe('#3B82F6');
|
|
51
|
+
expect(resolveToken('text-neutral-900', mockProject)).toBe('#111827');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should throw for unknown tokens', () => {
|
|
55
|
+
expect(() => resolveToken('unknown-token', mockProject)).toThrow('Cannot resolve');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should throw for unknown scales', () => {
|
|
59
|
+
expect(() => resolveToken('ACCENT[500]', mockProject)).toThrow('Unknown color scale');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('listProjectTokens', () => {
|
|
64
|
+
it('should list all scale and semantic tokens', () => {
|
|
65
|
+
const tokens = listProjectTokens(mockProject);
|
|
66
|
+
expect(tokens.length).toBeGreaterThan(0);
|
|
67
|
+
expect(tokens.some((t) => t.token === 'primary-500')).toBe(true);
|
|
68
|
+
expect(tokens.some((t) => t.token === 'text-inverse')).toBe(true);
|
|
69
|
+
expect(tokens.some((t) => t.scale === 'semantic')).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('buildReverseIndex', () => {
|
|
74
|
+
it('should map hex to token name', () => {
|
|
75
|
+
const index = buildReverseIndex(mockProject);
|
|
76
|
+
expect(index.get('#3B82F6')).toBe('primary-500');
|
|
77
|
+
expect(index.get('#FFFFFF')).toBe('text-inverse');
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -497,12 +497,31 @@ export class BrainIntelligence {
|
|
|
497
497
|
limit?: number;
|
|
498
498
|
}): PatternStrength[] {
|
|
499
499
|
const limit = context.limit ?? 5;
|
|
500
|
-
|
|
500
|
+
|
|
501
|
+
// Try domain-filtered first, fall back to all domains if too few results
|
|
502
|
+
let strengths = this.getStrengths({
|
|
501
503
|
domain: context.domain,
|
|
502
|
-
minStrength: 30
|
|
504
|
+
minStrength: 20, // lowered from 30 — small corpus needs lower threshold
|
|
503
505
|
limit: limit * 3,
|
|
504
506
|
});
|
|
505
507
|
|
|
508
|
+
// If domain-filtered returns too few, try without domain filter
|
|
509
|
+
// This handles cases where domain was stored as 'unknown' due to
|
|
510
|
+
// vault.get() returning null during computeStrengths
|
|
511
|
+
if (strengths.length < limit && context.domain) {
|
|
512
|
+
const allStrengths = this.getStrengths({
|
|
513
|
+
minStrength: 20,
|
|
514
|
+
limit: limit * 5,
|
|
515
|
+
});
|
|
516
|
+
// Include domain-matching AND entries where domain lookup failed
|
|
517
|
+
const additional = allStrengths.filter(
|
|
518
|
+
(s) =>
|
|
519
|
+
!strengths.some((existing) => existing.pattern === s.pattern) &&
|
|
520
|
+
(s.domain === context.domain || s.domain === 'unknown'),
|
|
521
|
+
);
|
|
522
|
+
strengths = [...strengths, ...additional];
|
|
523
|
+
}
|
|
524
|
+
|
|
506
525
|
// If task context provided, boost patterns with matching terms
|
|
507
526
|
if (context.task) {
|
|
508
527
|
const taskTerms = new Set(context.task.toLowerCase().split(/\W+/).filter(Boolean));
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chain-to-capability mapping — v1 to v2 bridge.
|
|
3
|
+
*
|
|
4
|
+
* Maps Soleri's existing 26 v1 chain names (from data/flows/*.flow.yaml)
|
|
5
|
+
* to capability IDs in domain.action format.
|
|
6
|
+
*
|
|
7
|
+
* Used during migration: flows with chains: [] are auto-translated to
|
|
8
|
+
* capability references. Remove this file when all flows use needs: []
|
|
9
|
+
* exclusively.
|
|
10
|
+
*
|
|
11
|
+
* @see docs/architecture/capability-packs.md — "Chain-to-capability mapping"
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Exhaustive map of every chain name used across Soleri's 8 flow YAML files.
|
|
16
|
+
*
|
|
17
|
+
* Sources:
|
|
18
|
+
* build.flow.yaml — vault-search, memory-search, component-search,
|
|
19
|
+
* recommend-design-system, architecture-search,
|
|
20
|
+
* brain-recommend, component-workflow,
|
|
21
|
+
* validate-component, validate-tokens
|
|
22
|
+
* deliver.flow.yaml — validate-component, validate-tokens,
|
|
23
|
+
* design-rules-check, test-coverage-check,
|
|
24
|
+
* performance-audit, delivery-checklist
|
|
25
|
+
* design.flow.yaml — vault-search, memory-search, cognee-design-search,
|
|
26
|
+
* recommend-design-system, recommend-style,
|
|
27
|
+
* recommend-palette, recommend-typography,
|
|
28
|
+
* get-stack-guidelines, brain-recommend
|
|
29
|
+
* enhance.flow.yaml — vault-search, memory-search, architecture-search,
|
|
30
|
+
* brain-recommend, validate-component, validate-tokens
|
|
31
|
+
* explore.flow.yaml — vault-search, memory-search, brain-strengths,
|
|
32
|
+
* brain-recommend, playbook-search
|
|
33
|
+
* fix.flow.yaml — vault-search-antipatterns, memory-search,
|
|
34
|
+
* error-pattern-search, brain-recommend,
|
|
35
|
+
* validate-component, validate-tokens
|
|
36
|
+
* plan.flow.yaml — vault-search, memory-search, brain-recommend,
|
|
37
|
+
* architecture-search, plan-create
|
|
38
|
+
* review.flow.yaml — validate-component, validate-tokens,
|
|
39
|
+
* design-rules-check, vault-search, contrast-check,
|
|
40
|
+
* accessibility-audit, review-report
|
|
41
|
+
*/
|
|
42
|
+
const CHAIN_TO_CAPABILITY: Record<string, string> = {
|
|
43
|
+
// Vault & Knowledge
|
|
44
|
+
'vault-search': 'vault.search',
|
|
45
|
+
'vault-search-antipatterns': 'vault.search',
|
|
46
|
+
'memory-search': 'memory.search',
|
|
47
|
+
'playbook-search': 'vault.playbook',
|
|
48
|
+
|
|
49
|
+
// Brain
|
|
50
|
+
'brain-recommend': 'brain.recommend',
|
|
51
|
+
'brain-strengths': 'brain.strengths',
|
|
52
|
+
|
|
53
|
+
// Components
|
|
54
|
+
'component-search': 'component.search',
|
|
55
|
+
'component-workflow': 'component.workflow',
|
|
56
|
+
'validate-component': 'component.validate',
|
|
57
|
+
|
|
58
|
+
// Design
|
|
59
|
+
'contrast-check': 'color.validate',
|
|
60
|
+
'validate-tokens': 'token.check',
|
|
61
|
+
'design-rules-check': 'design.rules',
|
|
62
|
+
'recommend-design-system': 'design.recommend',
|
|
63
|
+
'recommend-palette': 'design.palette',
|
|
64
|
+
'recommend-style': 'design.style',
|
|
65
|
+
'recommend-typography': 'design.typography',
|
|
66
|
+
'get-stack-guidelines': 'stack.guidelines',
|
|
67
|
+
|
|
68
|
+
// Architecture
|
|
69
|
+
'architecture-search': 'architecture.search',
|
|
70
|
+
'cognee-design-search': 'cognee.search',
|
|
71
|
+
|
|
72
|
+
// Planning
|
|
73
|
+
'plan-create': 'plan.create',
|
|
74
|
+
|
|
75
|
+
// Review & Quality
|
|
76
|
+
'review-report': 'review.report',
|
|
77
|
+
'accessibility-audit': 'a11y.audit',
|
|
78
|
+
'performance-audit': 'perf.audit',
|
|
79
|
+
'test-coverage-check': 'test.coverage',
|
|
80
|
+
'error-pattern-search': 'debug.patterns',
|
|
81
|
+
'delivery-checklist': 'deliver.checklist',
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Translate a v1 chain name to a v2 capability ID.
|
|
86
|
+
*
|
|
87
|
+
* @param chain - The chain name from a flow YAML `chains:` field
|
|
88
|
+
* @returns The corresponding capability ID in domain.action format, or
|
|
89
|
+
* undefined if no mapping exists
|
|
90
|
+
*/
|
|
91
|
+
export function chainToCapability(chain: string): string | undefined {
|
|
92
|
+
return CHAIN_TO_CAPABILITY[chain];
|
|
93
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability system — barrel export.
|
|
3
|
+
*
|
|
4
|
+
* @see docs/architecture/capability-packs.md
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { CapabilityRegistry } from './registry.js';
|
|
8
|
+
export type { FlowForValidation } from './registry.js';
|
|
9
|
+
export { chainToCapability } from './chain-mapping.js';
|
|
10
|
+
export type {
|
|
11
|
+
CapabilityDefinition,
|
|
12
|
+
CapabilityHandler,
|
|
13
|
+
CapabilityContext,
|
|
14
|
+
CapabilityResult,
|
|
15
|
+
KnowledgeContext,
|
|
16
|
+
BrainRecommendation,
|
|
17
|
+
RegisteredCapability,
|
|
18
|
+
ResolvedCapability,
|
|
19
|
+
PackSuggestion,
|
|
20
|
+
FlowValidation,
|
|
21
|
+
} from './types.js';
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability Registry — runtime resolution engine for the three-layer architecture.
|
|
3
|
+
*
|
|
4
|
+
* Maps capability IDs (domain.action) to pack handlers. Resolves dependencies,
|
|
5
|
+
* checks availability, and supports graceful degradation when capabilities are
|
|
6
|
+
* missing.
|
|
7
|
+
*
|
|
8
|
+
* Registration flow:
|
|
9
|
+
* 1. Pack manifest declares capabilities (static, serializable)
|
|
10
|
+
* 2. Pack's onActivate() provides handlers (runtime, async)
|
|
11
|
+
* 3. registerPack() reconciles declarations with handlers
|
|
12
|
+
*
|
|
13
|
+
* @see docs/architecture/capability-packs.md
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type {
|
|
17
|
+
CapabilityDefinition,
|
|
18
|
+
CapabilityHandler,
|
|
19
|
+
RegisteredCapability,
|
|
20
|
+
ResolvedCapability,
|
|
21
|
+
PackSuggestion,
|
|
22
|
+
FlowValidation,
|
|
23
|
+
} from './types.js';
|
|
24
|
+
import { chainToCapability } from './chain-mapping.js';
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Flow shape accepted by validateFlow — intentionally minimal so callers
|
|
28
|
+
// don't need to import the full Flow type from ../flows/types.js.
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
export interface FlowForValidation {
|
|
32
|
+
steps: Array<{
|
|
33
|
+
needs?: string[];
|
|
34
|
+
chains?: string[];
|
|
35
|
+
}>;
|
|
36
|
+
onMissingCapability?: {
|
|
37
|
+
default?: string;
|
|
38
|
+
blocking?: string[];
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Registry
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
export class CapabilityRegistry {
|
|
47
|
+
private capabilities = new Map<string, RegisteredCapability>();
|
|
48
|
+
private packs = new Map<string, { id: string; capabilities: CapabilityDefinition[] }>();
|
|
49
|
+
|
|
50
|
+
// -----------------------------------------------------------------------
|
|
51
|
+
// Registration
|
|
52
|
+
// -----------------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Register all capabilities from an installed pack.
|
|
56
|
+
*
|
|
57
|
+
* For each definition in `definitions`, the corresponding handler is looked
|
|
58
|
+
* up in `handlers`. If no handler is found the capability is skipped with a
|
|
59
|
+
* warning. When multiple packs provide the same capability, providers are
|
|
60
|
+
* sorted by priority (descending) — highest priority wins on resolve().
|
|
61
|
+
*
|
|
62
|
+
* @param packId - Unique identifier for the pack
|
|
63
|
+
* @param definitions - Capability definitions from the pack manifest
|
|
64
|
+
* @param handlers - Map of capabilityId → handler from onActivate()
|
|
65
|
+
* @param priority - Higher = preferred (core=100, user=75, domain=50, fallback=0)
|
|
66
|
+
*/
|
|
67
|
+
registerPack(
|
|
68
|
+
packId: string,
|
|
69
|
+
definitions: CapabilityDefinition[],
|
|
70
|
+
handlers: Map<string, CapabilityHandler>,
|
|
71
|
+
priority: number = 0,
|
|
72
|
+
): void {
|
|
73
|
+
for (const definition of definitions) {
|
|
74
|
+
const handler = handlers.get(definition.id);
|
|
75
|
+
if (!handler) {
|
|
76
|
+
console.warn(
|
|
77
|
+
`Pack "${packId}" declares capability "${definition.id}" but no handler provided — skipping`,
|
|
78
|
+
);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const existing = this.capabilities.get(definition.id);
|
|
83
|
+
if (existing) {
|
|
84
|
+
// Add as additional provider, keep sorted by priority descending
|
|
85
|
+
existing.providers.push({ packId, handler, priority });
|
|
86
|
+
existing.providers.sort((a, b) => b.priority - a.priority);
|
|
87
|
+
} else {
|
|
88
|
+
this.capabilities.set(definition.id, {
|
|
89
|
+
definition,
|
|
90
|
+
providers: [{ packId, handler, priority }],
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Store pack metadata for suggestPacksFor() lookups
|
|
96
|
+
this.packs.set(packId, { id: packId, capabilities: definitions });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// -----------------------------------------------------------------------
|
|
100
|
+
// Query
|
|
101
|
+
// -----------------------------------------------------------------------
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Check if a capability is registered (has at least one provider).
|
|
105
|
+
*/
|
|
106
|
+
has(capabilityId: string): boolean {
|
|
107
|
+
return this.capabilities.has(capabilityId);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Resolve a capability — returns the highest-priority handler, knowledge
|
|
112
|
+
* refs, and provider list. If the capability is missing or has unsatisfied
|
|
113
|
+
* dependencies, returns `available: false` with suggestions.
|
|
114
|
+
*/
|
|
115
|
+
resolve(capabilityId: string): ResolvedCapability {
|
|
116
|
+
const registered = this.capabilities.get(capabilityId);
|
|
117
|
+
|
|
118
|
+
if (!registered) {
|
|
119
|
+
return {
|
|
120
|
+
available: false,
|
|
121
|
+
capabilityId,
|
|
122
|
+
suggestion: this.suggestPacksFor([capabilityId]),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Check dependency satisfaction
|
|
127
|
+
const depends = registered.definition.depends ?? [];
|
|
128
|
+
const missingDeps = depends.filter((dep) => !this.capabilities.has(dep));
|
|
129
|
+
|
|
130
|
+
if (missingDeps.length > 0) {
|
|
131
|
+
return {
|
|
132
|
+
available: false,
|
|
133
|
+
capabilityId,
|
|
134
|
+
missingDependencies: missingDeps,
|
|
135
|
+
suggestion: this.suggestPacksFor(missingDeps),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Resolved — return the highest-priority provider (index 0 after sort)
|
|
140
|
+
const primary = registered.providers[0];
|
|
141
|
+
return {
|
|
142
|
+
available: true,
|
|
143
|
+
capabilityId,
|
|
144
|
+
handler: primary.handler,
|
|
145
|
+
providers: registered.providers.map((p) => p.packId),
|
|
146
|
+
knowledge: registered.definition.knowledge ?? [],
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* List all registered capabilities grouped by domain.
|
|
152
|
+
*
|
|
153
|
+
* Domain is derived from the first segment of the capability ID
|
|
154
|
+
* (e.g., "color" from "color.validate").
|
|
155
|
+
*/
|
|
156
|
+
list(): Map<string, CapabilityDefinition[]> {
|
|
157
|
+
const grouped = new Map<string, CapabilityDefinition[]>();
|
|
158
|
+
|
|
159
|
+
for (const [id, registered] of this.capabilities) {
|
|
160
|
+
const domain = id.split('.')[0];
|
|
161
|
+
const group = grouped.get(domain) ?? [];
|
|
162
|
+
group.push(registered.definition);
|
|
163
|
+
grouped.set(domain, group);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return grouped;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Search registered packs for capabilities matching the requested IDs.
|
|
171
|
+
*
|
|
172
|
+
* This searches ALL packs (not just capabilities currently registered with
|
|
173
|
+
* handlers) — useful for suggesting which packs to install when a capability
|
|
174
|
+
* is missing.
|
|
175
|
+
*/
|
|
176
|
+
suggestPacksFor(capabilityIds: string[]): PackSuggestion[] {
|
|
177
|
+
if (capabilityIds.length === 0) return [];
|
|
178
|
+
|
|
179
|
+
const idSet = new Set(capabilityIds);
|
|
180
|
+
const suggestions: PackSuggestion[] = [];
|
|
181
|
+
|
|
182
|
+
for (const [, pack] of this.packs) {
|
|
183
|
+
const provides = pack.capabilities.filter((cap) => idSet.has(cap.id)).map((cap) => cap.id);
|
|
184
|
+
|
|
185
|
+
if (provides.length > 0) {
|
|
186
|
+
suggestions.push({ packId: pack.id, provides });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return suggestions;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// -----------------------------------------------------------------------
|
|
194
|
+
// Validation
|
|
195
|
+
// -----------------------------------------------------------------------
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Validate a flow's capability requirements against installed packs.
|
|
199
|
+
*
|
|
200
|
+
* Reads both `needs` (v2 preferred) and `chains` (v1 deprecated) fields.
|
|
201
|
+
* For v1 chains, attempts best-effort mapping via chainToCapability().
|
|
202
|
+
*
|
|
203
|
+
* Missing capabilities are classified as either "blocking" or "degraded"
|
|
204
|
+
* based on the flow's onMissingCapability config.
|
|
205
|
+
*/
|
|
206
|
+
validateFlow(flow: FlowForValidation): FlowValidation {
|
|
207
|
+
// Collect all capability IDs needed across all steps
|
|
208
|
+
const needed = new Set<string>();
|
|
209
|
+
|
|
210
|
+
for (const step of flow.steps) {
|
|
211
|
+
// v2: needs field (preferred)
|
|
212
|
+
if (step.needs) {
|
|
213
|
+
for (const cap of step.needs) {
|
|
214
|
+
needed.add(cap);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// v1: chains field (deprecated, best-effort mapping)
|
|
219
|
+
if (step.chains) {
|
|
220
|
+
for (const chain of step.chains) {
|
|
221
|
+
const capId = chainToCapability(chain);
|
|
222
|
+
if (capId) needed.add(capId);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Partition into available vs missing
|
|
228
|
+
const available: string[] = [];
|
|
229
|
+
const missing: string[] = [];
|
|
230
|
+
|
|
231
|
+
for (const capId of needed) {
|
|
232
|
+
if (this.has(capId)) {
|
|
233
|
+
available.push(capId);
|
|
234
|
+
} else {
|
|
235
|
+
missing.push(capId);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Classify missing capabilities by impact
|
|
240
|
+
const blockingSet = new Set(flow.onMissingCapability?.blocking ?? []);
|
|
241
|
+
|
|
242
|
+
const degraded = missing.map((capability) => ({
|
|
243
|
+
capability,
|
|
244
|
+
impact: blockingSet.has(capability) ? ('blocking' as const) : ('degraded' as const),
|
|
245
|
+
suggestion: this.suggestPacksFor([capability]),
|
|
246
|
+
}));
|
|
247
|
+
|
|
248
|
+
const hasBlocker = degraded.some((d) => d.impact === 'blocking');
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
valid: missing.length === 0,
|
|
252
|
+
available,
|
|
253
|
+
missing,
|
|
254
|
+
degraded,
|
|
255
|
+
canRunPartially: !hasBlocker,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// -----------------------------------------------------------------------
|
|
260
|
+
// Inspection (useful for debugging / CLI commands)
|
|
261
|
+
// -----------------------------------------------------------------------
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Total number of registered capabilities.
|
|
265
|
+
*/
|
|
266
|
+
get size(): number {
|
|
267
|
+
return this.capabilities.size;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Total number of registered packs.
|
|
272
|
+
*/
|
|
273
|
+
get packCount(): number {
|
|
274
|
+
return this.packs.size;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Get all registered capability IDs.
|
|
279
|
+
*/
|
|
280
|
+
ids(): string[] {
|
|
281
|
+
return [...this.capabilities.keys()];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Get the RegisteredCapability for a given ID, or undefined.
|
|
286
|
+
*/
|
|
287
|
+
get(capabilityId: string): RegisteredCapability | undefined {
|
|
288
|
+
return this.capabilities.get(capabilityId);
|
|
289
|
+
}
|
|
290
|
+
}
|