@polymorphism-tech/morph-spec 4.14.0 → 4.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/bin/morph-spec.js +1 -0
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/agents/ai-agents/ai-system-architect.md +2 -0
- package/framework/agents/ai-agents/vector-search-expert.md +233 -0
- package/framework/agents/architecture/seo-growth-hacker.md +2 -0
- package/framework/agents/architecture/standards-architect.md +3 -0
- package/framework/agents/backend/dotnet-senior.md +3 -0
- package/framework/agents/backend/ef-modeler.md +2 -0
- package/framework/agents/backend/hangfire-orchestrator.md +2 -0
- package/framework/agents/backend/ms-agent-expert.md +3 -0
- package/framework/agents/backend/supabase-expert.md +256 -0
- package/framework/agents/frontend/css-specialist.md +2 -0
- package/framework/agents/frontend/nextjs-expert.md +3 -0
- package/framework/agents/frontend/ui-ux-designer.md +3 -1
- package/framework/agents/infrastructure/infra-architect.md +3 -0
- package/framework/agents/integrations/asaas-financial.md +2 -0
- package/framework/agents/integrations/clerk-auth.md +2 -0
- package/framework/agents/integrations/resend-email.md +2 -0
- package/framework/agents.json +31 -30
- package/framework/skills/level-0-meta/morph-init/SKILL.md +19 -0
- package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
- package/package.json +1 -1
- package/src/commands/project/setup-infra-cmd.js +1 -1
- package/src/scripts/setup-infra.js +60 -30
- package/src/utils/agents-installer.js +18 -8
- package/framework/agents/integrations/hangfire-integration.md +0 -69
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Spec-driven development framework for multi-stack projects. Turns feature requests into implementation-ready code through structured, AI-orchestrated phases.
|
|
4
4
|
|
|
5
5
|
**Package:** `@polymorphism-tech/morph-spec`
|
|
6
|
-
**Version:** 4.
|
|
6
|
+
**Version:** 4.16.0
|
|
7
7
|
**Requires:** Node.js 18+, Claude Code
|
|
8
8
|
|
|
9
9
|
---
|
|
@@ -364,4 +364,4 @@ Code generated by morph-spec (contracts, templates, implementation output) belon
|
|
|
364
364
|
|
|
365
365
|
---
|
|
366
366
|
|
|
367
|
-
*morph-spec v4.
|
|
367
|
+
*morph-spec v4.16.0 by [Polymorphism Tech](https://polymorphism.tech)*
|
package/bin/morph-spec.js
CHANGED
|
@@ -98,6 +98,7 @@ program
|
|
|
98
98
|
.command('setup-infra')
|
|
99
99
|
.description('Install MORPH-SPEC infrastructure (headless, no prompts). Called by /morph-init skill.')
|
|
100
100
|
.option('-p, --path <path>', 'Target path (default: current directory)')
|
|
101
|
+
.option('--reinstall', 'Re-install only stack-aware assets (rules, skills, agents)')
|
|
101
102
|
.action(setupInfraCommand);
|
|
102
103
|
|
|
103
104
|
program
|
package/claude-plugin.json
CHANGED
package/docs/CHEATSHEET.md
CHANGED
package/docs/QUICKSTART.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
name: ai-system-architect
|
|
3
3
|
description: AI System Architect specialist for designing multi-agent systems, LLM orchestration, RAG pipelines, and Semantic Kernel patterns. Use when designing AI agent architectures, implementing LLM-powered features, building RAG pipelines, or integrating Microsoft Agent Framework.
|
|
4
4
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
color: orange
|
|
6
|
+
effort: high
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# AI System Architect
|
|
@@ -0,0 +1,233 @@
|
|
|
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*
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
name: seo-growth-hacker
|
|
3
3
|
description: SEO and Growth specialist for technical SEO, Core Web Vitals optimization, content strategy, and organic growth for SaaS and landing pages. Use when optimizing for search engine ranking, improving Lighthouse scores, implementing SEO for Next.js pages, or planning content-driven growth.
|
|
4
4
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
color: pink
|
|
6
|
+
effort: medium
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# SEO Growth Hacker
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
name: standards-architect
|
|
3
3
|
description: Standards Architect (Tier 1 Orchestrator) that enforces MORPH-SPEC naming conventions, coding standards, and cross-cutting compliance across all outputs. Always active in MORPH-SPEC workflows. Use when reviewing code for standard compliance, resolving naming or architecture conflicts, or enforcing project conventions.
|
|
4
4
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
color: red
|
|
6
|
+
effort: high
|
|
7
|
+
permissionMode: acceptEdits
|
|
5
8
|
---
|
|
6
9
|
|
|
7
10
|
# Standards Architect
|
|
@@ -3,8 +3,11 @@ 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
|
|
9
|
+
color: yellow
|
|
10
|
+
effort: medium
|
|
8
11
|
---
|
|
9
12
|
|
|
10
13
|
# Agent Framework Expert
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: supabase-expert
|
|
3
|
+
description: Supabase & PostgreSQL specialist for RLS policies, auth integration, pgvector, Realtime subscriptions, Edge Functions, and migration management. Use when designing database schemas, implementing Row Level Security, setting up auth flows, or working with pgvector embeddings.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
stacks:
|
|
6
|
+
- supabase
|
|
7
|
+
color: teal
|
|
8
|
+
effort: medium
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Supabase & PostgreSQL Specialist
|
|
12
|
+
|
|
13
|
+
Expert in Supabase auth, Row Level Security, Realtime, Edge Functions, and pgvector.
|
|
14
|
+
|
|
15
|
+
> **Ref:** `framework/standards/infrastructure/supabase/` — RLS, auth, storage, pgvector standards
|
|
16
|
+
|
|
17
|
+
## Connection Pooling
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
# Direct connection (migrations only)
|
|
21
|
+
postgresql://postgres:[password]@db.[project].supabase.co:5432/postgres
|
|
22
|
+
|
|
23
|
+
# PgBouncer (application — ALWAYS use this)
|
|
24
|
+
postgresql://postgres.[project]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Rule:** Application code ALWAYS connects via PgBouncer (port 6543). Direct connections (port 5432) only for migrations and schema changes.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Row Level Security (RLS)
|
|
32
|
+
|
|
33
|
+
### Enable RLS on every table
|
|
34
|
+
|
|
35
|
+
```sql
|
|
36
|
+
ALTER TABLE public.documents ENABLE ROW LEVEL SECURITY;
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Common RLS Patterns
|
|
40
|
+
|
|
41
|
+
```sql
|
|
42
|
+
-- User owns the row
|
|
43
|
+
CREATE POLICY "Users can view own documents"
|
|
44
|
+
ON public.documents FOR SELECT
|
|
45
|
+
USING (auth.uid() = user_id);
|
|
46
|
+
|
|
47
|
+
-- User can insert own rows
|
|
48
|
+
CREATE POLICY "Users can insert own documents"
|
|
49
|
+
ON public.documents FOR INSERT
|
|
50
|
+
WITH CHECK (auth.uid() = user_id);
|
|
51
|
+
|
|
52
|
+
-- User can update own rows
|
|
53
|
+
CREATE POLICY "Users can update own documents"
|
|
54
|
+
ON public.documents FOR UPDATE
|
|
55
|
+
USING (auth.uid() = user_id)
|
|
56
|
+
WITH CHECK (auth.uid() = user_id);
|
|
57
|
+
|
|
58
|
+
-- User can delete own rows
|
|
59
|
+
CREATE POLICY "Users can delete own documents"
|
|
60
|
+
ON public.documents FOR DELETE
|
|
61
|
+
USING (auth.uid() = user_id);
|
|
62
|
+
|
|
63
|
+
-- Service role bypass (for backend API)
|
|
64
|
+
CREATE POLICY "Service role full access"
|
|
65
|
+
ON public.documents FOR ALL
|
|
66
|
+
USING (auth.role() = 'service_role');
|
|
67
|
+
|
|
68
|
+
-- Team-based access
|
|
69
|
+
CREATE POLICY "Team members can view"
|
|
70
|
+
ON public.documents FOR SELECT
|
|
71
|
+
USING (
|
|
72
|
+
team_id IN (
|
|
73
|
+
SELECT team_id FROM public.team_members
|
|
74
|
+
WHERE user_id = auth.uid()
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### RLS with Clerk JWT (custom claims)
|
|
80
|
+
|
|
81
|
+
```sql
|
|
82
|
+
-- Extract Clerk user ID from JWT
|
|
83
|
+
CREATE OR REPLACE FUNCTION auth.clerk_user_id()
|
|
84
|
+
RETURNS TEXT AS $$
|
|
85
|
+
SELECT coalesce(
|
|
86
|
+
current_setting('request.jwt.claims', true)::json->>'sub',
|
|
87
|
+
''
|
|
88
|
+
);
|
|
89
|
+
$$ LANGUAGE sql STABLE;
|
|
90
|
+
|
|
91
|
+
-- Use in RLS policies
|
|
92
|
+
CREATE POLICY "Clerk users own rows"
|
|
93
|
+
ON public.documents FOR ALL
|
|
94
|
+
USING (clerk_user_id = auth.clerk_user_id());
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Migrations
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Create new migration
|
|
103
|
+
npx supabase migration new create_documents_table
|
|
104
|
+
|
|
105
|
+
# Apply locally
|
|
106
|
+
npx supabase db reset
|
|
107
|
+
|
|
108
|
+
# Push to remote
|
|
109
|
+
npx supabase db push
|
|
110
|
+
|
|
111
|
+
# Diff local vs remote
|
|
112
|
+
npx supabase db diff --use-migra
|
|
113
|
+
|
|
114
|
+
# Lint for common issues
|
|
115
|
+
npx supabase db lint --level warning
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Migration file structure
|
|
119
|
+
|
|
120
|
+
```sql
|
|
121
|
+
-- supabase/migrations/20240101000000_create_documents_table.sql
|
|
122
|
+
|
|
123
|
+
CREATE TABLE public.documents (
|
|
124
|
+
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
125
|
+
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
126
|
+
title TEXT NOT NULL,
|
|
127
|
+
content TEXT,
|
|
128
|
+
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
|
129
|
+
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
-- Always enable RLS
|
|
133
|
+
ALTER TABLE public.documents ENABLE ROW LEVEL SECURITY;
|
|
134
|
+
|
|
135
|
+
-- Always add indexes for filtered columns
|
|
136
|
+
CREATE INDEX idx_documents_user_id ON public.documents(user_id);
|
|
137
|
+
CREATE INDEX idx_documents_created_at ON public.documents(created_at DESC);
|
|
138
|
+
|
|
139
|
+
-- RLS policies
|
|
140
|
+
CREATE POLICY "Users manage own documents"
|
|
141
|
+
ON public.documents FOR ALL
|
|
142
|
+
USING (auth.uid() = user_id)
|
|
143
|
+
WITH CHECK (auth.uid() = user_id);
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## pgvector (Embeddings)
|
|
149
|
+
|
|
150
|
+
### Setup
|
|
151
|
+
|
|
152
|
+
```sql
|
|
153
|
+
CREATE EXTENSION IF NOT EXISTS vector;
|
|
154
|
+
|
|
155
|
+
CREATE TABLE public.embeddings (
|
|
156
|
+
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
157
|
+
document_id UUID REFERENCES public.documents(id) ON DELETE CASCADE,
|
|
158
|
+
content TEXT NOT NULL,
|
|
159
|
+
embedding vector(1536) NOT NULL, -- OpenAI text-embedding-3-small
|
|
160
|
+
metadata JSONB DEFAULT '{}'::jsonb,
|
|
161
|
+
created_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
-- HNSW index for fast similarity search (cosine distance)
|
|
165
|
+
CREATE INDEX idx_embeddings_vector ON public.embeddings
|
|
166
|
+
USING hnsw (embedding vector_cosine_ops)
|
|
167
|
+
WITH (m = 16, ef_construction = 64);
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Similarity search function
|
|
171
|
+
|
|
172
|
+
```sql
|
|
173
|
+
CREATE OR REPLACE FUNCTION match_embeddings(
|
|
174
|
+
query_embedding vector(1536),
|
|
175
|
+
match_threshold FLOAT DEFAULT 0.78,
|
|
176
|
+
match_count INT DEFAULT 5
|
|
177
|
+
)
|
|
178
|
+
RETURNS TABLE (
|
|
179
|
+
id UUID,
|
|
180
|
+
content TEXT,
|
|
181
|
+
metadata JSONB,
|
|
182
|
+
similarity FLOAT
|
|
183
|
+
)
|
|
184
|
+
LANGUAGE plpgsql AS $$
|
|
185
|
+
BEGIN
|
|
186
|
+
RETURN QUERY
|
|
187
|
+
SELECT
|
|
188
|
+
e.id,
|
|
189
|
+
e.content,
|
|
190
|
+
e.metadata,
|
|
191
|
+
1 - (e.embedding <=> query_embedding) AS similarity
|
|
192
|
+
FROM public.embeddings e
|
|
193
|
+
WHERE 1 - (e.embedding <=> query_embedding) > match_threshold
|
|
194
|
+
ORDER BY e.embedding <=> query_embedding
|
|
195
|
+
LIMIT match_count;
|
|
196
|
+
END;
|
|
197
|
+
$$;
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Realtime Subscriptions
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
// Subscribe to changes on a table
|
|
206
|
+
const channel = supabase
|
|
207
|
+
.channel('documents-changes')
|
|
208
|
+
.on('postgres_changes',
|
|
209
|
+
{ event: '*', schema: 'public', table: 'documents', filter: `user_id=eq.${userId}` },
|
|
210
|
+
(payload) => {
|
|
211
|
+
console.log('Change:', payload.eventType, payload.new);
|
|
212
|
+
}
|
|
213
|
+
)
|
|
214
|
+
.subscribe();
|
|
215
|
+
|
|
216
|
+
// Cleanup
|
|
217
|
+
channel.unsubscribe();
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Rule:** Always filter subscriptions by user/team — never subscribe to full table changes.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Storage (File Uploads)
|
|
225
|
+
|
|
226
|
+
```sql
|
|
227
|
+
-- Create bucket
|
|
228
|
+
INSERT INTO storage.buckets (id, name, public)
|
|
229
|
+
VALUES ('avatars', 'avatars', true);
|
|
230
|
+
|
|
231
|
+
-- RLS for storage
|
|
232
|
+
CREATE POLICY "Users upload own avatar"
|
|
233
|
+
ON storage.objects FOR INSERT
|
|
234
|
+
WITH CHECK (
|
|
235
|
+
bucket_id = 'avatars' AND
|
|
236
|
+
auth.uid()::text = (storage.foldername(name))[1]
|
|
237
|
+
);
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Checklist
|
|
243
|
+
|
|
244
|
+
- [ ] PgBouncer (port 6543) used for all application connections
|
|
245
|
+
- [ ] RLS enabled on ALL public tables
|
|
246
|
+
- [ ] RLS policies cover SELECT, INSERT, UPDATE, DELETE
|
|
247
|
+
- [ ] Service role policy exists for backend API access
|
|
248
|
+
- [ ] Migrations use `npx supabase migration new` (not manual SQL)
|
|
249
|
+
- [ ] Indexes on all frequently filtered columns
|
|
250
|
+
- [ ] pgvector: HNSW index with appropriate m/ef_construction values
|
|
251
|
+
- [ ] Realtime subscriptions filtered by user/team
|
|
252
|
+
- [ ] Storage buckets have RLS policies
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
name: css-specialist
|
|
3
3
|
description: CSS & Design System Specialist for design token enforcement, naming conventions (BEM), WCAG contrast validation, and CSS architecture. Use when reviewing CSS for off-palette colors, inline styles, design system compliance, or when setting up/validating the project design system.
|
|
4
4
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
color: pink
|
|
6
|
+
effort: medium
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# CSS & Design System Specialist
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: ui-
|
|
2
|
+
name: ui-designer
|
|
3
3
|
description: UI/UX Designer specialist for wireframes, design systems, component specs, user flows, and design brief definition. Commits to a visual direction (aesthetic, palette, motion) BEFORE generating any output. Use for Phase 2 (UI/UX) and Phase 3 (spec) of features with frontend UI.
|
|
4
4
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
color: purple
|
|
6
|
+
effort: medium
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# UI/UX Designer
|