@polymorphism-tech/morph-spec 4.15.0 → 4.17.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.
Files changed (100) hide show
  1. package/README.md +2 -2
  2. package/bin/morph-spec.js +4 -0
  3. package/bin/task-manager.js +999 -962
  4. package/claude-plugin.json +1 -1
  5. package/docs/CHEATSHEET.md +1 -1
  6. package/docs/QUICKSTART.md +1 -1
  7. package/framework/agents/ai-agents/vector-search-expert.md +247 -233
  8. package/framework/agents/backend/ms-agent-expert.md +2 -1
  9. package/framework/agents/backend/neon-expert.md +397 -0
  10. package/framework/agents/frontend/gsap-animator.md +131 -0
  11. package/framework/agents.json +1175 -1077
  12. package/framework/commands/morph-preflight.md +200 -192
  13. package/framework/hooks/claude-code/session-start/inject-morph-context.js +1 -1
  14. package/framework/rules/gsap-standards.md +13 -0
  15. package/framework/rules/neon-standards.md +25 -0
  16. package/framework/skills/level-0-meta/mcp-registry.json +1 -1
  17. package/framework/skills/level-0-meta/morph-agent-teams/SKILL.md +472 -472
  18. package/framework/skills/level-0-meta/morph-init/SKILL.md +30 -11
  19. package/framework/skills/level-0-meta/morph-post-implementation/SKILL.md +5 -5
  20. package/framework/skills/level-0-meta/morph-tool-usage-guide/SKILL.md +5 -5
  21. package/framework/skills/level-0-meta/morph-tool-usage-guide/references/tools-per-phase.md +7 -7
  22. package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +24 -24
  23. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +12 -12
  24. package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +9 -9
  25. package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +1 -1
  26. package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +1 -1
  27. package/framework/skills/level-1-workflows/morph-phase-tasks/references/task-planning-patterns.md +143 -143
  28. package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +1 -1
  29. package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
  30. package/framework/standards/STANDARDS.json +184 -107
  31. package/framework/standards/ai-agents/production.md +1 -0
  32. package/framework/standards/ai-agents/setup.md +3 -2
  33. package/framework/standards/ai-agents/workflows.md +1 -0
  34. package/framework/standards/architecture/vertical-slice/vertical-slice.md +4 -4
  35. package/framework/standards/backend/database/postgresql/database.md +58 -78
  36. package/framework/standards/backend/dotnet/scalar-ui.md +172 -172
  37. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +274 -274
  38. package/framework/standards/backend/integrations/asaas/asaas-api.md +1 -1
  39. package/framework/standards/backend/integrations/clerk/clerk-auth.md +23 -21
  40. package/framework/standards/frontend/design-system/animations.md +9 -0
  41. package/framework/standards/frontend/gsap/gsap-core.md +463 -0
  42. package/framework/standards/frontend/gsap/gsap-plugins.md +294 -0
  43. package/framework/standards/frontend/gsap/gsap-scrolltrigger.md +318 -0
  44. package/framework/standards/frontend/nextjs/motion-patterns.md +1 -0
  45. package/framework/standards/frontend/nextjs/nextjs-patterns.md +47 -37
  46. package/framework/standards/infrastructure/docker/easypanel-deploy.md +4 -8
  47. package/framework/standards/infrastructure/neon/neon-pgrag.md +239 -0
  48. package/framework/standards/infrastructure/neon/neon-pgvector.md +236 -0
  49. package/framework/standards/infrastructure/neon/neon-semantic-kernel.md +310 -0
  50. package/framework/standards/infrastructure/neon/neon-setup.md +186 -0
  51. package/framework/standards/integration/mcp/mcp-tools.md +32 -34
  52. package/framework/templates/README.md +18 -18
  53. package/framework/templates/REGISTRY.json +49 -96
  54. package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
  55. package/framework/templates/code/dotnet/backend/repository.cs +148 -148
  56. package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +2 -2
  57. package/framework/templates/code/dotnet/database/vector-entity.cs +93 -0
  58. package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +1 -1
  59. package/framework/templates/code/sql/{supabase-migration.sql → postgresql-migration.sql} +8 -17
  60. package/framework/templates/code/sql/{supabase-migration.template.sql → postgresql-migration.template.sql} +10 -13
  61. package/framework/templates/code/sql/{rls-policy.sql → postgresql-rls-policy.sql} +8 -8
  62. package/framework/templates/code/typescript/contracts.ts +167 -168
  63. package/framework/templates/context/CONTEXT.md +3 -3
  64. package/framework/templates/docs/proposal.md +6 -6
  65. package/framework/templates/docs/ui-components.md +1 -1
  66. package/framework/templates/feature/decisions.md +121 -121
  67. package/framework/templates/feature/recap.md +145 -145
  68. package/framework/templates/feature/tasks.md +199 -199
  69. package/framework/templates/frontend/nextjs/gsap-scroll-section.tsx.hbs +44 -0
  70. package/framework/templates/infrastructure/docker/docker-compose.template.yml +50 -67
  71. package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
  72. package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
  73. package/framework/templates/infrastructure/docker/easypanel.template.json +46 -54
  74. package/framework/templates/infrastructure/github/README.md +56 -56
  75. package/framework/templates/integrations/semantic-kernel-neon.cs +125 -0
  76. package/framework/workflows/README.md +1 -1
  77. package/framework/workflows/docs/full-morph.md +69 -69
  78. package/package.json +1 -1
  79. package/src/commands/agents/dispatch-agents.js +19 -15
  80. package/src/commands/project/setup-infra-cmd.js +1 -1
  81. package/src/commands/state/advance-phase.js +5 -0
  82. package/src/commands/tasks/task.js +3 -0
  83. package/src/core/state/state-manager.js +45 -1
  84. package/src/core/templates/template-registry.js +1 -66
  85. package/src/lib/detectors/index.js +2 -2
  86. package/src/lib/generators/architecture-scanner.js +640 -640
  87. package/src/lib/installers/mcp-installer.js +1 -1
  88. package/src/lib/tasks/task-classifier.js +15 -1
  89. package/src/lib/tasks/test-runner.js +5 -1
  90. package/src/lib/validators/content/content-validator.js +9 -10
  91. package/src/lib/validators/validation-runner.js +7 -5
  92. package/src/scripts/setup-infra.js +60 -30
  93. package/framework/agents/backend/supabase-expert.md +0 -256
  94. package/framework/rules/supabase-standards.md +0 -29
  95. package/framework/standards/infrastructure/supabase/mcp-setup.md +0 -142
  96. package/framework/standards/infrastructure/supabase/supabase-auth.md +0 -176
  97. package/framework/standards/infrastructure/supabase/supabase-custom-jwt.md +0 -206
  98. package/framework/standards/infrastructure/supabase/supabase-pgvector.md +0 -169
  99. package/framework/standards/infrastructure/supabase/supabase-rls.md +0 -184
  100. package/framework/standards/infrastructure/supabase/supabase-storage.md +0 -153
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "morph-spec",
3
- "version": "4.15.0",
3
+ "version": "4.17.0",
4
4
  "displayName": "MORPH-SPEC Framework",
5
5
  "description": "Spec-driven development with 38 agents and 8-phase workflow for .NET/Blazor/Next.js/Azure",
6
6
  "publisher": "polymorphism-tech",
@@ -196,4 +196,4 @@ These files are never edited directly. Use CLI commands or `morph-spec update` i
196
196
 
197
197
  ---
198
198
 
199
- *morph-spec v4.15.0 by Polymorphism Tech*
199
+ *morph-spec v4.17.0 by Polymorphism Tech*
@@ -197,4 +197,4 @@ morph-spec doctor
197
197
 
198
198
  ---
199
199
 
200
- *morph-spec v4.15.0 by Polymorphism Tech*
200
+ *morph-spec v4.17.0 by Polymorphism Tech*
@@ -1,233 +1,247 @@
1
- ---
2
- name: vector-search-expert
3
- description: Vector Search & RAG specialist for embedding pipelines, pgvector indexes, semantic search, hybrid search, and retrieval-augmented generation. Use when implementing embedding generation, vector similarity search, RAG pipelines, or hybrid full-text + vector search.
4
- allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
- color: yellow
6
- effort: medium
7
- ---
8
-
9
- # Vector Search & RAG Specialist
10
-
11
- Expert in embedding pipelines, pgvector, semantic search, and retrieval-augmented generation.
12
-
13
- > **Ref:** `framework/standards/backend/database/vector-search-rag.md` — Chunking, embedding, retrieval patterns
14
-
15
- ---
16
-
17
- ## Embedding Pipeline
18
-
19
- ```
20
- Documents → Chunking → Embedding → pgvector Storage → Retrieval → LLM
21
- ```
22
-
23
- ### Chunking Strategies
24
-
25
- | Strategy | Method | Best For | Chunk Size |
26
- |----------|--------|----------|------------|
27
- | **Paragraph** | Split by `\n\n` | General text | 200-500 tokens |
28
- | **Markdown Headers** | Split by `#`, `##` | Documentation | Variable |
29
- | **Token-based** | Fixed token windows | Uniform chunks | 256-512 tokens |
30
- | **Semantic** | Cosine similarity threshold | Highest quality | Variable |
31
-
32
- **Always overlap:** 10-20% overlap between chunks prevents context loss at boundaries.
33
-
34
- ```csharp
35
- // Simple paragraph chunker
36
- public static IEnumerable<string> ChunkByParagraph(string text, int maxTokens = 500)
37
- {
38
- var paragraphs = text.Split("\n\n", StringSplitOptions.RemoveEmptyEntries);
39
- var current = new StringBuilder();
40
- var currentTokens = 0;
41
-
42
- foreach (var para in paragraphs)
43
- {
44
- var paraTokens = EstimateTokens(para);
45
- if (currentTokens + paraTokens > maxTokens && current.Length > 0)
46
- {
47
- yield return current.ToString().Trim();
48
- current.Clear();
49
- currentTokens = 0;
50
- }
51
- current.AppendLine(para);
52
- currentTokens += paraTokens;
53
- }
54
- if (current.Length > 0) yield return current.ToString().Trim();
55
- }
56
- ```
57
-
58
- ---
59
-
60
- ## Embedding Generation
61
-
62
- ```csharp
63
- // Using Microsoft.Extensions.AI
64
- public class EmbeddingService(IEmbeddingGenerator<string, Embedding<float>> generator)
65
- {
66
- public async Task<float[]> GenerateAsync(string text, CancellationToken ct = default)
67
- {
68
- var result = await generator.GenerateAsync([text], cancellationToken: ct);
69
- return result[0].Vector.ToArray();
70
- }
71
-
72
- public async Task<IReadOnlyList<float[]>> GenerateBatchAsync(
73
- IEnumerable<string> texts, CancellationToken ct = default)
74
- {
75
- var result = await generator.GenerateAsync(texts.ToList(), cancellationToken: ct);
76
- return result.Select(e => e.Vector.ToArray()).ToList();
77
- }
78
- }
79
-
80
- // Registration
81
- builder.Services.AddEmbeddingGenerator(b => b
82
- .UseOpenTelemetry()
83
- .UseLogging()
84
- .Use(new OpenAIEmbeddingGenerator(
85
- new OpenAIClient(apiKey),
86
- "text-embedding-3-small"))); // 1536 dimensions
87
- ```
88
-
89
- ---
90
-
91
- ## pgvector Storage & Search
92
-
93
- ### Table schema
94
-
95
- ```sql
96
- CREATE TABLE public.embeddings (
97
- id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
98
- source_id UUID NOT NULL,
99
- source_type TEXT NOT NULL, -- 'document', 'faq', 'article'
100
- chunk_index INT NOT NULL,
101
- content TEXT NOT NULL,
102
- embedding vector(1536) NOT NULL,
103
- metadata JSONB DEFAULT '{}'::jsonb,
104
- created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
105
- UNIQUE(source_id, chunk_index)
106
- );
107
-
108
- -- HNSW index (fast, recommended for < 1M vectors)
109
- CREATE INDEX idx_embeddings_hnsw ON public.embeddings
110
- USING hnsw (embedding vector_cosine_ops)
111
- WITH (m = 16, ef_construction = 64);
112
-
113
- -- IVFFlat index (better for > 1M vectors)
114
- -- CREATE INDEX idx_embeddings_ivf ON public.embeddings
115
- -- USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
116
- ```
117
-
118
- ### Similarity search
119
-
120
- ```sql
121
- -- Cosine similarity (1 = identical, 0 = unrelated)
122
- SELECT id, content, metadata,
123
- 1 - (embedding <=> $1::vector) AS similarity
124
- FROM public.embeddings
125
- WHERE 1 - (embedding <=> $1::vector) > 0.78
126
- ORDER BY embedding <=> $1::vector
127
- LIMIT 5;
128
- ```
129
-
130
- ### Hybrid search (vector + full-text)
131
-
132
- ```sql
133
- -- Combine vector similarity with PostgreSQL full-text search
134
- CREATE OR REPLACE FUNCTION hybrid_search(
135
- query_text TEXT,
136
- query_embedding vector(1536),
137
- match_count INT DEFAULT 5,
138
- vector_weight FLOAT DEFAULT 0.7,
139
- text_weight FLOAT DEFAULT 0.3
140
- )
141
- RETURNS TABLE (id UUID, content TEXT, score FLOAT)
142
- LANGUAGE plpgsql AS $$
143
- BEGIN
144
- RETURN QUERY
145
- WITH vector_results AS (
146
- SELECT e.id, e.content,
147
- 1 - (e.embedding <=> query_embedding) AS vscore
148
- FROM public.embeddings e
149
- ORDER BY e.embedding <=> query_embedding
150
- LIMIT match_count * 3
151
- ),
152
- text_results AS (
153
- SELECT e.id, e.content,
154
- ts_rank(to_tsvector('english', e.content), plainto_tsquery('english', query_text)) AS tscore
155
- FROM public.embeddings e
156
- WHERE to_tsvector('english', e.content) @@ plainto_tsquery('english', query_text)
157
- LIMIT match_count * 3
158
- )
159
- SELECT COALESCE(v.id, t.id),
160
- COALESCE(v.content, t.content),
161
- (COALESCE(v.vscore, 0) * vector_weight + COALESCE(t.tscore, 0) * text_weight) AS score
162
- FROM vector_results v
163
- FULL OUTER JOIN text_results t ON v.id = t.id
164
- ORDER BY score DESC
165
- LIMIT match_count;
166
- END;
167
- $$;
168
- ```
169
-
170
- ---
171
-
172
- ## RAG Tool for Agent Framework
173
-
174
- ```csharp
175
- public class KnowledgeBaseTool(
176
- EmbeddingService embeddings,
177
- ISupabaseClient supabase)
178
- {
179
- [Description("Search the knowledge base for relevant information")]
180
- public async Task<string> SearchAsync(
181
- [Description("Natural language search query")] string query,
182
- [Description("Maximum results to return")] int topK = 5,
183
- CancellationToken ct = default)
184
- {
185
- var embedding = await embeddings.GenerateAsync(query, ct);
186
-
187
- var results = await supabase.Rpc("match_embeddings", new
188
- {
189
- query_embedding = embedding,
190
- match_threshold = 0.78,
191
- match_count = topK
192
- }, ct);
193
-
194
- return string.Join("\n\n---\n\n",
195
- results.Select(r => $"[Score: {r.Similarity:F2}]\n{r.Content}"));
196
- }
197
- }
198
- ```
199
-
200
- ---
201
-
202
- ## Index Selection Guide
203
-
204
- | Vectors | Recommended | Why |
205
- |---------|-------------|-----|
206
- | < 10K | No index (sequential scan) | Index overhead not worth it |
207
- | 10K - 1M | HNSW (m=16, ef=64) | Fast, good recall |
208
- | 1M+ | IVFFlat (lists=sqrt(n)) | Lower memory, acceptable recall |
209
-
210
- ### Tuning HNSW
211
-
212
- - `m` (connections per node): higher = better recall, more memory. Default 16.
213
- - `ef_construction` (build-time search depth): higher = better index, slower build. Default 64.
214
- - `ef_search` (query-time): `SET hnsw.ef_search = 100;` for better recall at query time.
215
-
216
- ---
217
-
218
- ## Checklist
219
-
220
- - [ ] Chunking strategy selected and tested with real data
221
- - [ ] Chunk overlap configured (10-20%)
222
- - [ ] Embedding model chosen (text-embedding-3-small for cost, text-embedding-3-large for quality)
223
- - [ ] pgvector extension enabled
224
- - [ ] HNSW or IVFFlat index created based on vector count
225
- - [ ] Similarity threshold tuned (start at 0.78, adjust by domain)
226
- - [ ] Hybrid search implemented if full-text relevance matters
227
- - [ ] Batch embedding for initial ingestion (not one-by-one)
228
- - [ ] RLS policies on embeddings table
229
- - [ ] Source tracking (source_id + source_type) for updates/deletes
230
-
231
- ---
232
-
233
- *MORPH-SPEC by Polymorphism Tech*
1
+ ---
2
+ name: vector-search-expert
3
+ description: Vector Search & RAG specialist for embedding pipelines, pgvector indexes, semantic search, hybrid search, and retrieval-augmented generation. Use when implementing embedding generation, vector similarity search, RAG pipelines, or hybrid full-text + vector search.
4
+ allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
+ color: yellow
6
+ effort: medium
7
+ ---
8
+
9
+ # Vector Search & RAG Specialist
10
+
11
+ Expert in embedding pipelines, pgvector, semantic search, and retrieval-augmented generation.
12
+
13
+ > **Ref:** `framework/standards/backend/database/vector-search-rag.md` — Chunking, embedding, retrieval patterns
14
+
15
+ ---
16
+
17
+ ## Embedding Pipeline
18
+
19
+ ```
20
+ Documents → Chunking → Embedding → pgvector Storage → Retrieval → LLM
21
+ ```
22
+
23
+ ### Chunking Strategies
24
+
25
+ | Strategy | Method | Best For | Chunk Size |
26
+ |----------|--------|----------|------------|
27
+ | **Paragraph** | Split by `\n\n` | General text | 200-500 tokens |
28
+ | **Markdown Headers** | Split by `#`, `##` | Documentation | Variable |
29
+ | **Token-based** | Fixed token windows | Uniform chunks | 256-512 tokens |
30
+ | **Semantic** | Cosine similarity threshold | Highest quality | Variable |
31
+
32
+ **Always overlap:** 10-20% overlap between chunks prevents context loss at boundaries.
33
+
34
+ ```csharp
35
+ // Simple paragraph chunker
36
+ public static IEnumerable<string> ChunkByParagraph(string text, int maxTokens = 500)
37
+ {
38
+ var paragraphs = text.Split("\n\n", StringSplitOptions.RemoveEmptyEntries);
39
+ var current = new StringBuilder();
40
+ var currentTokens = 0;
41
+
42
+ foreach (var para in paragraphs)
43
+ {
44
+ var paraTokens = EstimateTokens(para);
45
+ if (currentTokens + paraTokens > maxTokens && current.Length > 0)
46
+ {
47
+ yield return current.ToString().Trim();
48
+ current.Clear();
49
+ currentTokens = 0;
50
+ }
51
+ current.AppendLine(para);
52
+ currentTokens += paraTokens;
53
+ }
54
+ if (current.Length > 0) yield return current.ToString().Trim();
55
+ }
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Embedding Generation
61
+
62
+ ```csharp
63
+ // Using Microsoft.Extensions.AI
64
+ public class EmbeddingService(IEmbeddingGenerator<string, Embedding<float>> generator)
65
+ {
66
+ public async Task<float[]> GenerateAsync(string text, CancellationToken ct = default)
67
+ {
68
+ var result = await generator.GenerateAsync([text], cancellationToken: ct);
69
+ return result[0].Vector.ToArray();
70
+ }
71
+
72
+ public async Task<IReadOnlyList<float[]>> GenerateBatchAsync(
73
+ IEnumerable<string> texts, CancellationToken ct = default)
74
+ {
75
+ var result = await generator.GenerateAsync(texts.ToList(), cancellationToken: ct);
76
+ return result.Select(e => e.Vector.ToArray()).ToList();
77
+ }
78
+ }
79
+
80
+ // Registration
81
+ builder.Services.AddEmbeddingGenerator(b => b
82
+ .UseOpenTelemetry()
83
+ .UseLogging()
84
+ .Use(new OpenAIEmbeddingGenerator(
85
+ new OpenAIClient(apiKey),
86
+ "text-embedding-3-small"))); // 1536 dimensions
87
+ ```
88
+
89
+ ---
90
+
91
+ ## pgvector Storage & Search
92
+
93
+ ### Table schema
94
+
95
+ ```sql
96
+ CREATE TABLE public.embeddings (
97
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
98
+ source_id UUID NOT NULL,
99
+ source_type TEXT NOT NULL, -- 'document', 'faq', 'article'
100
+ chunk_index INT NOT NULL,
101
+ content TEXT NOT NULL,
102
+ embedding vector(1536) NOT NULL,
103
+ metadata JSONB DEFAULT '{}'::jsonb,
104
+ created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
105
+ UNIQUE(source_id, chunk_index)
106
+ );
107
+
108
+ -- HNSW index (fast, recommended for < 1M vectors)
109
+ CREATE INDEX idx_embeddings_hnsw ON public.embeddings
110
+ USING hnsw (embedding vector_cosine_ops)
111
+ WITH (m = 16, ef_construction = 64);
112
+
113
+ -- IVFFlat index (better for > 1M vectors)
114
+ -- CREATE INDEX idx_embeddings_ivf ON public.embeddings
115
+ -- USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
116
+ ```
117
+
118
+ ### Similarity search
119
+
120
+ ```sql
121
+ -- Cosine similarity (1 = identical, 0 = unrelated)
122
+ SELECT id, content, metadata,
123
+ 1 - (embedding <=> $1::vector) AS similarity
124
+ FROM public.embeddings
125
+ WHERE 1 - (embedding <=> $1::vector) > 0.78
126
+ ORDER BY embedding <=> $1::vector
127
+ LIMIT 5;
128
+ ```
129
+
130
+ ### Hybrid search (vector + full-text)
131
+
132
+ ```sql
133
+ -- Combine vector similarity with PostgreSQL full-text search
134
+ CREATE OR REPLACE FUNCTION hybrid_search(
135
+ query_text TEXT,
136
+ query_embedding vector(1536),
137
+ match_count INT DEFAULT 5,
138
+ vector_weight FLOAT DEFAULT 0.7,
139
+ text_weight FLOAT DEFAULT 0.3
140
+ )
141
+ RETURNS TABLE (id UUID, content TEXT, score FLOAT)
142
+ LANGUAGE plpgsql AS $$
143
+ BEGIN
144
+ RETURN QUERY
145
+ WITH vector_results AS (
146
+ SELECT e.id, e.content,
147
+ 1 - (e.embedding <=> query_embedding) AS vscore
148
+ FROM public.embeddings e
149
+ ORDER BY e.embedding <=> query_embedding
150
+ LIMIT match_count * 3
151
+ ),
152
+ text_results AS (
153
+ SELECT e.id, e.content,
154
+ ts_rank(to_tsvector('english', e.content), plainto_tsquery('english', query_text)) AS tscore
155
+ FROM public.embeddings e
156
+ WHERE to_tsvector('english', e.content) @@ plainto_tsquery('english', query_text)
157
+ LIMIT match_count * 3
158
+ )
159
+ SELECT COALESCE(v.id, t.id),
160
+ COALESCE(v.content, t.content),
161
+ (COALESCE(v.vscore, 0) * vector_weight + COALESCE(t.tscore, 0) * text_weight) AS score
162
+ FROM vector_results v
163
+ FULL OUTER JOIN text_results t ON v.id = t.id
164
+ ORDER BY score DESC
165
+ LIMIT match_count;
166
+ END;
167
+ $$;
168
+ ```
169
+
170
+ ---
171
+
172
+ ## RAG Tool for Agent Framework
173
+
174
+ ```csharp
175
+ public class KnowledgeBaseTool(
176
+ EmbeddingService embeddings,
177
+ NpgsqlDataSource dataSource)
178
+ {
179
+ [Description("Search the knowledge base for relevant information")]
180
+ public async Task<string> SearchAsync(
181
+ [Description("Natural language search query")] string query,
182
+ [Description("Maximum results to return")] int topK = 5,
183
+ CancellationToken ct = default)
184
+ {
185
+ var embedding = await embeddings.GenerateAsync(query, ct);
186
+
187
+ await using var conn = await dataSource.OpenConnectionAsync(ct);
188
+ await using var cmd = new NpgsqlCommand("""
189
+ SELECT id, content, metadata,
190
+ 1 - (embedding <=> @embedding::vector) AS similarity
191
+ FROM public.embeddings
192
+ WHERE 1 - (embedding <=> @embedding::vector) > @threshold
193
+ ORDER BY embedding <=> @embedding::vector
194
+ LIMIT @topK
195
+ """, conn);
196
+
197
+ cmd.Parameters.AddWithValue("embedding", embedding);
198
+ cmd.Parameters.AddWithValue("threshold", 0.78);
199
+ cmd.Parameters.AddWithValue("topK", topK);
200
+
201
+ var results = new List<(double Similarity, string Content)>();
202
+ await using var reader = await cmd.ExecuteReaderAsync(ct);
203
+ while (await reader.ReadAsync(ct))
204
+ {
205
+ results.Add((reader.GetDouble(3), reader.GetString(1)));
206
+ }
207
+
208
+ return string.Join("\n\n---\n\n",
209
+ results.Select(r => $"[Score: {r.Similarity:F2}]\n{r.Content}"));
210
+ }
211
+ }
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Index Selection Guide
217
+
218
+ | Vectors | Recommended | Why |
219
+ |---------|-------------|-----|
220
+ | < 10K | No index (sequential scan) | Index overhead not worth it |
221
+ | 10K - 1M | HNSW (m=16, ef=64) | Fast, good recall |
222
+ | 1M+ | IVFFlat (lists=sqrt(n)) | Lower memory, acceptable recall |
223
+
224
+ ### Tuning HNSW
225
+
226
+ - `m` (connections per node): higher = better recall, more memory. Default 16.
227
+ - `ef_construction` (build-time search depth): higher = better index, slower build. Default 64.
228
+ - `ef_search` (query-time): `SET hnsw.ef_search = 100;` for better recall at query time.
229
+
230
+ ---
231
+
232
+ ## Checklist
233
+
234
+ - [ ] Chunking strategy selected and tested with real data
235
+ - [ ] Chunk overlap configured (10-20%)
236
+ - [ ] Embedding model chosen (text-embedding-3-small for cost, text-embedding-3-large for quality)
237
+ - [ ] pgvector extension enabled
238
+ - [ ] HNSW or IVFFlat index created based on vector count
239
+ - [ ] Similarity threshold tuned (start at 0.78, adjust by domain)
240
+ - [ ] Hybrid search implemented if full-text relevance matters
241
+ - [ ] Batch embedding for initial ingestion (not one-by-one)
242
+ - [ ] RLS policies on embeddings table
243
+ - [ ] Source tracking (source_id + source_type) for updates/deletes
244
+
245
+ ---
246
+
247
+ *MORPH-SPEC by Polymorphism Tech*
@@ -3,6 +3,7 @@ name: ms-agent-expert
3
3
  description: Microsoft Agent Framework Expert for Semantic Kernel, AI extensions, function calling, MCP/A2A protocols, and agentic pipeline implementation. Use when building AI agents with Semantic Kernel, implementing tool/plugin calling, designing multi-agent workflows, or integrating LLMs with .NET services.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  stacks:
6
+ - dotnet
6
7
  - semantic-kernel
7
8
  - ms-agents
8
9
  color: yellow
@@ -34,7 +35,7 @@ When working on AI agent tasks:
34
35
  1. Consult `setup.md` for agent configuration, tools, and DI registration
35
36
  2. Follow `workflows.md` for orchestration (sequential, parallel, conditional)
36
37
  3. Apply `production.md` for middleware, observability, and production patterns
37
- 4. NEVER use Semantic Kernel - use Microsoft.Agents.AI exclusively
38
+ 4. Prefer Microsoft.Agents.AI for agent workflows (preview). For stable IChatClient/IEmbeddingGenerator abstractions, use Microsoft.Extensions.AI as fallback until MAF reaches GA.
38
39
 
39
40
  ## When to Use
40
41